8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FinTechAdvent Calendar 2018

Day 14

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

Last updated at Posted at 2018-12-14

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

という感じです。

###基準線と転換線のクロスを用いた
詳しくはQuantXで一目均衡表を作ってみた(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) #先行スパン1
      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

としてみます。

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

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

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)

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

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

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

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

これで完成です‼️‼️

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

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) #先行スパン1
      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

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

シグナルはこんな感じです。
スクリーンショット 2021-03-07 10.22.55.png

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

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

qiita6.py
buy_sig=index18[(index18>0)&(index19<0)]
sell_sig=index20[(index20<0)&(index21>0)]

とすれば雲だけを条件にできます。

スクリーンショット 2021-03-07 10.24.37.png

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

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

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

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

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?