小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

「手把手教你」用Python寫一個擇時策略回測

 追夢文庫 2020-02-21

文章來源于量化小白上分記 ,作者量化小白H。

看多了前面的鋪墊,接下來寫一寫可以實操的。本篇給出寫擇時策略回測的詳細步驟,并用代碼展示全過程,代碼用python寫,數據和代碼后臺回復“擇時”獲取,可以自己測試。

擇時策略

根據百度百科的解釋,擇時交易是指利用某種方法來判斷大勢的走勢情況,是上漲還是下跌或者是盤整。如果判斷是上漲,則買入持有;如果判斷是下跌,則賣出清倉,如果是盤整,可以高拋低吸。

從量化角度來說,擇時是通過資產的數據構造出買賣信號,按照買賣信號進行交易?;販y就是實現這整個過程。

本文以最簡單的雙均線策略為例進行回測,具體規(guī)則如下:

  1. 短均線上穿長均線(金叉),且當前無持倉:買入;
  2. 短均線下穿長均線(死叉),且當前持倉,賣出;
  3. 其他情況,保持之前倉位;
  4. 可以考慮控制回撤,單次虧損超過一定幅度平倉。

回測評價

對于策略的評價,總體分為收益和風險兩方面,或者將兩者綜合起來,列一些最常用的評價指標。

年化收益

回測起點到終點的累積收益年化,算復利或單利都可以,復利假設策略的盈利也會被用于投資,因此復利算出來結果會更好看一些。

夏普比

夏普比 = (策略期望收益率 - 無風險收益率)/策略波動率

夏普比綜合衡量了收益和風險,是最廣泛應用的指標。

勝率

統(tǒng)計勝率要先統(tǒng)計交易次數,然后計算所以交易中盈利次數占的比例

最大回撤率

回撤是策略從前期最高點到當前時點的虧損,最大回撤是所有回撤中的最大值,反映的是策略的最大可能損失。

單次最大虧損

所有單次交易中的最大虧損

策略階段性表現

對策略時間段進行分割,統(tǒng)計每個時間段內上述指標的變化情況,本文按年進行分割,統(tǒng)計測年逐年的收益率和相對于基準的超額收益率。

其他

除此外,還有波動率、下行風險、索提諾比率等各種指標,python中有專門的模塊可以計算各種指標,這里我們自己算出各種指標,供參考。

此外,還需要測試策略的穩(wěn)定性,對策略中參數進行擾動,檢驗策略的敏感性情況,好的策略應該是參數不敏感的。

回測說明

回測標的:滬深300指數

回測區(qū)間:2010年1月-2019年3月

代碼說明:回測代碼分成兩塊,一塊是策略函數(Strategy),一塊是評價函數(Performance),策略函數通過指數的收盤價構造信號,計算策略凈值,統(tǒng)計策略的每筆交易的情況。評價函數根據策略凈值和策略每筆交易的情況計算策略的上述各個指標。

策略代碼

回測函數

def Strategy(pdatas,win_long,win_short,lossratio = 999): # pdatas = datas.copy();win_long = 12;win_short = 6;lossratio = 999; ''' pma:計算均線的價格序列 win:窗寬 lossratio:止損率,默認為0 ''' pdatas = pdatas.copy() pdatas['lma'] = pdatas.CLOSE.rolling(win_long,min_periods = 0).mean() pdatas['sma'] = pdatas.CLOSE.rolling(win_short,min_periods = 0).mean() pdatas['position'] = 0 # 記錄持倉 pdatas['flag'] = 0 # 記錄買賣 pricein = [] priceout = [] price_in = 1 for i in range(max(1,win_long),pdatas.shape[0] - 1): # 當前無倉位,短均線上穿長均線,做多 if (pdatas.sma[i-1] < pdatas.lma[i-1]) & (pdatas.sma[i] > pdatas.lma[i]) & (pdatas.position[i]==0): pdatas.loc[i,'flag'] = 1 pdatas.loc[i + 1,'position'] = 1 date_in = pdatas.DateTime[i] price_in = pdatas.loc[i,'CLOSE'] pricein.append([date_in,price_in]) # 當前持倉,下跌超出止損率,止損 elif (pdatas.position[i] == 1) & (pdatas.CLOSE[i]/price_in - 1 < -lossratio): pdatas.loc[i,'flag'] = -1 pdatas.loc[i + 1,'position'] = 0 priceout.append([pdatas.DateTime[i],pdatas.loc[i,'CLOSE']]) # 當前持倉,死叉,平倉 elif (pdatas.sma[i-1] > pdatas.lma[i-1]) & (pdatas.sma[i] < pdatas.lma[i]) &(pdatas.position[i]==1): pdatas.loc[i,'flag'] = -1 pdatas.loc[i+1 ,'position'] = 0 priceout.append([pdatas.DateTime[i],pdatas.loc[i,'CLOSE']]) # 其他情況,保持之前倉位不變 else: pdatas.loc[i+1,'position'] = pdatas.loc[i,'position'] p1 = pd.DataFrame(pricein,columns = ['datebuy','pricebuy']) p2 = pd.DataFrame(priceout,columns = ['datesell','pricesell']) transactions = pd.concat([p1,p2],axis = 1) pdatas = pdatas.loc[max(0,win_long):,:].reset_index(drop = True) pdatas['ret'] = pdatas.CLOSE.pct_change(1).fillna(0) pdatas['nav'] = (1 + pdatas.ret*pdatas.position).cumprod() pdatas['benchmark'] = pdatas.CLOSE/pdatas.CLOSE[0] stats,result_peryear = performace(transactions,pdatas) return stats,result_peryear,transactions,pdatas

