2021-12-21 17:28:36 +01:00
from utils.load_data import load_data
2021-12-14 18:16:17 +01:00
import pandas as pd
2021-12-21 17:28:36 +01:00
from training.training import run_single_asset_trainig
2021-12-23 10:35:20 +01:00
from reporting.wandb import launch_wandb , send_report_to_wandb , register_config_with_wandb
2021-12-21 17:28:36 +01:00
from models.model_map import map_model_name_to_function
2021-12-23 10:35:20 +01:00
from feature_extractors.feature_extractor_presets import preprocess_feature_extractors_config
2021-12-22 12:04:38 +01:00
from config import get_default_config , validate_config , get_model_name
2021-12-26 12:15:11 +01:00
from utils.helpers import get_first_valid_return_index , weighted_average
2021-12-14 18:16:17 +01:00
2021-12-21 17:28:36 +01:00
def setup_pipeline ( project_name : str , with_wandb : bool , sweep : bool ):
model_config , training_config , data_config = get_default_config ()
2021-12-20 17:49:11 +01:00
wandb = None
if with_wandb :
2021-12-21 17:28:36 +01:00
wandb = launch_wandb ( project_name = project_name , default_config = dict ( ** model_config , ** training_config , ** data_config ), sweep = sweep )
2021-12-23 10:35:20 +01:00
register_config_with_wandb ( wandb , model_config , training_config , data_config )
2021-12-21 17:28:36 +01:00
model_config = map_model_name_to_function ( model_config , data_config [ 'method' ])
2021-12-23 10:35:20 +01:00
data_config = preprocess_feature_extractors_config ( data_config )
2021-12-21 17:28:36 +01:00
pipeline ( project_name , wandb , sweep , model_config , training_config , data_config )
2021-12-20 17:49:11 +01:00
2021-12-20 14:01:14 +01:00
2021-12-22 12:04:38 +01:00
2021-12-26 12:15:11 +01:00
def pipeline ( project_name : str , wandb , sweep : bool , model_config : dict , training_config : dict , data_config : dict ):
2021-12-20 17:49:11 +01:00
results = pd . DataFrame ()
2021-12-22 12:04:38 +01:00
validate_config ( model_config , training_config , data_config )
2021-12-14 22:59:44 +01:00
2021-12-20 17:49:11 +01:00
for asset in data_config [ 'all_assets' ]:
print ( '-------- \n Predicting: ' , asset )
all_predictions = pd . DataFrame ()
2021-12-15 21:11:12 +01:00
2021-12-20 17:49:11 +01:00
# 1. Load data
data_params = data_config . copy ()
data_params [ 'target_asset' ] = asset
2021-12-14 22:59:44 +01:00
2021-12-20 17:49:11 +01:00
X , y , target_returns = load_data ( ** data_params )
2021-12-23 23:48:59 +01:00
first_valid_index = get_first_valid_return_index ( X . iloc [:, 0 ])
samples_to_train = len ( y ) - first_valid_index
2021-12-26 12:15:11 +01:00
if samples_to_train < training_config [ 'sliding_window_size' ] * 3 :
2021-12-23 23:48:59 +01:00
print ( "Not enough samples to train" )
continue
2021-12-17 14:32:17 +01:00
2021-12-20 17:49:11 +01:00
# 2. Train Level-1 models
2021-12-21 17:28:36 +01:00
current_result , current_predictions = run_single_asset_trainig (
2021-12-20 17:49:11 +01:00
ticker_to_predict = asset ,
X = X ,
y = y ,
target_returns = target_returns ,
2021-12-21 09:23:06 +01:00
models = model_config [ 'level_1_models' ],
2021-12-20 17:49:11 +01:00
method = data_config [ 'method' ],
2021-12-22 16:59:03 +01:00
expanding_window = training_config [ 'expanding_window' ],
2021-12-20 17:49:11 +01:00
sliding_window_size = training_config [ 'sliding_window_size' ],
retrain_every = training_config [ 'retrain_every' ],
scaler = training_config [ 'scaler' ],
2021-12-23 23:48:59 +01:00
no_of_classes = data_config [ 'no_of_classes' ],
level = 1
2021-12-20 17:49:11 +01:00
)
results = pd . concat ([ results , current_result ], axis = 1 )
all_predictions = pd . concat ([ all_predictions , current_predictions ], axis = 1 )
2021-12-17 14:32:17 +01:00
2021-12-21 17:28:36 +01:00
if len ( model_config [ 'level_2_models' ]) > 0 :
# 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 )
2021-12-17 14:32:17 +01:00
2021-12-21 17:28:36 +01:00
ensemble_result , ensemble_preds = run_single_asset_trainig (
ticker_to_predict = asset ,
X = ensemble_X ,
y = y ,
target_returns = target_returns ,
models = model_config [ 'level_2_models' ],
method = data_config [ 'method' ],
2021-12-22 16:59:03 +01:00
expanding_window = training_config [ 'expanding_window' ],
2021-12-21 17:28:36 +01:00
sliding_window_size = training_config [ 'sliding_window_size' ],
retrain_every = training_config [ 'retrain_every' ],
scaler = training_config [ 'scaler' ],
2021-12-23 23:48:59 +01:00
no_of_classes = data_config [ 'no_of_classes' ],
level = 2
2021-12-21 17:28:36 +01:00
)
2021-12-20 17:49:11 +01:00
2021-12-21 17:28:36 +01:00
results = pd . concat ([ results , ensemble_result ], axis = 1 )
all_predictions = pd . concat ([ all_predictions , ensemble_preds ], axis = 1 )
2021-12-22 12:04:38 +01:00
# 4. Save & report results
2021-12-20 17:49:11 +01:00
results . to_csv ( 'results.csv' )
2021-12-26 12:15:11 +01:00
level1_columns = results [[ column for column in results . columns if 'lvl1' in column ]]
level2_columns = results [[ column for column in results . columns if 'lvl2' in column ]]
# Only send the results of the final model to wandb
results_to_send = level2_columns if level2_columns . shape [ 1 ] > 0 else level1_columns
send_report_to_wandb ( results_to_send , wandb , project_name , get_model_name ( model_config ))
2021-12-20 17:49:11 +01:00
2021-12-23 17:06:22 +01:00
print ( " \n -------- \n " )
2021-12-26 12:15:11 +01:00
print ( "Benchmark buy-and-hold sharpe: " , round ( weighted_average ( results , 'no_of_samples' ) . loc [ 'benchmark_sharpe' ], 3 ))
2021-12-23 17:06:22 +01:00
print ( "Level-1: Number of samples evaluated: " , level1_columns . loc [ 'no_of_samples' ] . sum ())
2021-12-26 12:15:11 +01:00
print ( "Mean Sharpe ratio for Level-1 models: " , round ( weighted_average ( level1_columns , 'no_of_samples' ) . loc [ 'sharpe' ], 3 ))
print ( "Mean Probabilistic Sharpe ratio for Level-1 models: " , round ( weighted_average ( level1_columns , 'no_of_samples' ) . loc [ 'prob_sharpe' ] . mean (), 3 ))
2021-12-23 17:06:22 +01:00
2021-12-26 12:15:11 +01:00
print ( "Level-2 (Ensemble): Number of samples evaluated: " , level2_columns . loc [ 'no_of_samples' ] . sum ())
print ( "Mean Sharpe ratio for Level-2 (Ensemble) models: " , round ( weighted_average ( level2_columns , 'no_of_samples' ) . loc [ 'sharpe' ] . mean (), 3 ))
print ( "Mean Probabilistic Sharpe ratio for Level-2 (Ensemble) models: " , round ( weighted_average ( level2_columns , 'no_of_samples' ) . loc [ 'prob_sharpe' ] . mean (), 3 ))
2021-12-17 14:32:17 +01:00
2021-12-21 17:28:36 +01:00
if sweep :
if wandb . run is not None :
wandb . finish ()
2021-12-20 14:01:14 +01:00
2021-12-20 17:49:11 +01:00
if __name__ == '__main__' :
2021-12-21 17:28:36 +01:00
setup_pipeline ( project_name = 'price-prediction' , with_wandb = False , sweep = False )