QuantXで一目均衡表を作ってみた(Python) ・続編

#QuantXとは
株式会社SmartTradeが提供しているアルゴリズム開発プラットフォーム
[QuantX Factoryの公式ホームページ](https://factory.quantx.io)
無料でアルゴリズムを作成してバックテストをすることができるほか、アルゴリズムを販売したり、購入したりすることができる。
詳しくは[QuantXの公式ドキュメントのページ](https://determined-feynman-fb5a05.netlify.com/ja/)
##前回までにやったこと
###一目均衡表を考えた
**基準線=(26日最高値+26日最安値)÷２**
**転換線=(9日最高値+9日最安値)÷２**
**先行スパン1本目=基準線と転換線の平均を26日先行したもの**
**先行スパン2本目=52日間の最高値と最安値の平均を26日先行したもの**
**遅行線=当日の終値を26日先行させたもの**

という感じです。

###基準線と転換線のクロスを用いた
詳しくは[QuantXで一目均衡表を作ってみた(Python)](https://qiita.com/motigasuki/items/85a23f6f0f598be9b16d)をみてください‼️

前回作ったアルゴリズムがこれでーーーーす。

```python:qiita1.py
import numpy as np
import pandas as pd
import talib as ta

def initialize(ctx):
    # 設定
    ctx.logger.debug("initialize() called")
    ctx.configure(
      channels={          # 利用チャンネル
        "jp.stock": {
          "symbols": [
             "jp.stock.1333",#マルハニチロ（水産）
               "jp.stock.1605",#国際石開帝石（鉱業）
               "jp.stock.1925",#ハウス（建設）
               "jp.stock.2914",#JT（食品）
               "jp.stock.3402",#東レ　（繊維）
               "jp.stock.3861",#王子HD（パルプ・紙）
               "jp.stock.4519",#中外薬（医薬品）
               "jp.stock.4452",#花王（化学）
               "jp.stock.5020",#JXTG（石油）
               "jp.stock.5108",#ブリヂストン（ゴム）
               "jp.stock.5201",#AGC（窯業）
               "jp.stock.5401",#新日鉄住金（鉄鋼）
               "jp.stock.5802",#住友電（非鉄金属製品）
               "jp.stock.6367",#ダイキン（機械）
               "jp.stock.6758",#ソニー（電気機器）
               "jp.stock.7012",#川重（造船）
               "jp.stock.7203",#トヨタ（自動車）
               "jp.stock.4543",#テルモ（精密機器）
               "jp.stock.7951",#ヤマハ（その他製造）
               "jp.stock.8058",#三菱商（商社）
               "jp.stock.9983",#ファストリ（小売業）
               "jp.stock.8306",#三菱UFJ（銀行）
               "jp.stock.8604",#野村（証券）
               "jp.stock.8766",#東京海上（保険）
               "jp.stock.8253",#クレゾン（その他金融）
               "jp.stock.8801",#三井不動産（不動産）
               "jp.stock.9022",#JR東海（鉄道）
               "jp.stock.9062",#日通（陸運）
               "jp.stock.9104",#商船三井（海運）
               "jp.stock.9202",#ANAHD（空運）
               "jp.stock.9301",#三菱倉（倉庫）
               "jp.stock.9437",#NTTドコモ（通信）
               "jp.stock.9503",#関西電（電力）
               "jp.stock.9531",#東ガス（ガス）
               "jp.stock.6178",#日本郵政（サービス）
          ],
          "columns": [
            #"open_price_adj",    # 始値(株式分割調整後)
            "high_price_adj",    # 高値(株式分割調整後)
            "low_price_adj",     # 安値(株式分割調整後)
            #"volume_adj",         # 出来高
            #"txn_volume",         # 売買代金
            "close_price",        # 終値
            "close_price_adj",    # 終値(株式分割調整後) 
          ]
        }
      }
    )

    def _my_signal(data):
      cp=data["close_price_adj"].fillna(method="ffill")
      hp=data["high_price_adj"].fillna(method="ffill")
      result1=pd.DataFrame(data=0,columns=[],index=cp.index)
      sample1=pd.DataFrame(data=0,columns=[],index=cp.index)
      result1=pd.DataFrame(data=0,columns=[],index=cp.index)
      sample3=pd.DataFrame(data=0,columns=[],index=cp.index)
      index3=pd.DataFrame(data=0,columns=[],index=cp.index)
      index6=pd.DataFrame(data=0,columns=[],index=cp.index)
      index7=pd.DataFrame(data=0,columns=[],index=cp.index)
      index8=pd.DataFrame(data=0,columns=[],index=cp.index)
      index12=pd.DataFrame(data=0,columns=[],index=cp.index)
      index13=pd.DataFrame(data=0,columns=[],index=cp.index)
      index14=pd.DataFrame(data=0,columns=[],index=cp.index)
      index1=data["high_price_adj"].fillna(method='ffill').rolling(window=9,center=False).max()
      index2=data["low_price_adj"].fillna(method="ffill").rolling(window=9,center=False).min()
      index3=(index1+index2)/2 #転換線
      index4=data["high_price_adj"].fillna(method='ffill').rolling(window=26,center=False).max()
      index5=data["low_price_adj"].fillna(method='ffill').rolling(window=26,center=False).min()
      index6=(index4+index5)/2 #基準線
      index7=(index3+index6)/2 
      index8=index7.shift(26) #先行スパン１
      index9=data["high_price_adj"].fillna(method='ffill').rolling(window=52,center=False).max()
      index10=data["low_price_adj"].fillna(method='ffill').rolling(window=52,center=False).min()
      index11=(index8+index9)/2 
      index12=index11.shift(26) #先行スパン2
      index13=index3-index6
      index14=index13.shift(1)
      index15=data["close_price_adj"].fillna(method='ffill').shift(26)
      
      buy_sig=index13[(index13>0)&(index14<0)]
      sell_sig=index13[(index13<0)&(index14>0)]
      return {
          "buy:sig":buy_sig,
          "sell:sig":sell_sig,
          "転換線:g2":index3,
          "基準線:g2":index6,
          "先行スパン1:g2":index8,
          "先行スパン2:g2":index12,
          "遅行線:g2":index15
        }

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

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

   


    buy = current["buy:sig"].dropna()
    for (sym,val) in buy.items():
       
        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():
        
        sec = ctx.getSecurity(sym)
        sec.order(sec.unit() * -1, comment="SIGNAL SELL")
        ctx.logger.debug("SELL: %s,  %f" % (sec.code(), val))
        pass
```

##今回やること
**先行スパン1本目**と**先行スパン2本目**の間の**雲**を用いたアルゴリズムを作成する‼️‼️

####まず雲の解釈について

終値が雲の下から雲上に到達し、クロスした点を**BUY**
終値が雲の上から雲上に到達し、クロスした点を**SELL**

としてみます。

####雲とのクロスを解釈するアルゴリズムがこちらです

まず、**データの格納倉庫**を増やしておきます.こちらのコードでできます。

```python:qiita2.py
      index15=pd.DataFrame(data=0,columns=[],index=cp.index)
      index16=pd.DataFrame(data=0,columns=[],index=cp.index)
      index17=pd.DataFrame(data=0,columns=[],index=cp.index)
      index18=pd.DataFrame(data=0,columns=[],index=cp.index)
      index19=pd.DataFrame(data=0,columns=[],index=cp.index)
      index20=pd.DataFrame(data=0,columns=[],index=cp.index)
      index21=pd.DataFrame(data=0,columns=[],index=cp.index)
```

次に、終値と雲とのクロスを計測するコードを加えます。

```python:qiita3.py
      index16=np.maximum(index8,index12)
      index17=np.minimum(index8,index12)
      index18=cp-index17
      index19=index18.shift()
      index20=cp-index16
      index21=index20.shift()
      
```

そして、最後に、**売買シグナルの規定**に条件を加えます。

```python:qiita4.py
     buy_sig=index18[(index18>0)&(index19<0)&(index13>0)&(index14<0)]
     sell_sig=index20[(index20<0)&(index21>0)&(index13<0)&(index14>0)]
```

**これで完成です**‼️‼️

完成版のアルゴリズムがこちらです

```python:qiita5.py
import numpy as np
import pandas as pd
import talib as ta

def initialize(ctx):
    # 設定
    ctx.logger.debug("initialize() called")
    ctx.configure(
      channels={          # 利用チャンネル
        "jp.stock": {
          "symbols": [
             "jp.stock.1333",#マルハニチロ（水産）
               "jp.stock.1605",#国際石開帝石（鉱業）
               "jp.stock.1925",#ハウス（建設）
               "jp.stock.2914",#JT（食品）
               "jp.stock.3402",#東レ　（繊維）
               "jp.stock.3861",#王子HD（パルプ・紙）
               "jp.stock.4519",#中外薬（医薬品）
               "jp.stock.4452",#花王（化学）
               "jp.stock.5020",#JXTG（石油）
               "jp.stock.5108",#ブリヂストン（ゴム）
               "jp.stock.5201",#AGC（窯業）
               "jp.stock.5401",#新日鉄住金（鉄鋼）
               "jp.stock.5802",#住友電（非鉄金属製品）
               "jp.stock.6367",#ダイキン（機械）
               "jp.stock.6758",#ソニー（電気機器）
               "jp.stock.7012",#川重（造船）
               "jp.stock.7203",#トヨタ（自動車）
               "jp.stock.4543",#テルモ（精密機器）
               "jp.stock.7951",#ヤマハ（その他製造）
               "jp.stock.8058",#三菱商（商社）
               "jp.stock.9983",#ファストリ（小売業）
               "jp.stock.8306",#三菱UFJ（銀行）
               "jp.stock.8604",#野村（証券）
               "jp.stock.8766",#東京海上（保険）
               "jp.stock.8253",#クレゾン（その他金融）
               "jp.stock.8801",#三井不動産（不動産）
               "jp.stock.9022",#JR東海（鉄道）
               "jp.stock.9062",#日通（陸運）
               "jp.stock.9104",#商船三井（海運）
               "jp.stock.9202",#ANAHD（空運）
               "jp.stock.9301",#三菱倉（倉庫）
               "jp.stock.9437",#NTTドコモ（通信）
               "jp.stock.9503",#関西電（電力）
               "jp.stock.9531",#東ガス（ガス）
               "jp.stock.6178",#日本郵政（サービス）
          ],
          "columns": [
            #"open_price_adj",    # 始値(株式分割調整後)
            "high_price_adj",    # 高値(株式分割調整後)
            "low_price_adj",     # 安値(株式分割調整後)
            #"volume_adj",         # 出来高
            #"txn_volume",         # 売買代金
            "close_price",        # 終値
            "close_price_adj",    # 終値(株式分割調整後) 
          ]
        }
      }
    )

    def _my_signal(data):
      cp=data["close_price_adj"].fillna(method="ffill")
      hp=data["high_price_adj"].fillna(method="ffill")
      result1=pd.DataFrame(data=0,columns=[],index=cp.index)
      sample1=pd.DataFrame(data=0,columns=[],index=cp.index)
      result1=pd.DataFrame(data=0,columns=[],index=cp.index)
      sample3=pd.DataFrame(data=0,columns=[],index=cp.index)
      index3=pd.DataFrame(data=0,columns=[],index=cp.index)
      index6=pd.DataFrame(data=0,columns=[],index=cp.index)
      index7=pd.DataFrame(data=0,columns=[],index=cp.index)
      index8=pd.DataFrame(data=0,columns=[],index=cp.index)
      index12=pd.DataFrame(data=0,columns=[],index=cp.index)
      index13=pd.DataFrame(data=0,columns=[],index=cp.index)
      index14=pd.DataFrame(data=0,columns=[],index=cp.index)
      index15=pd.DataFrame(data=0,columns=[],index=cp.index)
      index16=pd.DataFrame(data=0,columns=[],index=cp.index)
      index17=pd.DataFrame(data=0,columns=[],index=cp.index)
      index18=pd.DataFrame(data=0,columns=[],index=cp.index)
      index19=pd.DataFrame(data=0,columns=[],index=cp.index)
      index20=pd.DataFrame(data=0,columns=[],index=cp.index)
      index21=pd.DataFrame(data=0,columns=[],index=cp.index)
      index1=data["high_price_adj"].fillna(method='ffill').rolling(window=9,center=False).max()
      index2=data["low_price_adj"].fillna(method="ffill").rolling(window=9,center=False).min()
      index3=(index1+index2)/2 #転換線
      index4=data["high_price_adj"].fillna(method='ffill').rolling(window=26,center=False).max()
      index5=data["low_price_adj"].fillna(method='ffill').rolling(window=26,center=False).min()
      index6=(index4+index5)/2 #基準線
      index7=(index3+index6)/2 
      index8=index7.shift(26) #先行スパン１
      index9=data["high_price_adj"].fillna(method='ffill').rolling(window=52,center=False).max()
      index10=data["low_price_adj"].fillna(method='ffill').rolling(window=52,center=False).min()
      index11=(index8+index9)/2 
      index12=index11.shift(26) #先行スパン2
      index13=index3-index6
      index14=index13.shift()
      index15=data["close_price_adj"].fillna(method='ffill').shift(26)
      index16=np.maximum(index8,index12)
      index17=np.minimum(index8,index12)
      index18=cp-index17
      index19=index18.shift()
      index20=cp-index16
      index21=index20.shift()
      
      buy_sig=index18[(index18>0)&(index19<0)&(index13>0)&(index14<0)]
      sell_sig=index20[(index20<0)&(index21>0)&(index13<0)&(index14>0)]
      
      return {
          "buy:sig":buy_sig,
          "sell:sig":sell_sig,
          "転換線:g2":index3,
          "基準線:g2":index6,
          "先行スパン1:g2":index8,
          "先行スパン2:g2":index12,
          "遅行線:g2":index15,
          "先行スパン(大)":index16,
          "先行スパン(小)":index17
        }

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

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

   


    buy = current["buy:sig"].dropna()
    for (sym,val) in buy.items():
       
        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():
        
        sec = ctx.getSecurity(sym)
        sec.order(sec.unit() * -1, comment="SIGNAL SELL")
        ctx.logger.debug("SELL: %s,  %f" % (sec.code(), val))
        pass
```

##気になる結果は？

![スクリーンショット 2021-03-07 10.22.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305178/940d1f40-0db9-1b8b-36e2-2bc359e6fbac.png)

前回、**基準線と転換線のクロスだけ**を用いた時は、**3年**で**11%の利益**だったのが、**雲のクロス**を条件に加えることで**34%**にまで改善しました‼️‼️

シグナルはこんな感じです。
![スクリーンショット 2021-03-07 10.22.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305178/5dcfdf42-a179-0217-3519-13fbd59f115d.png)


**基準線と転換線のクロス**と**雲のクロス**が**同時に起こるところ**で売買シグナルを発したので、**雲の効果が分かりにくくなっている**ので、、、、

**雲だけでバックテスト**をしたものをお見せします

```python:qiita6.py
buy_sig=index18[(index18>0)&(index19<0)]
sell_sig=index20[(index20<0)&(index21>0)]
```
とすれば雲だけを条件にできます。

![スクリーンショット 2021-03-07 10.24.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305178/c22a2df9-dfc8-74a9-1e1c-145ca0732c53.png)

なかなか**いい売買シグナル**が出ています‼️‼️‼️

チャートを見る限り、上手く使えば、**雲は高い効果を発揮できそう**です。
株式銘柄をいじってみると、結果が上がる予感がします:smile:


バックテスト結果が上がり次第、記事を書くので、**続編**をお待ちください:pray:
**ご購読ありがとうございました**:yum::yum::yum::yum:

##免責注意事項
このコード・知識を使った実際の取引で生じた損益に関しては一切の責任を負いかねますので御了承下さい。また、内容には注意を払っていますが、その正確性を一切保証いたしませんので御了承ください。