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

【量化笔记】随机指标交易策略 KDJ

时间:2023-05-11 22:02:23

相关推荐

【量化笔记】随机指标交易策略 KDJ

KDJ指标的计算公式

未成熟随机指标RSV

RSV=第n天的收盘价−最近n天内的最低价最近n天内的最高价−最近n天内的最低价RSV=\frac{第n天的收盘价-最近n天内的最低价}{最近n天内的最高价-最近n天内的最低价}RSV=最近n天内的最高价−最近n天内的最低价第n天的收盘价−最近n天内的最低价​

K指标:

K值=23∗前一日K值+13∗当日RSVK值=\frac{2}{3}*前一日K值+\frac{1}{3}*当日RSVK值=32​∗前一日K值+31​∗当日RSV

D指标:

D值=23∗前一日D值+13∗当日K值D值=\frac{2}{3}*前一日D值+\frac{1}{3}*当日K值D值=32​∗前一日D值+31​∗当日K值

J指标:

J值=3∗K值−2∗D值J值=3*K值-2*D值J值=3∗K值−2∗D值

import pandas as pdimport numpy as npimport matplotlib.pyplot as plt

# 以标准普尔指数为例计算RSV值GSPC=pd.read_csv('GSPC.csv',index_col='Date')GSPC=GSPC.iloc[:,1:]GSPC.index=pd.to_datetime(GSPC.index)GSPC.head()

close=GSPC.Closehigh=GSPC.Highlow=GSPC.Low

date=close.index.to_series()ndate=len(date)

periodHigh=pd.Series(np.zeros(ndate-8),\index=date.index[8:])periodLow=pd.Series(np.zeros(ndate-8),\index=date.index[8:])RSV=pd.Series(np.zeros(ndate-8),\index=date.index[8:])

for j in range(8,ndate):period=date[j-8:j+1]i=date[j]periodHigh[i]=high[period].max()periodLow[i]=low[period].min()RSV[i]=100*(close[i]-periodLow[i])\/(periodHigh[i]-periodLow[i])periodHigh.name='periodHigh'periodLow.name='periodLow'RSV.name='RSV'

periodHigh.head(3)periodLow.head(3)RSV.head()RSV.describe()

count 326.000000mean63.558226std 31.525472min 0.00000025% 37.32335950% 72.58042275% 91.854801max100.000000Name: RSV, dtype: float64

plt.rcParams['figure.figsize'] = (20.0, 10.0)close1=close['']RSV1=RSV['']Cl_RSV=pd.DataFrame([close1,RSV1]).transpose()Cl_RSV.plot(subplots=True,title='未成熟随机指标RSV')

array([<matplotlib.axes._subplots.AxesSubplot object at 0x114f6a908>,<matplotlib.axes._subplots.AxesSubplot object at 0x114f805f8>],dtype=object)

GSPC=GSPC['']

import candlecandle.candlePlot(GSPC,\'标普500指数日K线图')

计算K,D指标

## 在RSV前填充前两期的数据为50RSV1=pd.Series([50,50],index=date[6:8]).append(RSV)RSV1.name='RSV'RSV1.head()

Date-01-10 50.000000-01-13 50.000000-01-14 76.994107-01-15 93.035207-01-16 85.985395Name: RSV, dtype: float64

KValue=pd.Series(0.0,index=RSV1.index)

KValue[0]=50for i in range(1,len(RSV1)):KValue[i]=2/3*KValue[i-1]+RSV1[i]/3KValue.name='KValue'KValue.head()

Date-01-10 50.000000-01-13 50.000000-01-14 58.998036-01-15 70.343759-01-16 75.557638Name: KValue, dtype: float64

DValue=pd.Series(0.0,index=RSV1.index)DValue[0]=50for i in range(1,len(RSV1)):DValue[i]=2/3*DValue[i-1]+KValue[i]/3

KValue=KValue[1:]DValue.name='DValue'DValue=DValue[1:]DValue.head()

