700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【量化笔记】均线交易策略

【量化笔记】均线交易策略

时间:2023-12-02 03:39:45

相关推荐

【量化笔记】均线交易策略

简单移动平均数

简单求过去5天的价格平均数

S M A t = 5 = p 1 + p 2 + p 3 + p 4 + p 5 5 SMA_{t=5}=\frac{p_1+p_2+p_3+p_4+p_5}{5} SMAt=5​=5p1​+p2​+p3​+p4​+p5​​

#计算青岛啤酒的5日简单移动平均线import pandas as pdimport numpy as npimport matplotlib.pyplot as pltTsingTao=pd.read_csv('TsingTao.csv')TsingTao.index=TsingTao.iloc[:,1]TsingTao.index=pd.to_datetime(TsingTao.index, format='%Y-%m-%d')TsingTao=TsingTao.iloc[:,2:]TsingTao.head(n=3)

Close=TsingTao.Close

plt.rcParams['font.sans-serif'] = ['SimHei']plt.plot(Close,'k')plt.xlabel('date')plt.ylabel('Close')plt.title('青岛啤酒股票收盘价时序图')

/Users/yaochenli/anaconda3/lib/python3.7/site-packages/pandas/plotting/_converter.py:129: FutureWarning: Using an implicitly registered datetime converter for a matplotlib plotting method. The converter was registered by pandas on import. Future versions of pandas will require you to explicitly register matplotlib converters.To register the converters:>>> from pandas.plotting import register_matplotlib_converters>>> register_matplotlib_converters()warnings.warn(msg, FutureWarning)Text(0.5, 1.0, '青岛啤酒股票收盘价时序图')/Users/yaochenli/anaconda3/lib/python3.7/site-packages/matplotlib/font_manager.py:1241: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans.(prop.get_family(), self.defaultFamily[fontext]))

Sma5=pd.Series(0.0,index=Close.index)

for i in range(4,len(Close)):Sma5[i]=np.mean(Close[(i-4):(i+1)])Sma5.tail()

Date-04-24 46.522-04-27 46.462-04-28 45.936-04-29 45.430-04-30 44.950dtype: float64

plt.plot(Close[4:],label="Close",color='g')plt.plot(Sma5[4:],label="Sma5",color='r',linestyle='dashed')plt.title("青岛啤酒股票价格图")plt.ylim(35,50)plt.legend()

<matplotlib.legend.Legend at 0x12242bef0>

封装成函数,包含一个参数表示几期平均数

def smaCal(tsPrice,k):import pandas as pdSma=pd.Series(0.0,index=tsPrice.index)for i in range(k-1,len(tsPrice)):Sma[i]=sum(tsPrice[(i-k+1):(i+1)])/kreturn(Sma)

sma5=smaCal(Close ,5) sma5.tail()

Date-04-24 46.522-04-27 46.462-04-28 45.936-04-29 45.430-04-30 44.950dtype: float64

加权平均移动

W M A t = 5 = w 1 p 1 + w 2 p 2 + w 3 p 3 + w 4 p 4 + w 5 p 5 WMA_{t=5}=w_1p_1+w_2 p_2+w_3 p_3+w_4 p_4 + w_5 p_5 WMAt=5​=w1​p1​+w2​p2​+w3​p3​+w4​p4​+w5​p5​

# 定义权重b=np.array([1,2,3,4,5])w=b/sum(b)w

array([0.06666667, 0.13333333, 0.2 , 0.26666667, 0.33333333])

#计算加权平均移动Wma5=pd.Series(0.0,index=Close.index)for i in range(4,len(Close)):Wma5[i]=sum(w*Close[(i-4):(i+1)])Wma5[2:7]

Date-01-060.000000-01-070.000000-01-08 46.778667-01-09 46.250667-01-10 45.710667dtype: float64

plt.rcParams['font.sans-serif'] = ['SimHei']plt.plot(Close[4:],label="Close",color='g')plt.plot(Wma5[4:],label="Wma5",color='r',linestyle='dashed')plt.title("青岛啤酒收盘价加权移动平均线")plt.ylim(35,50)plt.legend()

<matplotlib.legend.Legend at 0x12252c780>

封装成函数

def wmaCal(tsPrice,weight):import pandas as pdimport numpy as npk=len(weight)arrWeight=np.array(weight)Wma=pd.Series(0.0,index=tsPrice.index)for i in range(k-1,len(tsPrice.index)):Wma[i]=sum(arrWeight*tsPrice[(i-k+1):(i+1)])return(Wma)

