第7章 線形モデル編: 第6節 Alphalensを用いて分析する

はじめに

Alphalensとは?

Alphalensとは分析に特化したpythonライブラリです。今回は本ライブラリを用いて特徴量分析を行いたいと思います。モチベーションとしましては、前回の記事で予測値を出しましたが、観測値と予測値を分析するにあたって、ICを見るだけでは物足りないので、もっと細かく分析しようという話です。

alphalensのgithubはこちらをご参照ください。

インポートと設定

import warnings
warnings.filterwarnings('ignore')
from pathlib import Path
import pandas as pd
from alphalens.tears import create_summary_tear_sheet
from alphalens.utils import get_clean_factor_and_forward_returns
idx = pd.IndexSlice

データの読み込み

こちらでは前回の記事で第7章 線形モデル編: 第5節 線形回帰で株価予測をするで行った3つのモデルの出力結果を読み込みます。データセットのフォーマットとしてはscoresは残差や情報係数、アルファの情報が入っていて、predictionsが観測値と予測値である。

画像1

with pd.HDFStore('data.h5') as store:
   lr_predictions = store['lr/predictions']
   lasso_predictions = store['lasso/predictions']
   lasso_scores = store['lasso/scores']
   ridge_predictions = store['ridge/predictions']
   ridge_scores = store['ridge/scores']
DATA_STORE = Path('..', 'data', 'assets.h5')
def get_trade_prices(tickers, start, stop):
   prices = (pd.read_hdf(DATA_STORE, 'quandl/wiki/prices').swaplevel().sort_index())
   prices.index.names = ['symbol', 'date']
   prices = prices.loc[idx[tickers, str(start):str(stop)], 'adj_open']
   return (prices
           .unstack('symbol')
           .sort_index()
           .shift(-1)
           .tz_localize('UTC'))
def get_best_alpha(scores):
   return scores.groupby('alpha').ic.mean().idxmax()
def get_factor(predictions):
   return (predictions.unstack('symbol')
           .dropna(how='all')
           .stack()
           .tz_localize('UTC', level='date')
           .sort_index())    

線形回帰

lr_factor = get_factor(lr_predictions.predicted.swaplevel())
lr_factor.head()
'''
date                       symbol
2014-12-09 00:00:00+00:00  AAL       0.001839
                          AAPL     -0.001534
                          ABBV      0.001316
                          AGN       0.002175
                          AIG      -0.000336
dtype: float64
'''
tickers = lr_factor.index.get_level_values('symbol').unique()
trade_prices = get_trade_prices(tickers, 2014, 2017)
trade_prices.info()
'''
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1007 entries, 2014-01-02 00:00:00+00:00 to 2017-12-29 00:00:00+00:00
Columns: 257 entries, AAL to YUM
dtypes: float64(257)
memory usage: 2.0 MB
'''
lr_factor_data = get_clean_factor_and_forward_returns(factor=lr_factor,
                                                     prices=trade_prices,
                                                     quantiles=5,
                                                     periods=(1, 5, 10, 21))
lr_factor_data.info()
'''
Dropped 0.0% entries from factor data: 0.0% in forward returns computation and 0.0% in binning phase (set max_loss=0 to see potentially suppressed Exceptions).
max_loss is 35.0%, not exceeded: OK!
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 74054 entries, (Timestamp('2014-12-09 00:00:00+0000', tz='UTC'), 'AAL') to (Timestamp('2017-11-29 00:00:00+0000', tz='UTC'), 'XOM')
Data columns (total 6 columns):
#   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
0   1D               74054 non-null  float64
1   5D               74054 non-null  float64
2   10D              74054 non-null  float64
3   21D              74054 non-null  float64
4   factor           74054 non-null  float64
5   factor_quantile  74054 non-null  int64  
dtypes: float64(5), int64(1)
memory usage: 3.7+ MB
'''

ここでget_clean_factor_and_forward_returnsは日次データから複数のフォワードリターン(periods指定)と分位数を指定する。分位数は、ファクターをランキング付けたもので、今回は5段階評価している。最小値から最大値までを均等に5分割して、ファクターがどの階級に入っているのかを表している。これからそこも含めて詳しく分析する。

画像8

create_summary_tear_sheet(lr_factor_data);

画像2

画像3

これらの表と図がalphalens.tears.create_summary_tear_sheetで一気に呼べるんですね。残り2つの回帰に関しても同じことをやるので、解説は割愛します。

リッジ回帰

best_ridge_alpha = get_best_alpha(ridge_scores)
ridge_predictions = ridge_predictions[ridge_predictions.alpha==best_ridge_alpha].drop('alpha', axis=1)
ridge_factor = get_factor(ridge_predictions.predicted.swaplevel())
ridge_factor_data = get_clean_factor_and_forward_returns(factor=ridge_factor,
                                                        prices=trade_prices,
                                                        quantiles=5,
                                                        periods=(1, 5, 10, 21))
create_summary_tear_sheet(ridge_factor_data);

画像4

画像5

ラッソ回帰

best_lasso_alpha = get_best_alpha(lasso_scores)
lasso_predictions = lasso_predictions[lasso_predictions.alpha==best_lasso_alpha].drop('alpha', axis=1)
lasso_factor = get_factor(lasso_predictions.predicted.swaplevel())
lasso_factor_data = get_clean_factor_and_forward_returns(factor=lasso_factor,
                                                     prices=trade_prices,
                                                     quantiles=5,
                                                     periods=(1, 5, 10, 21))
create_summary_tear_sheet(lasso_factor_data);

画像6

画像7





この記事が気に入ったらサポートをしてみませんか?