Date-01-13 50.000000-01-14 52.999345-01-15 58.780817-01-16 64.373090-01-17 66.998029Name: DValue, dtype: float64

plt.subplot(211)plt.title('标准普尔500的收盘价')plt.plot(close[''])plt.subplot(212)plt.title('标准普尔500的RSV与KD线')plt.plot(RSV[''])plt.plot(KValue[''],linestyle='dashed')plt.plot(DValue[''],linestyle='-.')plt.legend(loc='upper left')

<matplotlib.legend.Legend at 0x115e66e80>

计算J指标

JValue=3*KValue-2*DValueJValue.name='JValue'JValue.head()

Date-01-13 50.000000-01-14 70.995416-01-15 93.469645-01-16 97.926733-01-17 82.747662Name: JValue, dtype: float64

plt.subplot(211)plt.title('标准普尔500的收盘价')plt.plot(close[''])plt.subplot(212)plt.title('标准普尔500的RSV与KDJ线')plt.plot(RSV[''])plt.plot(KValue[''],linestyle='dashed')plt.plot(DValue[''],linestyle='-.')plt.plot(JValue[''],linestyle='--')plt.legend(loc='upper left')

<matplotlib.legend.Legend at 0x1165034e0>

KDJ交易策略

K和D的取值范围是0~100 一般而言K值或者D值在80以上为超买区,K值或D值在20以下为超卖区。

对于J值,当J值大于100,可以视为超买区

此外在K线,D线的脚擦好情况也可以释放买入,卖出信号:

在K线由下向上穿过D线是,即出现所谓“黄金交叉”,释放买入信号,当K线由上下穿D线的时候,出现“死亡交叉”,释放卖出信号。

## 捕捉超买超卖信号## K>85 signal=-1## K<20 signal=1## D>80 signal=-1## D<20 signal=1KSignal=KValue.apply(lambda x:\-1 if x>85 else 1 if x<20 else 0)

DSignal=DValue.apply(lambda x: \-1 if x>80 else 1 if x<20 else 0)KDSignal=KSignal+DSignalKDSignal.name='KDSignal'

KDSignal[KDSignal>=1]==1KDSignal[KDSignal<=-1]==-1KDSignal.head(n=3)KDSignal[KDSignal==1].head(n=3)

Date-02-03 1-02-04 1-08-06 1Name: KDSignal, dtype: int64

def trade(signal,price):ret=((price-price.shift(1))/price.shift\(1))[1:]ret.name='ret'signal=signal.shift(1)[1:]tradeRet=ret*signal+0tradeRet.name='tradeRet'Returns=pd.merge(pd.DataFrame(ret),\pd.DataFrame(tradeRet),left_index=True,\right_index=True).dropna()return(Returns)

KDtrade=trade(KDSignal,close)KDtrade.rename(columns={'ret':'Ret',\'tradeRet':'KDtradeRet'},\inplace=True)KDtrade.head()

import ffndef backtest(ret,tradeRet):def performance(x):winpct=len(x[x>0])/len(x[x!=0])annRet=(1+x).cumprod()[-1]**(245/len(x))-1sharpe=ffn.calc_risk_return_ratio(x)maxDD=ffn.calc_max_drawdown((1+x).cumprod())perfo=pd.Series([winpct,annRet,sharpe,maxDD],\index=['win rate','annualized return',\'sharpe ratio','maximum drawdown'])return(perfo)BuyAndHold=performance(ret)Trade=performance(tradeRet)return(pd.DataFrame({ret.name:BuyAndHold,\tradeRet.name:Trade}))

backtest(KDtrade.Ret,KDtrade.KDtradeRet)

## 对-进行回测cumRets1=(1+KDtrade).cumprod()plt.plot(cumRets1.Ret,label='Ret')plt.plot(cumRets1.KDtradeRet,'--',\label='KDtradeRet')plt.title('KD指标交易策略绩效表现')plt.legend()

<matplotlib.legend.Legend at 0x1a1a329a58>

backtest(KDtrade.Ret[:'-10-10'],\KDtrade.KDtradeRet[:'-10-10'])