wma5=wmaCal(Close,w) wma5.head()

Date-01-020.000000-01-030.000000-01-060.000000-01-070.000000-01-08 46.778667dtype: float64

wma5=wmaCal(Close,[0.1,0.15,0.2,0.25,0.3])wma5.tail()

Date-04-24 46.4585-04-27 46.3580-04-28 45.6385-04-29 45.1405-04-30 44.6605dtype: float64

指数加权移动平均

指数加权平均指的是将上一期的移动平均指数与本期的股价进行加权平均

t<=k时 E W M A t = p 1 + p 2 + . . . + p t t EWMA_{t}=\frac{p_1+p_2+...+p_t}{t} EWMAt​=tp1​+p2​+...+pt​​

t>=k+1时 E W M A t = p t ∗ α + E W M A t − 1 ∗ ( 1 − α ) EWMA_{t}=p_{t}*\alpha + EWMA_{t-1}*(1-\alpha) EWMAt​=pt​∗α+EWMAt−1​∗(1−α)

Ema5_number1=np.mean(Close[0:5])Ema5_number2=0.2* Close[5]+(1-0.2)*Ema5_number1Ema5=pd.Series(0.0,index=Close.index)Ema5[4]=Ema5_number1Ema5[5]=Ema5_number2

for i in range(6,len(Close)):expo=np.array(sorted(range(i-4),reverse=True))w=(1-0.2)**expoEma5[i]=sum(0.2*w*Close[5:(i+1)])+Ema5_number1*0.2**(i-5)

Ema5.tail()

Date-04-24 46.283839-04-27 46.263071-04-28 45.832457-04-29 45.555965-04-30 45.242772dtype: float64

plt.rcParams['font.sans-serif'] = ['SimHei']plt.plot(Close[4:],label="Close",color='k')plt.plot(Ema5[4:],label="Ema5",\color='g',linestyle='-.')plt.title("青岛啤酒收盘价指数移动平均线")plt.ylim(35,50)plt.legend()

<matplotlib.legend.Legend at 0x1226b7e10>

封装成函数

def ewmaCal(tsprice,period=5,exponential=0.2):import pandas as pdimport numpy as npEwma=pd.Series(0.0,index=tsprice.index)Ewma[period-1]=np.mean(tsprice[:period])for i in range(period,len(tsprice)):Ewma[i]=exponential*tsprice[i]+(1-exponential)*Ewma[i-1]return(Ewma)

Ewma=ewmaCal(Close,5,0.2)Ewma.head()

Date-01-020.000-01-030.000-01-060.000-01-070.000-01-08 47.024dtype: float64

中国银行股价均线分析

ChinaBank=pd.read_csv('ChinaBank.csv')ChinaBank.index=ChinaBank.iloc[:,1]ChinaBank.index=pd.to_datetime(ChinaBank.index, format='%Y-%m-%d')ChinaBank=ChinaBank.iloc[:,2:]

CBClose=ChinaBank.CloseCBClose.describe()

count 345.000000mean 3.145739std 0.775868min 2.45000025% 2.60000050% 2.70000075% 3.890000max 5.060000Name: Close, dtype: float64

Close15=CBClose['']

#10日简单移动平均Sma10=smaCal(Close15,10)Sma10.tail(n=3)

Date-04-28 4.815-04-29 4.841-04-30 4.845dtype: float64

#10日加权移动平均weight=np.array(range(1,11))/sum(range(1,11))Wma10=wmaCal(Close15,weight)Wma10.tail(n=3)

Date-04-28 4.834364-04-29 4.862545-04-30 4.862364dtype: float64

#10日指数移动平均expo= 2/(len(Close15)+1)Ema10=ewmaCal(Close15,10,expo)Ema10.tail(n=3)

Date-04-28 4.427053-04-29 4.439534-04-30 4.448741dtype: float64

plt.rcParams['font.sans-serif'] = ['SimHei']plt.plot(Close15[10:],label="Close",color='k')plt.plot(Sma10[10:],label="Sma10",color='r',linestyle='dashed')plt.plot(Wma10[10:],label="Wma10",color='b',linestyle=':')plt.plot(Ema10[10:],label="Ema10",color='G',linestyle='-.')plt.title("中国银行价格均线")plt.ylim(3.5,5.5)plt.legend()

