pythonでトレイリングストップ！！その２＠QuantX

高値、安値に合わせて自動的に利確損切りポジションを変えてくれるのトレーリングストップをその２を実装しました。　

今回はポジションクローズの部分を少し変えてみた！！
- 1) トレーリングストップ3%
- 2) 利益率10%以上でかつ、トレーリングストップ1%
- 3) 利益率5%以上でかつ、トレーリングストップ2%


#自己紹介
この度Smart Tradeでインターンすることになったゴンです。

ゴンについて、知りたい方はこちら。
ブログ読んでねー

https://www.investor-gon.com/

ツイッターはこちら
https://twitter.com/gon_gon_tarou

初めての記事はこちら(QuantXを初めてみて)
https://qiita.com/investor-gon/items/2b1952ae5c2c88334c74


#何を作るのか（完成目標）
日経225平均寄与率上位10位の銘柄(2018年12月25日)を用いて、
トレイリングストップロジックで利確損切りをする、移動平均線を用いたアルゴリズムを作る！！！


トレイリングストップとは、なんですかって方は簡単にこちら。

>高値安値に合わせて、逆指値注文をリアルタイムに自動修正する自動売買です。

>同じ売るなら少しでも高いところで売りたい、高値から下落してきたところで売りたい、という場合等で活用できます。

ただQuantXの関係で空売りは対応していないので、今回は高値に合わせて売買する方式にしました。



##気になる条件はこんな感じ

- 基本的には移動平均線のゴールデンクロスで買いシグナルを出す。

- 売り(ポジションクローズ)に関しては、
    - 1) トレーリングストップ3%
    - 2) 利益率10%以上でかつ、MAX利益から1%下落したら売り
    - 3) 利益率5%以上でかつ、MAX利益から2%下落したら売り
 





#まずは完成コード（コピペ、どうぞ）

```
############################################################################
# トレイリングストップ 売買

  #ライブラリーの設定
import pandas as pd
import talib as ta
import numpy as np


def initialize(ctx):
    # 設定
    ctx.logger.debug("initialize() called")
    
    # ポートフォリオの何％をオーダーするか
    ctx.target = 0.1

    # 損切りと益出しの水準
    ctx.loss_cut = -0.04
    ctx.trailing_stop = 0.96
    
    #トレイリングストップの日にち
    ctx.high_term = 15
    
    ctx.configure(
      target="jp.stock.daily",
      channels={          # 利用チャンネル
        "jp.stock": {
          "symbols": [
            "jp.stock.9983", #ファーストリテイリング
            "jp.stock.9984", #ソフトバンク
            "jp.stock.6954", #ファナック
            "jp.stock.9433", #KDDI
            "jp.stock.8028", #ファミリーマート
            "jp.stock.8035", #東京エレクトロン
            "jp.stock.4543", #テルモ
            "jp.stock.6367", #ダイキン
            "jp.stock.6971", #京セラ
            "jp.stock.9735", #セコム
           
          ],
          "columns": [
            #"open_price_adj",    # 始値(株式分割調整後)
            "high_price_adj",    # 高値(株式分割調整後)
            #"low_price_adj",     # 安値(株式分割調整後)
            #"close_price",        # 終値
            "close_price_adj",    # 終値(株式分割調整後) 
            #"volume_adj",         # 出来高
            #"txn_volume",         # 売買代金
          ]
        }
      }
    )

 #売買シグナル生成部分
    def _my_signal(data):
     
      #各銘柄の終値(株式分割調整後)を取得、欠損データの補完 
      cp = data["close_price_adj"].fillna(method='ffill')
      m25 = cp.rolling(window=25, center=False).mean()
      m5 = cp.rolling(window=5, center=False).mean()
      ratio = m5 / m25
      
      df_goldencross = (ratio >= 1.00) & (ratio.shift(1) < 1.00)
      
      # 欠損値を埋める
      hp = data["high_price_adj"].fillna(method="ffill")
      # 過去30日間における最高値を取得
      new_max = hp.rolling(window=ctx.high_term, center=False).max()
      #ctx.logger.debug(new_max)
      
      # 過去30日間における最高値の0.96倍と現在地の比較
      df_trailing_stop = (new_max*ctx.trailing_stop >= cp)
      #ctx.logger.debug(df_trailing_stop)
      
      # 売買シグナルの設定
      buy_sig = df_goldencross 
      sell_sig = df_trailing_stop

      return{
          "m5": m5,
          "m25": m25,
          "df_trailing_stop": df_trailing_stop,
          "new_max": new_max,
          "buy:sig": buy_sig,
          "sell:sig": sell_sig,
        }


    # シグナル登録
    ctx.regist_signal("my_signal", _my_signal)

def handle_signals(ctx, date, current):
  
   #ctx.logger.debug(current)
   
  # ポジションクローズ
   for (sym,val) in ctx.portfolio.positions.items():
     rtn = val["returns"]
     #ctx.logger.debug(val["max_returns"])
     trailing = val["max_returns"] - rtn
      
     if rtn < ctx.loss_cut:
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment="損切り {:.2%}".format(rtn))
     
     elif (rtn > 0.10) & (trailing > 0.01 ):
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment="益出し {:.2%}".format(rtn))   
        
     elif (rtn > 0.05) & (trailing > 0.02 ):
        sec = ctx.getSecurity(sym)
        sec.order_target_percent(0, comment="益出し {:.2%}".format(rtn))   
       
   # 売りシグナル
   sell = current["sell:sig"].dropna()
   df_sell = sell[sell > 0]
 
   for (sym,val) in df_sell.items():
     sec = ctx.getSecurity(sym)
     sec.order_target_percent(0, comment="利確")     
     
        
   # 買いシグナル
   df = current.copy()  
   df = df[df["buy:sig"]]

   if not df.empty:
      for (sym, val) in df.iterrows(): 
        sec = ctx.getSecurity(sym)
        msg = "買いシグナル"
        sec.order_target_percent(ctx.target, comment=msg)
        
```
#結果はこちら
![スクリーンショット 2019-03-28 12.38.52.png](https://qiita-image-store.s3.amazonaws.com/0/332034/2947ca34-bae3-f6f0-a822-3ab97d208880.png)

意外と利益でました。


詳しくみてみると、
![スクリーンショット 2019-03-28 12.39.30.png](https://qiita-image-store.s3.amazonaws.com/0/332034/1cfb5f87-5bc3-7927-7b00-668ff3f33a89.png)

いい感じに売り買いされてます。





#解説

解説は、知りたい人がいたらやります。
コードだけでわかる気もします。


それでは今回はこの辺で。