金融量化分析——双均线策略

目录

一、数据采集

二、提取有效数据

三、金叉、死叉分析

四、模拟实操

五、完整代码

六、未来展望


一、数据采集

1、首先安装Tushare:

pip install Tushare

2、使用Tushare接口,并导入所需的包:

import tushare as ts
import pandas as pd
import matplotlib as plt
import numpy as np
import mplfinance as mpf//绘制K线的包,本节没有用到

3、试着获取从2023-10-1到2023-11-1期间的茅台股票数据,:

df = pro.daily(ts_code='600519.SH', start_date='20231001', end_date='20231101')

4、将数据保存至CSV文件:

df.to_csv('600519data.csv',index=False)

二、提取有效数据

1、读取刚才保存的CSV文件,并选取所需数据:

df = pd.read_csv("600519data.csv",index_col='trade_date',parse_dates=['trade_date'])[['open','close','low','high']]

2、 由于所获得数据是时间倒序,所以需要按照时间标签正序排序

df = df.sort_index()

3、创建两列,并分别命名“ma5”和“ma30”,分别代表5日、30日均线的值:

df['ma5'] = np.nan
df['ma30'] = np.nan

for i in range(4,len(df)):
    df.loc[df.index[i],'ma5'] = df['close'][i-4:i+1].mean()

for i in range(29,len(df)):
    df.loc[df.index[i],'ma30'] = df['close'][i-29:i+1].mean()

也可使用另一种方法:

df['ma5'] = df['close'].rolling(5).mean
df['ma30'] = df['close'].rolling(30).mean

4、查看均线图:

df[['close','ma5','ma30']].plot()

三、金叉、死叉分析

1、创建两列数组,作为金叉和死叉:

若当日5日均线值大于等于30日均线值,并且前一日5日均线值小于30日均线值,则称交点为金叉.

若当日5日均线值小于等于30日均线值,并且前一日5日均线值大于30日均线值,则称交点为死叉.

golden_cross = []
death_cross = []
for i in range(1,len(df)):
    if df['ma5'][i]>=df['ma30'][i] and df['ma5'][i-1]<df['ma30'][i-1]:
        golden_cross.append(df.index[i])
    if df['ma5'][i]<=df['ma30'][i] and df['ma5'][i-1]>df['ma30'][i-1]:
        death_cross.append(df.index[i])

判定金叉、死叉另一种方法:

sr1 = df['ma5'] < df['ma30']
sr2 = df['ma5'] > df['ma30']
death_cross1 = df[sr1 & sr2.shift(1)].index
golden_cross1 = df[-(sr1 | sr2.shift(1))].index

左图为金叉,右图为死叉: 

四、模拟实操

        本文采取的双均线策略是选择5日和30日这两条移动平均线,当第一个金叉出现的时候买入,紧接着出现死叉的时候再卖出。

将两个存有金叉死叉数据的序列合并到一个序列sr里,

first_money = 100000
money = first_money
hold = 0 #持有多少股
sr1= pd.Series(1,index = golden_cross)
sr2 = pd.Series(0,index = death_cross)
sr = sr1._append(sr_death).sort_index()

