量化投資——利用 Pyalgotrade 進(jìn)行 SMA策略回測

過年前忙于其它項(xiàng)目,過年期間又貪玩偷懶了,今天簡要的將幾段學(xué)習(xí)代碼更新上來,供大家參交流。
量化交易在實(shí)盤交易之前,必須對量化交易策略進(jìn)行回測。在此,我們主要介紹其中比較優(yōu)秀的 Pyalgotrade 框架。

Pyalgotrade 簡介

Pyalgotrade是事件驅(qū)動的回測框架,支持虛盤和實(shí)盤兩種交易。文檔完整,整合了TA-Lib(技術(shù)分析庫)。在速度和靈活方面都表現(xiàn)出眾。但它的一大硬傷是不支持 Pandas 的模塊和對象,而且數(shù)據(jù)格式不支持國內(nèi)股票數(shù)據(jù),需要我們自己實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換。

PyAlgoTrade 六大組件:

  • Strategies策略: 定義的實(shí)現(xiàn)交易邏輯的類:何時買、何時賣,等等;
  • Feeds數(shù)據(jù)源:These are data providing abstractions. 例如,你可以使用CSV數(shù)據(jù)源從一個格式化后的csv(以逗號分割)文件中加載數(shù)據(jù)推送給策略。 數(shù)據(jù)源不僅限于bars。
  • Brokers經(jīng)紀(jì)商:經(jīng)紀(jì)商模塊負(fù)責(zé)執(zhí)行訂單。
  • DataSeries數(shù)據(jù)序列:DataSeries 是用于管理時間序列的抽象類
  • Technicals指標(biāo)計(jì)算:這是你用來對DataSeries進(jìn)行計(jì)算的一組過濾(指標(biāo))器。 例如簡單移動平均線(SMA),相對強(qiáng)弱指標(biāo)(RSI)等. 這些過濾(指標(biāo))器被建模為DataSeries 的裝飾器。
  • Optimizer優(yōu)化:這是能讓你在不同電腦之間、或多進(jìn)程、或二者結(jié)合以加快回測效率的一組類。

自定義回歸策略

這里不廢話了,我們直接上代碼,我們的交易策略類 MyStrategy 繼承自Pyalgotrade.strategy.BacktestingStrategy 類:

# 基于 pyalgotrade 的交易策略類
class MyStrategy(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, smaPeriod):
        super(MyStrategy, self).__init__(feed)
        self.__instrument = instrument
        self.__closed = feed[instrument].getCloseDataSeries()
        self.__sma = ma.SMA(self.__closed, smaPeriod)
        self.__position = None
        self.getBroker()
       
    def getSMA(self):
        return self.__sma
   
    def onEnterLong(self, position):
        print("onEnterLong", position.getShares())

    def onEnterOk(self, position):
        execInfo = position.getEntryOrder().getExecutionInfo()
        self.info("BUY at %.2f" % (execInfo.getPrice()))
       
    def onEnterCanceled(self, position):
        self.__position = None
        print("onEnterCanceled", position.getShares())
       
    def onExitOk(self, position):
        execInfo = position.getExitOrder().getExecutionInfo()
        self.info("SELL at $%.2f" % (execInfo.getPrice()))
        self.__position = None
        print("onExitOk", position.getShares())
       
    def onExitCanceled(self, position):
        self.__position.exitMarket()
        print("onExitCanceled", position.getShares())
       
    def onBars(self, bars):
        if self.__position is None:
            if cross.cross_above(self.__closed, self.__sma) > 0:
                shares = int(self.getBroker().getCash() * 0.9 / bars[self.__instrument].getPrice())
                print("cross_above shares,", shares)
                # Enter a buy market order. The order is good till canceled.
                self.__position = self.enterLong(self.__instrument, shares, True)
        elif not self.__position.exitActive() and cross.cross_below(self.__closed, self.__sma) > 0:
            print("cross_below")
            self.__position.exitMarket()
           

    def getClose(self):
        return self.__closed

對股票進(jìn)行策略回溯

示例代碼,以 格力電器(000651)為例,初始資本 100萬,回溯時間 2018年1月1日 至 2019年 2月 12日,SMA周期 30:

code = "000651" # 格力電器
feed = tsfeed.Feed()
feed.addBarsFromCode(code,start='2018-01-01',end='2019-02-12')

# Evaluate the strategy with the feed's bars.
myStrategy = MyStrategy(feed, code, 30) # SMA周期 30
returnsAnalyzer = returns.Returns()
myStrategy.attachAnalyzer(returnsAnalyzer)
sharpe_ratio = sharpe.SharpeRatio()
myStrategy.attachAnalyzer(sharpe_ratio)

plt = plotter.StrategyPlotter(myStrategy)
plt.getInstrumentSubplot(code).addDataSeries("SMA", myStrategy.getSMA())
plt.getOrCreateSubplot("returns").addDataSeries("Simple returns", returnsAnalyzer.getReturns())

myStrategy.run()
myStrategy.info("Final portfolio value: $%.2f" % myStrategy.getResult())

plt.plot()

最終回測結(jié)果如下圖:


格力電器,2018-01-01 至 2019-02-12 回溯

不同周期的策略回測結(jié)果

如上圖所示,格力電器 2018年 初始資本 100萬,末期資本 72.88 萬,虧損近 30%。如此看來,是否交易策略無效呢?
我們不妨進(jìn)行更長時間的回測,從 2009年01月01日開始,進(jìn)行10年時間的回測,結(jié)果如下:


格力電器,2009-01-01 至 2019-02-12 回溯

可見,格力電器 10 年時間回測結(jié)果,末期資本為 340.66 萬元, 10年收益 240%。此外,經(jīng)過我們測試,SMA 不同周期對收益也有明顯影響,下面,直接給出我們針對 格力電器和工商銀行 不同周期,不同SMA頻率的回測結(jié)果:

格力電器收益率 1年(2018-01-01~ 2019-02-12) 10 年(2009-01-01~ 2019-02-12 )
SMA 5 -18.32% 116.41%
SMA 10 -26.01% 166.57%
SMA 15 -28.76% 127.1%
SMA 20 -25.44% 347.41%
SMA 30 -27.12% 240.66%
SMA 50 -3.12% 229.2%
工商銀行收益率 1年(2018-01-01~ 2019-02-12) 10 年(2009-01-01~ 2019-02-12 )
SMA 5 0% 110.65%
SMA 10 -16.41% 88.34%
SMA 15 -8.43% 113.07%
SMA 20 -11.74% 30%
SMA 30 -14.44% 66.24%
SMA 50 -6.39% 40.90%

結(jié)論

根據(jù)我們基于自定義策略對格力電器和 工商銀行的回測分析,初步可以得到如下結(jié)論:

  1. 基于我們的策略,堅(jiān)持長期策略投資,其最大收益高于大盤表現(xiàn)(最大收益率 347% :格力電器,10年期,SMA 20);
  2. 選取SMA 周期,在 20 左右(在15 ~ 30 之間),其收益最大,相對虧損風(fēng)險(xiǎn)較??;
  3. 選取SMA 周期越大(等于 50 時),風(fēng)險(xiǎn)越??;
  4. 綜合來看,投資格力電器收益率更大,而風(fēng)險(xiǎn)在可控范圍內(nèi)。

注:以上結(jié)論只是作為對策略歷史數(shù)據(jù)回測的結(jié)果分析,不可作為實(shí)際投資參考。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容