赞
踩
目录
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参数为期望的最终数量。
(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%。
至于双均线策略是否有用,小伙伴们还可多换些股票和时间区间来验证。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。