9
4

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 5 years have passed since last update.

[注意]100%勝ってしまうシグナル #QuantX

Last updated at Posted at 2018-08-15

100% 勝ってしまった

QuantXでアルゴリズムを書く方法を投稿していたのですが,ふと100%勝てるシグナルが書けるんじゃない?と思って書いてみたら書けたというお話です. 

とりあえず結果を.

2018-08-15_15.jpg

天国や:hotsprings:

Look-Ahead Bias

コレは現実のシグナルでは絶対に起きない, Look-Ahead Biasという間違いです.

株価分析を行う上でのルックアヘッドとは,誤って将来の価格を分析対象に入れて予測を行ってしまうことを言います.

QuantXのバックテストでは,(私の想像がただしければ)指定された全期間のヒストリカルデータを取得して売買シグナルを計算し,その後,該当日の買いシグナルおよび売りシグナルに基づいて損益を計算する仕様になっています.

つまり,コードの書き方を間違うと,シグナル計算時に誤って将来のデータが入る可能性があるわけです.

実際のコードがこちらです.

def initialize(ctx):
    # 設定
    ctx.target = 0.10
    ctx.period = 5
    ctx.codes = [1605, 1925, 2503, 4519, 4911, 6301, 6752, 7741, 8001 ]
    ctx.symbol_list  = ["jp.stock.{}".format(code) for code in ctx.codes]
    
    
    ctx.configure(
      channels={ 
        "jp.stock": {
          "symbols":ctx.symbol_list,
          "columns": ["close_price_adj",
          ]}})

    def _NOTCORRECT_SIGNAL(data):
      
      df_close = data["close_price_adj"].fillna(method='ffill')
      df_cheat_close = df_close.pct_change().shift(-2) ## <----- ここ!!!!!!!!!
      buy_sig = df_cheat_close > 0 
      sell_sig = buy_sig.shift(1) == True
      
      return {
        "cheat":df_cheat_close, 
        "buy:sig": buy_sig, 
        "sell:sig": sell_sig, 
          
        }

    # シグナル登録
    ctx.regist_signal("NOTCORRECT_SIGNAL", _NOTCORRECT_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)
        msg = "買いシグナル"
        sec.order_target_percent(ctx.target, comment= msg)

    # 売り(ポジションクローズ)シグナル
    df_sell = df[df["sell:sig"]]
    if not df_sell.empty:
      for (sym, val) in df_sell.iterrows(): 
        sec = ctx.getSecurity(sym)
        msg = "売りシグナル"
        sec.order_target_percent(0, comment= msg)

上記 df_cheat_close = df_close.pct_change().shift(-2)が Look-Ahead 部分です.

df_closeは,pandas.DataFrame型です.メソッドである shift を使うと,データを前後(表形式で見れば上下)に動かすことができます.ただし,Index(ここでは日付)は動きません.

例;

import pandas as pd 
rng = pd.date_range('1/1/2018',periods=4,freq='D')
df = pd.DataFrame({'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,120,110,150]}, index=rng)

2018-08-15_17.jpg

今回書いたQuantXのコードでは,df_cheat_close = df_close.pct_change().shift(-2)と書くことで,2日後の変化率を取得し,ポジティブであれば,買いシグナルを出すという方法で100%勝てるシグナルを作りました.

QuantXでは,シグナルの算出タイミングと,実際の取引するタイミングは異なります.
シグナルは,今日の終値が確定した後,つまり午後三時の大引け後算出し,取引は翌日の大引け時に行います.

例を上げると,このような日程になります

8月15日 8月16日15時以降 8月17日15時 8月18日15時
Buysig発生 買い取引 評価損益

よって,17日から18日が値上がりすることがわかっていれば,16日にBuyシグナルを出せばよいということになります.
従って,shift(-2)でその情報を得ると,シグナルが出せるわけです.

ぬかよろこびはできます

look-ahead bias は,現実には起きませんが,バックテストでぬかよろこびすることはできます:angel:
みなさんはこんな間違いはしないと思いますが,複雑なアルゴリズムを書いていると,こういうケアレスミスだけど,致命的なミスは入りがちです.shift()メソッドはとても便利ですが,注意してお使い下さい.

9
4
1

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
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?