QuantXを使ってみる

#はじめに
理系大学生で、普段は機械工学を専攻しています。
pythonは、独学で少し勉強した程度で、金融の知識はほぼありません。
今回、SmartTradeでインターンをすることになり、QuantX（https://quantx.io/）
でアルゴリズム開発を行いました。
#QuantXを使う
##目的
QuantXでアルゴリズム開発を行う。
##作りたいアルゴリズム
複雑な取引は行わずに、大きな上昇トレンドの最初の方で買い、大きな下降トレンドの最初の方で、売れるようなアルゴリズムを使いたい。
そのために、下記の図のように、短期線が長期線を超えたときに、買えるようにする。（売りはその逆）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/378059/06762ef4-6309-f3c8-7d5b-4c406aefa7da.png)




##実際に作ってみる
今回は、この記事（https://qiita.com/katakyo/items/d786599f6638d53a8602）
を参考にしました。
作ったアルゴリズムは下記の通りとなります。

【追記】
今回は上図のようなゴールデンクロスを作りたいと思っていましたが、後で検証した結果下のアルゴリズムは平均乖離率のものとなっていました。
そのため、下のアルゴリズムは上記の図のようなものでなく、平均乖離率のものとなっております。

```ruby:try.py
import talib as ta 
import pandas as pd 
import numpy as np 

  #関数の初期化
def initialize(ctx):#初期関数の定義
  #設定
    ctx.logger.debug("initialize() called")#プログラムのログ出力を行う
    ctx.configure(#トレードの基本設定
      target="jp.stock.daily",#日本株を使う
      channels={          #銘柄選択　#データを実際に入れる
        "jp.stock": {
          "symbols": [
            "jp.stock.7201", #日産自動車
            "jp.stock.2914", #日本たばこ産業
            "jp.stock.8766", #東京海上ホールディングス
            "jp.stock.8031", #三井物産
            "jp.stock.8316", #三井住友フィナンシャルグループ
            "jp.stock.8411", #みずほフィナンシャルグループ
            # "jp.stock.9427", #NTTドコモ
            "jp.stock.4502", #武田薬品工業
            "jp.stock.8058", #三菱商事
            "jp.stock.9433", #KDDI
            "jp.stock.9432", #日本電信電話
            "jp.stock.7267", #本田技研工業
            "jp.stock.6902", #デンソー
            "jp.stock.4503", #アステラス製薬
            "jp.stock.4063", #信越化学工業
            "jp.stock.7974", #任天堂
            "jp.stock.6981", #村田製作所
            "jp.stock.3382", #セブン＆アイ・ホールディングス
            "jp.stock.9020", #東日本旅客鉄道
            "jp.stock.8802", #三菱地所
            "jp.stock.9022", #東海旅客鉄道
            "jp.stock.9984", #ソフトバンクグループ
            "jp.stock.6861", #キーエンス
            "jp.stock.6501", #日立製作所
            "jp.stock.6752", #パナソニック
            "jp.stock.6758", #ソニー
            "jp.stock.6954", #ファナック
            "jp.stock.7203", #トヨタ自動車
            "jp.stock.7751", #キヤノン
          ],
          "columns": [#columnsの中に終値などの必要なデータを入れる
            "open_price_adj",     # 始値(株式分割調整後)
            "high_price_adj",     # 高値(株式分割調整後)
            "low_price_adj",      # 安値(株式分割調整後)
            "close_price",        # 終値
            "close_price_adj",    # 終値(株式分割調整後) 
          ] 
        }
      }
    )
    
    #シグナル定義
    def _my_signal(data): #売買シグナルの定義
      

      #fillna(method='ffill')を使うと欠損値(NaN)を自動的に保管してくれる
      cp = data["close_price_adj"].fillna(method="ffill")
      ctx.logger.debug(cp)

      #単純移動平均線(SMA)の設定
      #データの入れ物を用意
      s_sma = pd.DataFrame(data=0,columns=[], index=cp.index)#短期の単純移動曲線
      l_sma = pd.DataFrame(data=0,columns=[], index=cp.index)
      #TA-Libによる計算
      for (sym,val) in cp.items():
        s_sma[sym] = ta.SMA(cp[sym].values.astype(np.double), timeperiod=5)
        l_sma[sym] = ta.SMA(cp[sym].values.astype(np.double), timeperiod=75)
      #SMAの売買シグナルの定義
      #短期線と長期線の比率を出したもの
      s_sma_ratio = s_sma/l_sma
      df_sma_buy_sig = (s_sma_ratio > 1.02) & (s_sma_ratio < 1.04) 
      df_sma_sell_sig = (s_sma_ratio < 0.96)  
      ctx.logger.debug(cp)
      #売買シグナルの設定
      buy_sig = df_sma_buy_sig 
      sell_sig = df_sma_sell_sig 
      buy_sig = df_sma_buy_sig 
      sell_sig = df_sma_sell_sig 
      #return内にシグナル定義部分で定義した変数を入れて可視化できるようにする
      return {
        "s_sma": s_sma,
        "l_sma": l_sma,
        "buy:sig":buy_sig,
        "sell:sig":sell_sig, 
        }

     # シグナル登録　登録するとシグナルが生成される
    ctx.regist_signal("my_signal", _my_signal)
    
#取引数量の設定
def handle_signals(ctx, date, current):
    df = current.copy()
  
    # 買いシグナル
    df_long = df[df["buy:sig"]]
    if not df_long.empty:
      for (sym, val) in df_long.iterrows(): 
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0.07, comment= "買いシグナル")

    # 売りシグナル
    df_sell = df[df["sell:sig"]]
    if not df_sell.empty:
      for (sym, val) in df_sell.iterrows(): 
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment= "売りシグナル")
        
    done_syms = set([])
    for (sym,val) in ctx.portfolio.positions.items():
      returns = val["returns"]
      if returns < -0.15:
        sec = ctx.getSecurity(sym)
        sec.order(-val["amount"], comment="損切り(%f)" % returns)
        done_syms.add(sym)
      elif returns > 0.30:
        sec = ctx.getSecurity(sym)
        sec.order(-val["amount"], comment="利益確定売(%f)" % returns)
        done_syms.add(sym)
```

短期線と長期線の位置の関係で売買したかったので、長期線/短期線が1.02～1.04の時に買い、0.96以下の時に、売るようにしました。
#結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/378059/9c75f96b-d4d1-4a69-6a27-79fc16841587.png)

今回は単純移動平均線のみを用いましたが、より精度の高いものを作るには、他の指標を組み合わせる必要性を感じました。次回は、他にも組み合せてやってみたいと思います。
#参考資料
QuantX(https://quantx.io/)
移動平均線について　その１〜3種類の移動平均線を描画してみる 〜＃QuantX（https://qiita.com/katakyo/items/d786599f6638d53a8602）
小次郎講師（2018）『移動平均線究極の読み方・使い方』日本実業出版社
#勉強会
SmartTrade社では毎週水曜日18:00から勉強会を行っています。（https://python-algo.connpass.com/）