說明

  1. lma,sma為通過收盤價計算的均線,position是持倉標記,flag是開倉標記;
  2. 策略考慮了止損,超出閾值lossratio止損,默認情況為不止損,設置lossratio = 0.01對應止損率1%,即下跌超過1%平倉;
  3. transcations中記錄每筆交易的買賣價格和日期,用于統(tǒng)計勝率;
  4. performance函數為策略評價函數;
  5. 沒有考慮手續(xù)費;

評價函數

def performace(transactions,strategy): # strategy = pdatas.copy(); N = 250   # 年化收益率 rety = strategy.nav[strategy.shape[0] - 1]**(N/strategy.shape[0]) - 1  # 夏普比 Sharp = (strategy.ret*strategy.position).mean()/(strategy.ret*strategy.position).std()*np.sqrt(N)   # 勝率 VictoryRatio = ((transactions.pricesell - transactions.pricebuy)>0).mean() DD = 1 - strategy.nav/strategy.nav.cummax() MDD = max(DD)   # 策略逐年表現  strategy['year'] = strategy.DateTime.apply(lambda x:x[:4]) nav_peryear = strategy.nav.groupby(strategy.year).last()/strategy.nav.groupby(strategy.year).first() - 1 benchmark_peryear = strategy.benchmark.groupby(strategy.year).last()/strategy.benchmark.groupby(strategy.year).first() - 1  excess_ret = nav_peryear - benchmark_peryear result_peryear = pd.concat([nav_peryear,benchmark_peryear,excess_ret],axis = 1) result_peryear.columns = ['strategy_ret','bench_ret','excess_ret'] result_peryear = result_peryear.T  # 作圖 xtick = np.round(np.linspace(0,strategy.shape[0] - 1,7),0) xticklabel = strategy.DateTime[xtick]   plt.figure(figsize = (9,4)) ax1 = plt.axes() plt.plot(np.arange(strategy.shape[0]),strategy.benchmark,'black',label = 'benchmark',linewidth = 2) plt.plot(np.arange(strategy.shape[0]),strategy.nav,'red',label = 'nav',linewidth = 2) plt.plot(np.arange(strategy.shape[0]),strategy.nav/strategy.benchmark,'orange',label = 'RS',linewidth = 2) plt.legend() ax1.set_xticks(xtick) ax1.set_xticklabels(xticklabel)      maxloss = min(transactions.pricesell/transactions.pricebuy - 1) print('------------------------------') print('夏普比為:',round(Sharp,2)) print('年化收益率為:{}%'.format(round(rety*100,2))) print('勝率為:{}%'.format(round(VictoryRatio*100,2))) print('最大回撤率為:{}%'.format(round(MDD*100,2))) print('單次最大虧損為:{}%'.format(round(-maxloss*100,2))) print('月均交易次數為:{}(買賣合計)'.format(round(strategy.flag.abs().sum()/strategy.shape[0]*20,2)))  result = {'Sharp':Sharp, 'RetYearly':rety, 'WinRate':VictoryRatio, 'MDD':MDD, 'maxlossOnce':-maxloss, 'num':round(strategy.flag.abs().sum()/strategy.shape[0],1)}  result = pd.DataFrame.from_dict(result,orient='index').T  return result,result_peryear

說明

  1. 計算了年化收益、夏普比、最大回撤、勝率、逐年收益率、單次最大虧損等指標;
  2. 收益都用復利;

回測結果

「手把手教你」用Python寫一個擇時策略回測

「手把手教你」用Python寫一個擇時策略回測

nav為策略凈值,benchmark為基準凈值,RS為相對強弱曲線,可以看出,策略表現并不穩(wěn)定。

transcation中記錄每筆交易的買賣時點和價格

「手把手教你」用Python寫一個擇時策略回測

result_peryear中是策略的逐年表現情況,也并不會比基準好多少

「手把手教你」用Python寫一個擇時策略回測

綜上,是一個完整的策略回測和評價過程,當然實際操作中還有許多需要細化的地方,僅供參考,歡迎指正!

關于Python金融量化

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多