<matplotlib.legend.Legend at 0x122a619e8>

均线时间跨度

Sma5=smaCal(Close15,5)Sma30=smaCal(Close15,30)plt.rcParams['font.sans-serif'] = ['SimHei']plt.plot(Close15[30:],label="Close",color='k')plt.plot(Sma5[30:],label="Sma5",color='b',linestyle='dashed')plt.plot(Sma30[30:],label="Sma30",color='r',linestyle=':')plt.title("中国银行股票价格的长短期均线")plt.ylim(3.5,5.5)plt.legend()

<matplotlib.legend.Legend at 0x122b4d0b8>

均线交易系统策略

如果股价上穿均线,说明有比较强的上涨趋势,反之下穿均线说明有比较强的下跌趋势

CBSma10=smaCal(CBClose,10)

SmaSignal=pd.Series(0,index=CBClose.index)for i in range(10,len(CBClose)):if all([CBClose[i]>CBSma10[i],CBClose[i-1]<CBSma10[i-1]]):SmaSignal[i]=1;elif all([CBClose[i]<CBSma10[i],CBClose[i-1]>CBSma10[i-1]]):SmaSignal[i]=-1;

SmaTrade=SmaSignal.shift(1).dropna()SmaTrade.head(n=3)

Date-01-03 0.0-01-06 0.0-01-07 0.0dtype: float64

SmaBuy=SmaTrade[SmaTrade==1]SmaBuy.head(n=3)

Date-01-23 1.0-01-29 1.0-02-11 1.0dtype: float64

SmaSell=SmaTrade[SmaTrade==-1]SmaSell.head(n=3)

Date-01-24 -1.0-02-10 -1.0-02-25 -1.0dtype: float64

CBRet=CBClose/CBClose.shift(1)-1SmaRet=(CBRet*SmaTrade).dropna()

cumStock=np.cumprod(1+CBRet[SmaRet.index[0]:])-1cumTrade=np.cumprod(1+SmaRet)-1cumdata=pd.DataFrame({'cumTrade':cumTrade,\'cumStock':cumStock})cumdata.iloc[-6:,:]

plt.plot(cumStock,label="cumStock",color='k')plt.plot(cumTrade,label="cumTrade",color='r',linestyle=':')plt.title("股票本身与均线交易的累积收益率")plt.legend()

<matplotlib.legend.Legend at 0x122c6c2b0>

# 计算胜率SmaRet[SmaRet==(-0)]=0smaWinrate=len(SmaRet[SmaRet>0])/len(SmaRet[SmaRet!=0])smaWinrate

0.3157894736842105

可以看到只用简单均线突破策略收益率和胜率都较低

双均线交叉捕捉中国银行股票买卖点

短期均线从下上穿长期均线时释放买入信号,短期均线从上下穿长期均线时释放卖出信号

#short and longSsma5=smaCal(CBClose,5);Lsma30=smaCal(CBClose,30);

SLSignal=pd.Series(0,index=Lsma30.index)for i in range(1,len(Lsma30)):if all([Ssma5[i]>Lsma30[i],Ssma5[i-1]<Lsma30[i-1]]):SLSignal[i]=1elif all([Ssma5[i]<Lsma30[i],Ssma5[i-1]>Lsma30[i-1]]):SLSignal[i]=-1

SLSignal[SLSignal==1]SLSignal[SLSignal==-1]

Date-03-03 -1-05-02 -1-06-27 -1-08-29 -1-09-23 -1-10-08 -1-02-03 -1dtype: int64

SLTrade=SLSignal.shift(1)

Long=pd.Series(0,index=Lsma30.index)Long[SLTrade==1]=1CBRet=CBClose/CBClose.shift(1)-1LongRet=(Long*CBRet).dropna()winLrate=len(LongRet[LongRet>0])/len(LongRet[LongRet!= 0] )winLrate

0.5

Short= pd.Series(0,index=Lsma30.index)Short[SLTrade==-1]=-1ShortRet=(Short*CBRet).dropna()winSrate=len(ShortRet[ShortRet>0])/len(ShortRet[ShortRet!=0])winSrate

0.4

SLtradeRet=(SLTrade*CBRet).dropna()winRate= len(SLtradeRet[ SLtradeRet>0])/len(\SLtradeRet[SLtradeRet!=0])winRate

0.4444444444444444