for i in range(0,len(sr)):
    p =df['open'][sr.index[i]]
    if sr.iloc[i] == 1:
        #金叉
        buy = (money // (100 * p))
        hold += buy*100
        money -= buy*100*p
    else:
        money += hold *p
        hold = 0
p = df['open'][-1]
now_moeny = hold * p + money

print(now_moeny - first_money)

        结果显示,从2013年1月1日开始到2023年11月1日结束,在本金10w的情况下采取双均线策略,可以盈利1324734.0元,也就是132w+元。

五、完整代码

import tushare as ts
import pandas as pd
import matplotlib as plt
import numpy as np
import mplfinance as mpf

#读取数据
df = pd.read_csv("600519data.csv",index_col='trade_date',parse_dates=['trade_date'])[['open','close','low','high']]

#数据排序
df = df.sort_index()

#创建当日的5日和30日的均线值
df['ma5'] = np.nan
df['ma30'] = np.nan

for i in range(4,len(df)):
    df.loc[df.index[i],'ma5'] = df['close'][i-4:i+1].mean()

for i in range(29,len(df)):
    df.loc[df.index[i],'ma30'] = df['close'][i-29:i+1].mean()

#丢掉缺失数据
df = df.dropna()

#判断金叉、死叉
golden_cross = []
death_cross = []
for i in range(1,len(df)):
    if df['ma5'][i]>=df['ma30'][i] and df['ma5'][i-1]<df['ma30'][i-1]:
        golden_cross.append(df.index[i])
    if df['ma5'][i]<=df['ma30'][i] and df['ma5'][i-1]>df['ma30'][i-1]:
        death_cross.append(df.index[i])

#模拟实操
first_money = 100000
money = first_money
hold = 0 #持有多少股
sr1= pd.Series(1,index = golden_cross)
sr2 = pd.Series(0,index = death_cross)
sr = sr1._append(sr_death).sort_index()


for i in range(0,len(sr)):
    p =df['open'][sr.index[i]]
    if sr.iloc[i] == 1:
        #金叉
        buy = (money // (100 * p))
        hold += buy*100
        money -= buy*100*p
    else:
        money += hold *p
        hold = 0
p = df['open'][-1]
now_moeny = hold * p + money

print(now_moeny - first_money)

六、未来展望

        由于第二天才能知道昨天的收盘价,即使当天知道收盘价后也无法买入了,也就是说第二天才知道昨天是否有金叉死叉,所以实际操作中应该是后一天买入或者卖出。

        因此,在未来改进过程中可以将上述代码的p变量赋值第二天的开盘价格,以此来增加模拟策略的准确度。

七、拓展:利用聚宽金融量化交易平台

1、创建初始化函数

依旧选择贵州茅台股票,600519

# 初始化函数,设定基准等等
def initialize(context):
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    # 选取贵州茅台股票
    g.security = ['600519.XSHG']
    # 5日、60日
    g.p1 = 5
    g.p2 = 60

2、交易函数

(1)聚宽的attribute_history的函数:

一般只用前两个参数,第二个count参数为期望的最终数量。

  • count: 大于0的整数,表示获取bar的个数。如果行情数据的bar不足count个,返回的长度则小于count个数。

(2)账户信息函数

context.portfolio.positions,账户是否持仓。

context.portfolio.available_cash,账户鱼儿

(3)order_target函数,常用的依旧是前两个参数。

第二个参数可以填写账户金额,系数自动计算这些钱能买最大股票数。

def handle_data(context, data):
    for stock in g.security:
        # 金叉:如果5五日均线大于10日均线,并且不持仓
        # 死叉:如果5五日均线小于10日均线,并且持仓股票
        df = attribute_history(stock, g.p2)
        ma10 = df['close'].mean()
        ma5 = df['close'][-5:].mean()
        
        if ma10 > ma5 and stock in  context.portfolio.positions:
            # 死叉
            order_target(stock,0)
            
        if ma10 < ma5 and stock not in  context.portfolio.positions:
            # 金叉
            order_target(stock,context.portfolio.available_cash * 0.8)

3、完整代码

# 导入函数库
from jqdata import *

# 初始化函数,设定基准等等
def initialize(context):
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    # 选取贵州茅台股票
    g.security = ['600519.XSHG']
    # 5日、60日
    g.p1 = 5
    g.p2 = 60
## 开盘前运行函数
def handle_data(context, data):
    for stock in g.security:
        # 金叉:如果5五日均线大于10日均线,并且不持仓
        # 死叉:如果5五日均线小于10日均线,并且持仓股票
        df = attribute_history(stock, g.p2)
        ma10 = df['close'].mean()
        ma5 = df['close'][-5:].mean()
        
        if ma10 > ma5 and stock in  context.portfolio.positions:
            # 死叉
            order_target(stock,0)
            
        if ma10 < ma5 and stock not in  context.portfolio.positions:
            # 金叉
            order_target(stock,context.portfolio.available_cash * 0.8)

4、运行结果

时间选择的是2022-10-1至2023-10-1,可以看到一年时间收益4.46%。

至于双均线策略是否有用,小伙伴们还可多换些股票和时间区间来验证。

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个简单的均线策略的实现: 1. 策略思路: 均线策略是一种常见的趋势跟踪策略,它的核心思想是通过计算不同时间段的移动平均线来判断市场的趋势,并根据移动平均线之间的交叉信号进行买入或卖出操作。 2. 策略参数: 选择两条不同的移动平均线,一条是较短期的,一条是较长期的。例如,可以选择5日移动平均线和20日移动平均线。 3. 交易信号: 当短期移动平均线上穿长期移动平均线时,产生买入信号;当短期移动平均线下穿长期移动平均线时,产生卖出信号。 4. 代码实现: ```python import pandas as pd import yfinance as yf import matplotlib.pyplot as plt # 下载数据 data = yf.download('AAPL', start='2010-01-01', end='2021-01-01') # 计算5日移动平均线和20日移动平均线 data['MA5'] = data['Close'].rolling(window=5).mean() data['MA20'] = data['Close'].rolling(window=20).mean() # 计算交易信号 data['Signal'] = 0 data['Signal'][5:] = np.where(data['MA5'][5:] > data['MA20'][5:], 1, 0) data['Signal'][5:] = np.where(data['MA5'][5:] < data['MA20'][5:], -1, data['Signal'][5:]) # 计算每日收益率 data['Return'] = np.log(data['Close']/data['Close'].shift(1)) # 计算策略收益率 data['Strategy'] = data['Signal'].shift(1) * data['Return'] # 计算累计收益率 data['Cumulative_Return'] = np.cumsum(data['Strategy']) # 绘制图形 plt.plot(data['Cumulative_Return']) plt.xlabel('Date') plt.ylabel('Cumulative Return') plt.title('Dual Moving Average Strategy') plt.show() ``` 这里以苹果公司的股票价格为例,下载了2010年至2021年的日线数据,计算出了5日移动平均线和20日移动平均线,并根据交叉信号计算出了交易信号。最后计算出了策略的收益率,并绘制了累计收益率曲线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流离川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值