移動平均線乖離を利用したアルゴリズム

#今回のアルゴリズム
小型成長株メインで、移動平均線MA25とMA5を利用した順張りアルゴリズムを作成し実装してみました。

#移動平均線とは
移動平均線は、一定期間の平均価格を日々計算して算出した値を、単純平均したものです。
例えば5日移動平均値は5日分の平均価格となります。そして、日々の平均価格を線でつないだものが5日移動平均線となります。
平均価格（ここでは終値の平均）を使用することで日中の大きな変動に惑わされることなく、現在の相場の方向性（トレンド）がどちらを向いているのか（上がっているのか、下がっているのか）を見ることができます。
####よく利用される移動平均線の種類
・短期線　…　5日、10日
・中期線　…　20日、25日、75日
・長期線　…　100日、200日

#アルゴリズム
###銘柄
東証1部・2部・マザーズに上場している売上高成長率30%以上の銘柄をスクリーニングしました。
また、小型成長株がメインのポートフォリオなため、どうしてもダウントレンドの際にパフォーマンスが安定しないと考え、緩和するためにダブルインバースを組み込みました。


###シグナル
買い：MA25 +2%
売り：MA5 -2%

損切：なし
利確：なし
##コード

```python
import pandas as pd
import talib as ta
import numpy as np

def initialize(ctx):
    # 設定
    ctx.logger.debug("initialize() called")
    ctx.configure(
      target="jp.stock.daily",
      channels={          # 利用チャンネル
        "jp.stock": {
          "symbols": [
'jp.stock.1360', #  ダブルインバース
'jp.stock.4571', #   ナノキャリア
'jp.stock.4586', #   メドレックス
'jp.stock.4597', #   ソレイジア
'jp.stock.4598', #   DELTA-P
'jp.stock.6027', #   弁護士コム
'jp.stock.6030', #   アドベンチャ
'jp.stock.6033', #   エクストリーム
'jp.stock.6034', #   MRT
'jp.stock.6086', #   シンメンテHD
'jp.stock.6090', #   HMT
'jp.stock.6095', #   メドピア
'jp.stock.6172', #   メタップス
'jp.stock.6190', #   PXB
'jp.stock.6192', #   HyAS&Co.
'jp.stock.6195', #   ホープ
'jp.stock.6232', #   ACSL
'jp.stock.6537', #   WASHハウス
'jp.stock.6553', #   ソウルドアウト
'jp.stock.6561', #   HANATOUR
'jp.stock.6572', #   RPA
'jp.stock.6577', #   ベストワン
'jp.stock.7033', #   MSOL
'jp.stock.7034', #   プロレド
'jp.stock.7035', #   anfac
'jp.stock.7046', #   TDSE
'jp.stock.7047', #   ポート
'jp.stock.7172', #   JIA
'jp.stock.8789', #   フィンテック
'jp.stock.9271', #   和　心
          ],
          "columns": [
            #"open_price_adj",    # 始値(株式分割調整後)
            #"high_price_adj",    # 高値(株式分割調整後)
            #"low_price_adj",     # 安値(株式分割調整後)
            "close_price",        # 終値
            "close_price_adj",    # 終値(株式分割調整後) 
            "volume_adj",         # 出来高
            "txn_volume",         # 売買代金
          ]
        }
      }
    )

    def _mavg_signal(data):
        #ns_sentiment = data["ns_sentiment"].fillna(method="ffill")
        # ctx.logger.debug(ns_sentiment)
        m25 = data["close_price_adj"].fillna(method='ffill').ewm(span=25).mean()
        dfma25 = (data["close_price_adj"] -  m25) / m25 * 100
        m5 = data["close_price_adj"].fillna(method='ffill').ewm(span=5).mean()
        dfma5 = (data["close_price_adj"] -  m5) / m5 * 100

        buy_sig = dfma25[(dfma25 > 2.0)]
        sell_sig = dfma5[(dfma5 < -2.0)]
        return {
            "mavg_25:price": m25,
            "mavg_5:price": m5,
            #"mavg_ratio:ratio": ratio,
            "buy:sig": buy_sig,
            "sell:sig": sell_sig,
        }

    # シグナル登録
    ctx.regist_signal("mavg_signal", _mavg_signal)

def handle_signals(ctx, date, current):
    '''
    current: pd.DataFrame
    '''

    done_syms = set([])
    for (sym,val) in ctx.portfolio.positions.items():
        returns = val["returns"]
        ctx.logger.debug("%s %f" % (sym, returns))
        # if returns < -0.03:
        #   sec = ctx.getSecurity(sym)
        #   sec.order(-val["amount"], comment="損切り(%f)" % returns)
        #   done_syms.add(sym)
        # elif returns > 0.05:
        #   sec = ctx.getSecurity(sym)
        #   sec.order(-val["amount"], comment="利益確定売(%f)" % returns)
        #   done_syms.add(sym)


    buy = current["buy:sig"].dropna()
    for (sym,val) in buy.items():
        if sym in done_syms:
          continue

        sec = ctx.getSecurity(sym)
        sec.order(sec.unit() * 1, comment="SIGNAL BUY")
        #ctx.logger.debug("BUY: %s,  %f" % (sec.code(), val))
        pass

    sell = current["sell:sig"].dropna()
    for (sym,val) in sell.items():
        if sym in done_syms:
          continue

        sec = ctx.getSecurity(sym)
        sec.order(sec.unit() * -1, comment="SIGNAL SELL")
        #ctx.logger.debug("SELL: %s,  %f" % (sec.code(), val))
        pass

```

#バックテスト結果
<img width="830" alt="スクリーンショット 2019-02-21 18.01.43.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/269343/ca88980c-bf54-e209-bc43-356a4ab90483.jpeg">

昨年の暴落期間を含めても+18.9%とまずまずの成果ではないでしょうか。



#まとめ
色々な期間でバックテストを試みたものの、やはりダウントレンドになると、パフォーマンスがいまいちでしたので、下落相場であってもハイパフォーマンスを発揮できるよう、他のシグナルを追加するなど、引き続き改善を図っていきたいと思います。