cumLong=np.cumprod(1+LongRet)-1cumShort=np.cumprod(1+ShortRet)-1cumSLtrade=np.cumprod(1+SLtradeRet)-1

plt.rcParams['axes.unicode_minus'] = Falseplt.plot(cumSLtrade,label="cumSLtrade",color='k')plt.plot(cumLong, label="cumLongtrade",\color='b',linestyle='dashed')plt.plot(cumShort,label="cumShorttrade",\color='r',linestyle=':')plt.title("长短期均线交易累计收益率")plt.legend(loc='best')

<matplotlib.legend.Legend at 0x122d85dd8>

异同移动平均线 MACD

MACD的求值过程

1.计算离差值 DIF

D I F = E M A ( c l o s e , 12 ) − E M A ( c l o s e , 26 ) DIF=EMA_{(close,12)}-EMA_{(close,26)} DIF=EMA(close,12)​−EMA(close,26)​

2.计算离差值的9日指数移动平均值

D E A = E M A ( D I F , 9 ) DEA=EMA_{(DIF,9)} DEA=EMA(DIF,9)​

3. 计算MACD

M A C D = D I F − D E A MACD=DIF-DEA MACD=DIF−DEA

#MACDDIF=ewmaCal(CBClose,12,2/(1+12))\-ewmaCal(CBClose,26,2/(1+26))DIF.tail(n=3)

Date-04-28 0.150903-04-29 0.155585-04-30 0.147109dtype: float64

DEA=ewmaCal(DIF,9,2/(1+9))DEA.tail()

Date-04-24 0.133966-04-27 0.133887-04-28 0.137290-04-29 0.140949-04-30 0.142181dtype: float64

MACD=DIF-DEAMACD.tail(n=3)

Date-04-28 0.013613-04-29 0.014636-04-30 0.004928dtype: float64

plt.rcParams['font.sans-serif'] = ['SimHei']plt.subplot(211)plt.plot(DIF[''],\label="DIF",color='k')plt.plot(DEA[''], label="DEA",\color='b',linestyle='dashed')plt.title("信号线DIF与DEA")plt.legend()plt.subplot(212)plt.bar(x=MACD[''].index,\height=MACD[''],\label='MACD',color='r')plt.legend()

<matplotlib.legend.Legend at 0x1232f2f60>

macddata=pd.DataFrame()macddata['DIF']= DIF['']macddata['DEA']= DEA['']macddata['MACD']= MACD['']

import pandas as pdimport matplotlib.pyplot as pltfrom matplotlib.dates import DateFormatter, WeekdayLocator,\DayLocator, MONDAY,date2num#from matplotlib.finance import candlestick_ohlcfrom mpl_finance import candlestick_ohlcimport numpy as np#蜡烛图与线图def candleLinePlots(candleData, candleTitle='a', **kwargs):Date = [date2num(date) for date in candleData.index]candleData.loc[:,'Date'] = DatelistData = []for i in range(len(candleData)):a = [candleData.Date[i],\candleData.Open[i],candleData.High[i],\candleData.Low[i],candleData.Close[i]]listData.append(a)# 如 果 不 定 长 参 数 无 取 值 , 只 画 蜡 烛 图ax = plt.subplot()# 如 果 不 定 长 参 数 有 值 , 则 分 成 两 个 子 图flag=0if kwargs:if kwargs['splitFigures']:ax = plt.subplot(211)ax2= plt.subplot(212)flag=1;# 如 果 无 参 数 splitFigures , 则 只 画 一 个 图 形 框# 如 果 有 参 数 splitFigures , 则 画 出 两 个 图 形 框for key in kwargs:if key=='title':ax2.set_title(kwargs[key])if key=='ylabel':ax2.set_ylabel(kwargs[key])if key=='grid':ax2.grid(kwargs[key])if key=='Data':plt.sca(ax)if flag:plt.sca(ax2)#一维数据if kwargs[key].ndim==1:plt.plot(kwargs[key],\color='k',\label=kwargs[key].name)plt.legend(loc='best')#二维数据有两个columnselif all([kwargs[key].ndim==2,\len(kwargs[key].columns)==2]):plt.plot(kwargs[key].iloc[:,0], color='k', label=kwargs[key].iloc[:,0].name)plt.plot(kwargs[key].iloc[:,1],\linestyle='dashed',\label=kwargs[key].iloc[:,1].name)plt.legend(loc='best')elif all([kwargs[key].ndim==2,\len(kwargs[key].columns)==3]):plt.plot(kwargs[key].iloc[:,0], color='k', label=kwargs[key].iloc[:,0].name)plt.plot(kwargs[key].iloc[:,1],\linestyle='dashed',\label=kwargs[key].iloc[:,1].name)plt.bar(x=kwargs[key].index,\height=kwargs[key].iloc[:,2],\label=kwargs[key].iloc[:,2].name,color='r')plt.legend(loc='best')mondays = WeekdayLocator(MONDAY)weekFormatter = DateFormatter('%y %b %d')ax.xaxis.set_major_locator(mondays)ax.xaxis.set_minor_locator(DayLocator())ax.xaxis.set_major_formatter(weekFormatter)plt.sca(ax)candlestick_ohlc(ax,listData, width=0.7,\colorup='r',colordown='g')ax.set_title(candleTitle)plt.setp(ax.get_xticklabels(),\rotation=20,\horizontalalignment='center')ax.autoscale_view()return(plt.show())candleLinePlots(ChinaBank[''],\candleTitle='中国银行日K线图',\splitFigures=True,Data=macddata,\ylabel='MACD')