# 对进行回测cumRets2=(1+KDtrade[:'-10-10']).cumprod()plt.plot(cumRets2.Ret,\label='''Ret[:'-10-10']''')plt.plot(cumRets2.KDtradeRet,'--',\label='''KDtradeRet[:'-10-10']''')plt.title('KD指标交易策略10月10日之前绩效表现')plt.legend(loc='upper left')

<matplotlib.legend.Legend at 0x1a1a380438>

使用J值作为指标

## J>100 signal=-1## J<0 signal=1JSignal=JValue.apply(lambda x:\-1 if x>100 else 1 if x<0 else 0)

KDJSignal=KSignal+DSignal+JSignalKDJSignal=KDJSignal.apply(lambda x:\1 if x>=2 else -1 if x<=-2 else 0)

KDJtrade=trade(KDJSignal,close)KDJtrade.rename(columns={'ret':'Ret',\'tradeRet':'KDJtradeRet'},\inplace=True)backtest(KDJtrade.Ret,KDJtrade.KDJtradeRet)

KDJCumRet=(1+KDJtrade).cumprod()plt.plot(KDJCumRet.Ret,label='Ret')plt.plot(KDJCumRet.KDJtradeRet,'--',\label='KDJtradeRet')plt.title('KDJ指标交易策略绩效表现')plt.legend(loc='upper left')

<matplotlib.legend.Legend at 0x1a1a6a7cc0>

backtest(KDJtrade.Ret[:'-10-10'],\KDJtrade.KDJtradeRet[:'-10-10'])

捕捉黄金交叉和死亡交叉

def upbreak(Line,RefLine):signal=np.all([Line>RefLine,\Line.shift(1)<RefLine.shift(1)],\axis=0)return(pd.Series(signal[1:],\index=Line.index[1:]))

KDupbreak=upbreak(KValue,DValue)*1KDupbreak[KDupbreak==1].head()

Date-02-06 1-03-04 1-03-20 1-03-31 1-04-16 1dtype: int64

def downbreak(Line,RefLine):signal=np.all([Line<RefLine,\Line.shift(1)>RefLine.shift(1)],\axis=0)return(pd.Series(signal[1:],\index=Line.index[1:]))

KDdownbreak=downbreak(KValue,DValue)*1KDdownbreak[KDdownbreak==1].head()

Date-01-23 1-02-21 1-03-11 1-03-24 1-04-07 1dtype: int64

# 计算收盘价的变化量close=close['-01-14':]difclose=close.diff()

#价格上涨用1表示,价格下跌用-1表示prctrend=2*(difclose[1:]>=0)-1prctrend.head()

Date-01-15 1-01-16 -1-01-17 -1-01-21 1-01-22 1Name: Close, dtype: int64

#上涨行情中,K向上突破D,做多KDupSig=(KDupbreak[1:]+prctrend)==2KDupSig.head(n=3)

Date-01-15 False-01-16 False-01-17 Falsedtype: bool

KDdownSig=pd.Series(np.all([KDdownbreak[1:]==1,prctrend==-1],\axis=0),\index=prctrend.index)

breakSig=KDupSig*1+KDdownSig*-1breakSig.name='breakSig'breakSig.head()

Date-01-15 0-01-16 0-01-17 0-01-21 0-01-22 0Name: breakSig, dtype: int64

KDbreak=trade(breakSig,close)KDbreak.rename(columns={'ret':'Ret',\'tradeRet':'KDbreakRet'},\inplace=True)KDbreak.head()

backtest(KDbreak.Ret,KDbreak.KDbreakRet)

KDbreakRet=(1+KDbreak).cumprod()plt.plot(KDbreakRet.Ret,label='Ret')plt.plot(KDbreakRet.KDbreakRet,'--',\label='KDbreakRet')plt.title('KD"金叉"与"死叉"交易策略绩效表现')plt.legend(loc='upper left')

<matplotlib.legend.Legend at 0x1a1a9bee10>

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