Files
drift/run_pipeline.py
T
Mark Aron Szulyovszky d3d7184ea4 feat(Models): added StaticAverageModel for average ensembling & StaticNaiveModel (#64)
* feat(Models): added StaticAverageModel for average ensembling

* feat(Models): made sure we only pipe in predictions to StaticAverageModel, added StaticNaiveModel as potential baseline

* chore(Models): removed unnecessary commented out code
2021-12-21 15:57:08 +01:00

174 lines
7.0 KiB
Python

from sklearnex import patch_sklearn
patch_sklearn()
from utils.load_data import get_crypto_assets, get_etf_assets, load_data
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression, Lasso, BayesianRidge, LogisticRegression, Ridge
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsRegressor, KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.svm import SVR
from sklearn.naive_bayes import GaussianNB
from sklearn.neural_network import MLPRegressor, MLPClassifier
from sklearn.ensemble import AdaBoostRegressor, RandomForestRegressor, ExtraTreesRegressor, AdaBoostClassifier, GradientBoostingClassifier, RandomForestClassifier, ExtraTreesClassifier
from models.base import SKLearnModel
from models.momentum import StaticMomentumModel
from models.average import StaticAverageModel
from models.naive import StaticNaiveModel
import feature_extractors.feature_extractor_presets as feature_extractor_presets
from training.pipeline import run_single_asset_trainig_pipeline
def get_config() -> tuple[dict, dict, dict]:
training_config = dict(
sliding_window_size = 150,
retrain_every = 20,
scaler = 'minmax', # 'normalize' 'minmax' 'standardize' 'none'
include_original_data_in_ensemble = True,
)
data_config = dict(
path='data/',
all_assets = get_crypto_assets('data/'),
load_other_assets= False,
log_returns= True,
forecasting_horizon = 1,
own_features= feature_extractor_presets.date + feature_extractor_presets.level1,
other_features= [],
index_column= 'int',
method= 'classification',
)
regression_models = [
# ('Lasso', SKLearnModel(Lasso(alpha=0.1, max_iter=1000))),
('Ridge', SKLearnModel(Ridge(alpha=0.1))),
('BayesianRidge', SKLearnModel(BayesianRidge())),
# ('KNN', SKLearnModel(KNeighborsRegressor(n_neighbors=25))),
# ('AB', SKLearnModel(AdaBoostRegressor(random_state=1))),
# ('LR', SKLearnModel(LinearRegression(n_jobs=-1))),
# ('MLP', SKLearnModel(MLPRegressor(hidden_layer_sizes=(100,20), max_iter=1000))),
# ('RF', SKLearnModel(RandomForestRegressor(n_jobs=-1))),
# ('SVR', SKLearnModel(SVR(kernel='rbf', C=1e3, gamma=0.1)))
]
regression_ensemble_model = [('Ensemble - Average', StaticAverageModel())]
# regression_ensemble_model = [('Ensemble - Ridge', SKLearnModel(Ridge(alpha=0.1)))]
classification_models = [
('LR', SKLearnModel(LogisticRegression(n_jobs=-1))),
('LDA', SKLearnModel(LinearDiscriminantAnalysis())),
('KNN', SKLearnModel(KNeighborsClassifier())),
('CART', SKLearnModel(DecisionTreeClassifier())),
('StaticMomentum', StaticMomentumModel(allow_short=True)),
# ('StaticNaive', StaticNaiveModel()),
# ('NB', SKLearnModel(GaussianNB())),
# ('AB', SKLearnModel(AdaBoostClassifier())),
# ('RF', SKLearnModel(RandomForestClassifier(n_jobs=-1)))
]
classification_ensemble_model = [('Ensemble - Average', StaticAverageModel())]
# classification_ensemble_model = [('Ensemble - CART', SKLearnModel(DecisionTreeClassifier()))]
model_config = dict(
level_1_models = regression_models if data_config['method'] == 'regression' else classification_models,
level_2_model = regression_ensemble_model if data_config['method'] == 'regression' else classification_ensemble_model,
)
return model_config, training_config, data_config
def launch_wandb(config, sweep=False):
from wandb_setup import get_wandb
wandb = get_wandb()
if type(wandb) == type(None):
return None
elif sweep:
wandb.init(project="price-forecasting", config = config)
return wandb
else:
wandb.init(project="price-forecasting", config=config, reinit=True)
return wandb
def run_pipeline(with_wandb: bool, sweep: bool):
model_config, training_config, data_config = get_config()
wandb = None
if with_wandb:
wandb = launch_wandb(dict(**model_config, **training_config, **data_config), sweep)
if type(wandb) is not type(None):
for k in training_config: training_config[k] = wandb.config[k]
# for k in model_config: model_config[k] = wandb.config[k]
# for k in data_config: data_config[k] = wandb.config[k]
pipeline(model_config, training_config, data_config, wandb)
# Run pipeline
def pipeline(model_config:dict, training_config:dict, data_config:dict, wandb):
results = pd.DataFrame()
for asset in data_config['all_assets']:
print('--------\nPredicting: ', asset)
all_predictions = pd.DataFrame()
# 1. Load data
data_params = data_config.copy()
data_params['target_asset'] = asset
X, y, target_returns = load_data(**data_params)
# 2. Train Level-1 models
current_result, current_predictions = run_single_asset_trainig_pipeline(
ticker_to_predict = asset,
X = X,
y = y,
target_returns = target_returns,
models = model_config['level_1_models'],
method = data_config['method'],
sliding_window_size = training_config['sliding_window_size'],
retrain_every = training_config['retrain_every'],
scaler = training_config['scaler'],
wandb = wandb
)
results = pd.concat([results, current_result], axis=1)
all_predictions = pd.concat([all_predictions, current_predictions], axis=1)
# 3. Train Level-2 (Ensemble) model
ensemble_X = all_predictions
if training_config['include_original_data_in_ensemble']:
ensemble_X = pd.concat([ensemble_X, X], axis=1)
ensemble_result, ensemble_preds = run_single_asset_trainig_pipeline(
ticker_to_predict = asset,
X = ensemble_X,
y = y,
target_returns = target_returns,
models = model_config['level_2_model'],
method = data_config['method'],
sliding_window_size = training_config['sliding_window_size'],
retrain_every = training_config['retrain_every'],
scaler = training_config['scaler'],
wandb = wandb
)
results = pd.concat([results, ensemble_result], axis=1)
all_predictions = pd.concat([all_predictions, ensemble_preds], axis=1)
results.to_csv('results.csv')
level1_columns = results[[column for column in results.columns if 'Ensemble' not in column]]
ensemble_columns = results[[column for column in results.columns if 'Ensemble' in column]]
print("Mean Sharpe ratio for Level-1 models: ", level1_columns.loc['sharpe'].mean())
print("Mean Sharpe ratio for Level-2 (Ensemble) models: ", ensemble_columns.loc['sharpe'].mean())
if __name__ == '__main__':
run_pipeline(with_wandb = False, sweep = False)