使用MACD制定策略

DIF,DEA均为正, DIF向上突破DEA,买入信号

DIF,DEA均为负, DIF向下突破DEA,卖出信号

macdSignal=pd.Series(0,index=DIF.index)for i in range(1,len(DIF)):if all([DIF[i]>DEA[i]>0.0,DIF[i-1]<DEA[i-1]]):macdSignal[i]=1elif all([DIF[i]<DEA[i]<0.0,DIF[i-1]>DEA[i-1]]):macdSignal[i]=-1macdSignal.tail()

Date-04-24 0-04-27 0-04-28 1-04-29 0-04-30 0dtype: int64

macdTrade=macdSignal.shift(1)

CBRet=CBClose/CBClose.shift(1)-1macdRet=(CBRet*macdTrade).dropna()macdRet[macdRet==-0]=0macdWinRate=len(macdRet[macdRet>0])/len(macdRet[macdRet!=0])macdWinRate

0.5

多种均线策略运用实测

AllSignal=SmaSignal+SLSignal+macdSignalfor i in AllSignal.index:if AllSignal[i]>1:AllSignal[i]=1elif AllSignal[i]<-1:AllSignal[i]=-1else:AllSignal[i]=0

AllSignal[AllSignal==1]

Date-05-13 1-01-21 1dtype: int64

AllSignal[AllSignal==-1]

Date-06-27 -1-10-08 -1-03-03 -1dtype: int64

tradSig=AllSignal.shift(1).dropna()

CBClose=CBClose[-len(tradSig):]asset=pd.Series(0.0,index=Close.index)cash=pd.Series(0.0,index=CBClose.index)share=pd.Series(0,index=CBClose.index)

#当价格连续两天上升且交易信号没有显示卖出时,#第一次开账户持有股票entry=3cash[:entry]=20000while entry<len(CBClose):cash[entry]=cash[entry-1]if all([CBClose[entry-1]>=CBClose[entry-2],\CBClose[entry-2]>=CBClose[entry-3],\AllSignal[entry-1]!=-1]):share[entry]=1000cash[entry]= cash[entry]-1000*CBClose[entry]breakentry+=1

#根据sigal买卖股票i=entry+1while i<len(tradSig):cash[i]=cash[i-1]share[i]=share[i-1]flag=1if tradSig[i]==1:share[i]= share[i]+3000cash[i]=cash[i]-3000*CBClose[i]if all([tradSig[i]==-1,share[i]>0]):share[i]= share[i]-1000cash[i]=cash[i]+1000*CBClose[i]i+=1

asset=cash+share*CBClose

plt.subplot(411)plt.title("-上:中国银行均线交易账户")plt.plot(CBClose, color='b')plt.ylabel("Pricce")plt.subplot(412)plt.plot(share, color='b')plt.ylabel("Share")plt.ylim(0,max(share)+1000)plt.subplot(413)plt.plot(asset,label="asset",color='r')plt.ylabel("Asset")plt.ylim(min(asset)-5000,max(asset)+5000)plt.subplot(414)plt.plot(cash, label="cash",color='g')plt.ylabel("Cash")plt.ylim(0,max(cash)+5000)

(0, 25000.0)

## 投资收益率TradeReturn=(asset[-1]-20000)/20000TradeReturn

0.1785

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