失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > python量化交易--择时策略

python量化交易--择时策略

时间:2024-06-02 05:50:54

相关推荐

python量化交易--择时策略

1.在banban网爬取所有A股的股票名称和代码。

观察板板网站的股票,将在深圳上市和上海上市的A股信息爬取并保存到本地文件

2.传入股票代码,利用tushare api提取股票的所有历史数据,对股票数据进行处理。

3.设置双均线,KDJ,MACD等指标辅助量化。

4.设置资金曲线,利用历史数据回测,评估策略效果。

如下是用双均线策略来进行买入卖出交易的模拟得到的预计资金曲线,短线取的时间是5个交易日,长线取的时间是20个交易日,选用的股票是000625 长安汽车:

可以看出我们的预计资金曲线是运用此策略买入的话,10000可以涨到19000的样子,看似还不错,但是当我们去和该支股票的波动率进行对比之后会大失所望:

总python运行的数据来看,长安汽车股价翻了接近5倍,而我们的双均线带来的收益连一倍都不到,所以针对长安汽车,双均线策略的策略数值MA_short=5&MA_long=20不适合,可循环遍历找出最适合该支股票的均线策略数值。

源代码如下:

源代码

import pandas as pdimport tushareimport datetimeimport numpy as npfrom lxml import htmlimport requestsimport reimport timeimport pymongoimport threadingimport mplfinance as mpfimport matplotlib.pyplot as pltimport talibimport matplotlibfrom pyecharts.charts import Gridfrom pyecharts import options as optsimport threadingimport queue#token='69eb8e86b28f824d35309a425404600978c064485417896a59667f66'#pro=tushare.pro_api(token)#data=pro.daily(ts_code='600010.SS',start_date='0101',end_date='0601')def zeshicelue(daihao,name):#tushare的api获取包钢股份的数据data=tushare.get_k_data(daihao,start='-1-1',end='')#end为空值取当前时间,start为空值取去年今日df=pd.DataFrame(data)#数据预处理df.index=pd.to_datetime(df['date'])df=df.drop(axis=1,columns='date')df['scope']=(df.close/df.open)-1#print(df[abs(df.scope)>=0.11])#不加df时是bool判断,加了df之后是输出df中为true的行#print(df[abs(df.scope)>=0.11].index)#[54,107,859,904,2232,2319]返回的是满足条件的index序列df=df.drop(df[abs(df.loc[:,'scope'])>0.12].index)#按index序列去drop该行数据#定义长短均线,买入卖出信号,仓位信息等ma_short=5ma_long=20df['ma_short']=df['close'].rolling(ma_short,min_periods=1).mean()df['ma_long']=df['close'].rolling(ma_long,min_periods=1).mean()df['ma_short-1']=df['close'].shift(1).rolling(ma_short,min_periods=1).mean()df['ma_long-1']=df['close'].shift(1).rolling(ma_long,min_periods=1).mean()condition1=df['ma_short']-df['ma_long']#当天的短期均线与长期均线的差值condition2=df['ma_short-1']-df['ma_long-1']#上个交易日的短期均线与上个交易日的长期均线的差值df.loc[(condition1>=0)&(condition2<=0),'B|S']=1#买入信号df.loc[(condition1<0)&(condition2>0),'B|S']=0#卖出信号#初始仓位管理df['pos']=df['B|S'].shift(1)#初始化仓位信息#计算ATR值df['ATR14']=talib.ATR(df['high'].values,df['low'].values,df['close'].values,timeperiod=14)df['ATR14'].fillna(method='bfill',inplace=True)# 止盈止损#初始化变量rate1=5/10000#买卖时的手续费rate2=1/1000#卖时的印花税slippage=0.01#买卖时的价格滑点zhangting=(df['open'])-(df['close'].shift(1)*1.097)#开盘即涨停df.loc[zhangting>0,'pos']=np.nandieting=(df['open'])-(df['close'].shift(1)*0.9)#开盘即跌停df.loc[dieting<=0,'pos']=np.nandf['pos'].fillna(method='ffill',inplace=True)#将不能变化和nan的仓位设置为上个仓位的值#print(df.loc[(df['B|S']==1)|(df['B|S']==0)])money_start=10000#定义初始资金1万元#定义资金状况变化df.loc[df.index[0],'hold_num']=0#初始化持股数为0df.loc[df.index[0],'money']=money_start#初始化剩余的钱总数df.loc[df.index[0],'property']=money_start#初始化总资产df['money'].fillna(method='ffill',inplace=True)df['property'].fillna(method='ffill',inplace=True)df['pos'].fillna(0,inplace=True)for i in range(1,df.shape[0]):if df.loc[df.index[i],'pos']>df.loc[df.index[i-1],'pos']:#仓位不够,加仓买入df.loc[df.index[i],'hold_num']=(df.loc[df.index[i],'pos'])*(df.loc[df.index[i-1],'property'])/(df.loc[df.index[i],'open']+slippage)//100*100if (df.loc[df.index[i],'money']<((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage))):#加仓的钱不够df.loc[df.index[i],'hold_num']=df.loc[df.index[i],'hold_num']-100#钱不够,自动少买1手if ((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)>=5:#手续费超过5块df.loc[df.index[i],'money']=df.loc[df.index[i-1],'property']-((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*(1-rate1))df.loc[df.index[i],'shouxufei']=((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)else:df.loc[df.index[i],'money'] = df.loc[df.index[i-1],'property'] - ((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage))-5#开盘就买df.loc[df.index[i],'shouxufei']=5else:df.loc[df.index[i],'hold_num']=df.loc[df.index[i],'hold_num']if ((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)>=5:#手续费超过5块df.loc[df.index[i],'money']=df.loc[df.index[i-1],'property']-((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*(1-rate1))df.loc[df.index[i],'shouxufei']=((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)else:df.loc[df.index[i],'money'] = df.loc[df.index[i-1],'property'] - ((df.loc[df.index[i],'hold_num']-df.loc[df.index[i-1],'hold_num'])*(df.loc[df.index[i],'open']+slippage))-5#开盘就买df.loc[df.index[i],'shouxufei']=5df.loc[df.index[i],'property']=df.loc[df.index[i],'money']+(df.loc[df.index[i],'hold_num']*df.loc[df.index[i],'close'])#算资产时用收盘价if df.loc[df.index[i],'pos']==df.loc[df.index[i-1],'pos']:#仓位不变df.loc[df.index[i],'hold_num']=df.loc[df.index[i-1],'hold_num']df.loc[df.index[i],'money']=df.loc[df.index[i-1],'money']df.loc[df.index[i],'property']=df.loc[df.index[i],'money']+(df.loc[df.index[i],'hold_num']*df.loc[df.index[i],'close'])df.loc[df.index[i],'shouxufei']=0if df.loc[df.index[i],'pos']<df.loc[df.index[i-1],'pos']:#仓位过多,减仓卖出if df.loc[df.index[i],'pos']!=0:df.loc[df.index[i],'hold_num']=df.loc[df.index[i-1],'property']*df.loc[df.index[i],'pos']/df.loc[df.index[i],'open']//100*100if ((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)>=5:#手续费超过5块df.loc[df.index[i],'money']=df.loc[df.index[i-1],'money']+((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']-slippage)*(1-rate1)*(1-rate2))#开盘就卖,卖出加印花税df.loc[df.index[i],'shouxufei']=((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)+(df.loc[df.index[i],'hold_num']*(df.loc[df.index[i],'open']-slippage)*rate2)else:df.loc[df.index[i],'money']=df.loc[df.index[i-1],'money']+((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']-slippage)*(1-rate2))-5df.loc[df.index[i],'shouxufei']=5+((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']-slippage)*rate2)df.loc[df.index[i],'property']=df.loc[df.index[i-1],'money']+(df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*df.loc[df.index[i],'close']#算资产时用收盘价else:df.loc[df.index[i],'hold_num']=df.loc[df.index[i-1],'property']*df.loc[df.index[i],'pos']/df.loc[df.index[i],'open']//100*100if ((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)>=5:#手续费超过5块df.loc[df.index[i],'money']=df.loc[df.index[i-1],'money']+((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']-slippage)*(1-rate1)*(1-rate2)) # 开盘就卖,卖出加印花税df.loc[df.index[i],'shouxufei']=((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']+slippage)*rate1)+(df.loc[df.index[i],'hold_num']*(df.loc[df.index[i],'open']-slippage)*rate2)else:df.loc[df.index[i],'money']=df.loc[df.index[i-1],'money']+((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']-slippage)*(1-rate2))-5df.loc[df.index[i],'shouxufei']=5+((df.loc[df.index[i-1],'hold_num']-df.loc[df.index[i],'hold_num'])*(df.loc[df.index[i],'open']-slippage)*rate2)df.loc[df.index[i],'property']=df.loc[df.index[i],'money']#hold_num=0时,资产和money现金相等#print(df['money'],df['property'],df['hold_num'])#df['hold_num']=(money_start*df['pos']/df['open'])//100#持股总数#df['money']=money_start-df['open']*df['hold_num']#剩余的钱总数#df['property']=df['hold_num']*df['close']+df['money']#总资产#df.iloc[0].loc['money']=10000#print(df)#跳空缺口threshold=10#缺口阈值jump_power1=(df['low']-df['high'].shift(1))/threshold#向上跳空jump_power2=(df['high']-df['low'].shift(1))/threshold#向下跳空df.loc[(jump_power1>=1),'th']=1df.loc[(jump_power2<=-1),'th']=-1#观察区间c1=1900c2=2000#画蜡烛图#日Kmpf.plot(df.iloc[c1:c2,],type='candle',mav=(3,6,9),volume=True)#画蜡烛图,颜色改变不了,白涨黑跌#周Kopen=df.iloc[c1:c2]['open'].resample('W-FRI',closed='right',label='right').first()close=df.iloc[c1:c2]['close'].resample('W-FRI',closed='right',label='right').last()high=df.iloc[c1:c2]['high'].resample('W-FRI',closed='right',label='right').max()low=df.iloc[c1:c2]['low'].resample('W-FRI',closed='right',label='right').min()volume=df.iloc[c1:c2]['volume'].resample('W-FRI',closed='right',label='right').sum()dict={'open':open,'high':high,'low':low,'close':close,'volume':volume}df2=pd.DataFrame(dict)df2=df2.dropna(how='any')#print(df2)mpf.plot(df2,type='candle',volume=True)#KDJlow_list=df['low'].rolling(9,min_periods=1).min()high_list=df['high'].rolling(9,min_periods=1).max()RSV=(df['close']-low_list)/(high_list-low_list)*100#根据RSV值的大小可判断市场的超买超卖现象,大超买,小超卖df['K']=RSV.ewm(com=2,adjust=False).mean()df['D']=df['K'].ewm(com=2,adjust=False).mean()df['J']=3*df['K']-2*df['D']#MACDEMA12=df['close'].ewm(span=12,adjust=False).mean()EMA26=df['close'].ewm(span=26,adjust=False).mean()df['MACD_DIF']=EMA12-EMA26df['MACD_DEA']=df['MACD_DIF'].ewm(span=9,adjust=False).mean()df['MACD']=2*(df['MACD_DIF']-df['MACD_DEA'])#print(df['MACD'])#画均线图plt.subplot(221)#print(df.columns.values.tolist())#print(df.iloc[:,9].keys)plt.rcParams['font.sans-serif']='SimHei'#必须设置中文字体格式,不然图例显示不出来,只能作用到单一类图上,两类图的话需要再定义一遍plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['ma_short'],label='短期均线')plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['ma_long'],label='长期均线')#print(df.iloc[c1:c2].loc[df.iloc[c1:c2]['B|S']==0])dict={'facecolor':'black','shrink':0.05}plt.annotate('死叉',df.iloc[c1:c2].loc[df.iloc[c1:c2]['B|S']==0.0].index,df.iloc[c1:c2].loc[df.iloc[c1:c2]['B|S']==0.0]['ma_short'])plt.legend()plt.xticks(rotation=45)#旋转横坐标标签45度#画KDJ线图plt.subplot(222)plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['K'],label='K值线')plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['D'],label='D值线')plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['J'],label='J值线')plt.legend()plt.xticks(rotation=45)#旋转横坐标标签45度#K值线对应均线中的短线,D值线对应均线中的长线,K值线从下上穿D值线时,买入信号;反之则反#画MACD图plt.subplot(223)plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['MACD'],label='MACD')plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['MACD_DIF'],label='MACD_DIF')plt.plot(df.iloc[c1:c2].index,df.iloc[c1:c2]['MACD_DEA'],label='MACD_DEA')bar_red=np.where(df.iloc[c1:c2]['MACD']>0,df.iloc[c1:c2]['MACD'],0)bar_green=np.where(df.iloc[c1:c2]['MACD']<0,df.iloc[c1:c2]['MACD'],0)plt.bar(df.iloc[c1:c2].index,bar_red,facecolor='red',label='hist bar')plt.bar(df.iloc[c1:c2].index,bar_green,facecolor='green',label='hist bar')plt.legend()plt.xticks(rotation=45)#旋转横坐标标签45度#print(df.loc[:,'date'])#print(df['pos'])#print(df['money'])#MACD_DIF线对应短线,MACD_DEA线对应长线,当MACD_DIF线从下上穿MACD_DEA线时,买入信号;反之则反#画资金曲线图plt.subplot(224)plt.plot(df.index,df['property'],label='资金曲线')plt.xticks(rotation=45)plt.legend()plt.show()shouxufei_sum=0for s in range(df.shape[0]):df['shouxufei'].fillna(0,inplace=True)shouxufei_sum=shouxufei_sum+df.loc[df.index[s],'shouxufei']shouxufei_sum=round(shouxufei_sum,3)#手续费保留3位小数print('手续费花费金额:',shouxufei_sum)surge_price_rate=(df.loc[df.index[-1],'close']-df.loc[df.index[0],'open'])/df.loc[df.index[0],'open']#股价从开盘到目前的波动率print('{}股票从开盘到现在的波动价格率:'.format(name),surge_price_rate)surge_money_rate=(df.loc[df.index[-1],'property']-df.loc[df.index[0],'property'])/df.loc[df.index[0],'property']print('{}股票从开盘到现在的投资资金波动率:'.format(name),surge_money_rate)if surge_price_rate>surge_money_rate:print('均线策略系数对此股不合适,没有跑赢大盘,需调整系数')else:print('均线策略系数对此股合适,跑赢了大盘')df.to_csv(r'D:\A股择时策略结果文档\{}.csv'.format(name),mode='w',encoding='utf-8')print('{}股票策略分析完成'.format(name))#grid=Grid()#grid.add(bar1,grid_opts=opts.GridOpts(pos_left="3%", pos_right="1%", height="20%"))#grid.add(bar2,grid_opts=opts.GridOpts(pos_left="3%", pos_right="1%", height="30%",pos_top="50%"))#爬虫股票信息,传回择时函数中def getcode(url):#url='/gupiao/list_sz.html'headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36'}response=requests.get(url,headers=headers).contentetree1=html.etree.HTML(response)name_list=[]daihao_list=[]for d in range(1,1483):try:etree2=etree1.xpath('//*[@id="ctrlfscont"]/ul/li[{}]/a/text()'.format(d))name=re.search(r'[\u4e00-\u9fa5]+',str(etree2)).group(0)daihao=re.search(r'\d+',str(etree2)).group(0)name_list.append(name)daihao_list.append(daihao)#gupiao1=zeshicelue(daihao,name)print('第{}支股票完成'.format(d))except:print('网络错误,重试中,请稍候!')d=d-1dict={'name':name_list,'code':daihao_list}dataframe=pd.DataFrame(dict)dataframe.to_csv(r'C:\Users\asus\Desktop\股票代码.csv',mode='ab')url1='/gupiao/list_sz.html'#深圳上市股票url2='/gupiao/list_sh.html'#上海上市股票url_list=[url1,url2]for i in range(2):if i==0:print('爬取深圳上市股票中')#getcode1=getcode(url_list[i])else:print('爬取上海上市股票中')#getcode1=getcode(url_list[i])#t=threading.Thread(target=getcode,args=(url_list[i],))#t.start()dataframe2=pd.read_csv(r'C:\Users\asus\Desktop\股票代码.csv')starttime=time.time()#print(dataframe2.name)for i in range(dataframe2.shape[0]):name=dataframe2.name[i]daihao=str(dataframe2.code[i])#excel表格的0开头数字会自动省略,如下处理if len(daihao)==1:daihao='00000'+str(daihao)if len(daihao)==2:daihao='0000'+str(daihao)if len(daihao)==3:daihao='000'+str(daihao)if len(daihao)==4:daihao='00'+str(daihao)if len(daihao)==5:daihao='0'+str(daihao)if len(daihao)==6:daihao=daihao#print(daihao)#zeshicelue1=zeshicelue(daihao,name)zeshicelue2=zeshicelue('000625','长安汽车')endtime=time.time()print('总计时长:',endtime-starttime)print('运行完成')

如果觉得《python量化交易--择时策略》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。