📌

SIGNATE日本取引所グループ ニュース分析チャレンジ[モデル構築編2]

2021/04/30に公開

SIGNATE日本取引所グループ ニュース分析チャレンジ[モデル構築編1][1]の続き

ルール

  • 100万円を元手に月曜日にポートフォリを組み(買い)、金曜日にすべて売る
  • 途中で売り買いできない
  • 5銘柄以上 and 50万円以上の買いが必須

戦略

  • 予測対象: リターン((金曜日のclose価格 - 月曜日のopen価格) / 月曜日のopen価格)
  • 予測に基づきポートフォリを組む (とりあえずtop8の銘柄を12.5万円で買う)

特徴量

前回の記事で使った特徴量に加えてreturnも特徴量として加える

def create_numeric_feature(input_df):
    all_columns = set(input_df.keys())
    except_columns = set(['EndOfDayQuote CumulativeAdjustmentFactor', 'EndOfDayQuote PreviousCloseDate', 'EndOfDayQuote PreviousExchangeOfficialCloseDate'])
    use_columns = all_columns - except_columns
    return input_df[use_columns].copy()
    
def create_talib_feature(input_df):
    out_df = []
    target_label = 'EndOfDayQuote ExchangeOfficialClose'
    for target_code in tqdm(input_df['Local Code'].unique()):
        ret = {}
        df = input_df.loc[input_df.loc[:, 'Local Code']==target_code, target_label]
        prices = np.array(df, dtype='f8')
    
        ret['rsi7'] = ta.RSI(prices, timeperiod=7)
        ret['sma14'] = ta.SMA(prices, timeperiod=14)
        ret['sma7'] = ta.SMA(prices, timeperiod=7)
        ret['bb_up'], ret['bb_mid'], ret['bb_low'] = ta.BBANDS(prices, timeperiod=14)
        ret['mom'] = ta.MOM(prices, timeperiod=14)
        tmp_df = pd.DataFrame(ret, index=df.index)
        ret['sma7_diff'] = tmp_df['sma7'].diff()
        ret['sma14_diff'] = tmp_df['sma14'].diff()
        ret['sma_diff'] =tmp_df['sma7'] -tmp_df['sma14']
        ret['bb_diff'] = tmp_df['bb_mid'] - tmp_df['bb_up']
        code_df = pd.DataFrame(ret, index=df.index)
        out_df.append(code_df)
    return pd.concat(out_df, axis=0)

def create_return_feature(input_df):
    out_df = []
    target_label = 'EndOfDayQuote ExchangeOfficialClose'
    for target_code in tqdm(input_df['Local Code'].unique()):
        ret = {}
        df = input_df.loc[input_df.loc[:, 'Local Code'] == target_code, target_label]
        ret['retrun1'] = input_df[input_df['Local Code'] == target_code][target_label].pct_change(periods=1)
        ret['retrun7'] = input_df[input_df['Local Code'] == target_code][target_label].pct_change(periods=7)
        ret['retrun14'] = input_df[input_df['Local Code'] == target_code][target_label].pct_change(periods=14)
        code_df = pd.DataFrame(ret, index=df.index)
        out_df.append(code_df)
    return pd.concat(out_df, axis=0)    

上記の関数から特徴量を作っていく

def to_feature(input_df):
    processors = [
        create_numeric_feature,
        create_talib_feature,
        create_return_feature
    ]

    out_df = pd.DataFrame()

    for func in tqdm(processors, total=len(processors)):
        with Timer(prefix='create' + func.__name__ + ' '):
            _df = func(input_df)

        # 長さが等しいことをチェック (ずれている場合, func の実装がおかしい)
        assert len(_df) == len(input_df), func.__name__
        out_df = pd.concat([out_df, _df], axis=1)
    return out_df

学習はLight gbmを使う

結果

1週間のリターンが 9.99% (前回より上がった
TestのRMSLE: score 4.49e-05 (精度ですぎ、リークしてる??

選択した各銘柄のリターン

選んだ銘柄は安定して高いリターンを出している!

予測に聞いた特徴量ベクトルの解析

予測には株価自体よりリターンが効いている。

つづく[2]

脚注
  1. 前記事 ↩︎

  2. 次の記事 ↩︎

Discussion