mirror of
https://github.com/webclinic017/drift.git
synced 2026-08-19 05:48:09 +00:00
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
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
from models.base import Model
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class StaticAverageModel(Model):
|
||||||
|
'''
|
||||||
|
Model that averages .
|
||||||
|
'''
|
||||||
|
|
||||||
|
# data_format = 'dataframe'
|
||||||
|
data_scaling = 'unscaled'
|
||||||
|
only_column = 'model_'
|
||||||
|
|
||||||
|
def fit(self, X, y):
|
||||||
|
# This is a static model, it can' learn anything
|
||||||
|
pass
|
||||||
|
|
||||||
|
def predict(self, X):
|
||||||
|
# Make sure there's data to average
|
||||||
|
assert X.shape[1] > 0
|
||||||
|
prediction = np.average(X[0])
|
||||||
|
return np.array([prediction])
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
return self
|
||||||
+5
-1
@@ -1,20 +1,24 @@
|
|||||||
|
|
||||||
from typing import Literal, Optional
|
from typing import Literal, Optional
|
||||||
from sklearn.base import clone
|
from sklearn.base import clone
|
||||||
|
from abc import ABC, abstractmethod, abstractproperty
|
||||||
|
|
||||||
class Model:
|
class Model(ABC):
|
||||||
|
|
||||||
# data_format: Literal['dataframe', 'numpy']
|
# data_format: Literal['dataframe', 'numpy']
|
||||||
data_scaling: Literal["scaled", "unscaled"]
|
data_scaling: Literal["scaled", "unscaled"]
|
||||||
# data_format: Literal["wide", "narrow"]
|
# data_format: Literal["wide", "narrow"]
|
||||||
only_column: Optional[str]
|
only_column: Optional[str]
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def fit(self, X, y):
|
def fit(self, X, y):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def predict(self, X):
|
def predict(self, X):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def clone(self):
|
def clone(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ class StaticMomentumModel(Model):
|
|||||||
Model that uses only one feature: momentum. It's positive if momentum is greater than 0, otherwise it's negative.
|
Model that uses only one feature: momentum. It's positive if momentum is greater than 0, otherwise it's negative.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
data_format = 'dataframe'
|
# data_format = 'dataframe'
|
||||||
data_scaling = 'unscaled'
|
data_scaling = 'unscaled'
|
||||||
only_column = 'mom'
|
only_column = 'mom'
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
from models.base import Model
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class StaticNaiveModel(Model):
|
||||||
|
'''
|
||||||
|
Model that carries the last observation (from returns) to the next one, naively.
|
||||||
|
'''
|
||||||
|
|
||||||
|
# data_format = 'dataframe'
|
||||||
|
data_scaling = 'unscaled'
|
||||||
|
only_column = None
|
||||||
|
|
||||||
|
def fit(self, X, y):
|
||||||
|
# This is a static model, it can' learn anything
|
||||||
|
pass
|
||||||
|
|
||||||
|
def predict(self, X):
|
||||||
|
return np.array([X[-1][0]])
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
return self
|
||||||
+11
-6
@@ -15,6 +15,8 @@ from sklearn.neural_network import MLPRegressor, MLPClassifier
|
|||||||
from sklearn.ensemble import AdaBoostRegressor, RandomForestRegressor, ExtraTreesRegressor, AdaBoostClassifier, GradientBoostingClassifier, RandomForestClassifier, ExtraTreesClassifier
|
from sklearn.ensemble import AdaBoostRegressor, RandomForestRegressor, ExtraTreesRegressor, AdaBoostClassifier, GradientBoostingClassifier, RandomForestClassifier, ExtraTreesClassifier
|
||||||
from models.base import SKLearnModel
|
from models.base import SKLearnModel
|
||||||
from models.momentum import StaticMomentumModel
|
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
|
import feature_extractors.feature_extractor_presets as feature_extractor_presets
|
||||||
from training.pipeline import run_single_asset_trainig_pipeline
|
from training.pipeline import run_single_asset_trainig_pipeline
|
||||||
@@ -53,19 +55,22 @@ def get_config() -> tuple[dict, dict, dict]:
|
|||||||
# ('RF', SKLearnModel(RandomForestRegressor(n_jobs=-1))),
|
# ('RF', SKLearnModel(RandomForestRegressor(n_jobs=-1))),
|
||||||
# ('SVR', SKLearnModel(SVR(kernel='rbf', C=1e3, gamma=0.1)))
|
# ('SVR', SKLearnModel(SVR(kernel='rbf', C=1e3, gamma=0.1)))
|
||||||
]
|
]
|
||||||
regression_ensemble_model = [('Ensemble - Ridge', SKLearnModel(Ridge(alpha=0.1)))]
|
regression_ensemble_model = [('Ensemble - Average', StaticAverageModel())]
|
||||||
|
# regression_ensemble_model = [('Ensemble - Ridge', SKLearnModel(Ridge(alpha=0.1)))]
|
||||||
|
|
||||||
classification_models = [
|
classification_models = [
|
||||||
('LR', SKLearnModel(LogisticRegression(n_jobs=-1))),
|
('LR', SKLearnModel(LogisticRegression(n_jobs=-1))),
|
||||||
# ('LDA', SKLearnModel(LinearDiscriminantAnalysis())),
|
('LDA', SKLearnModel(LinearDiscriminantAnalysis())),
|
||||||
# ('KNN', SKLearnModel(KNeighborsClassifier())),
|
('KNN', SKLearnModel(KNeighborsClassifier())),
|
||||||
# ('CART', SKLearnModel(DecisionTreeClassifier())),
|
('CART', SKLearnModel(DecisionTreeClassifier())),
|
||||||
('StaticMomentum', StaticMomentumModel(allow_short=True))
|
('StaticMomentum', StaticMomentumModel(allow_short=True)),
|
||||||
|
# ('StaticNaive', StaticNaiveModel()),
|
||||||
# ('NB', SKLearnModel(GaussianNB())),
|
# ('NB', SKLearnModel(GaussianNB())),
|
||||||
# ('AB', SKLearnModel(AdaBoostClassifier())),
|
# ('AB', SKLearnModel(AdaBoostClassifier())),
|
||||||
# ('RF', SKLearnModel(RandomForestClassifier(n_jobs=-1)))
|
# ('RF', SKLearnModel(RandomForestClassifier(n_jobs=-1)))
|
||||||
]
|
]
|
||||||
classification_ensemble_model = [('Ensemble - CART', SKLearnModel(DecisionTreeClassifier()))]
|
classification_ensemble_model = [('Ensemble - Average', StaticAverageModel())]
|
||||||
|
# classification_ensemble_model = [('Ensemble - CART', SKLearnModel(DecisionTreeClassifier()))]
|
||||||
|
|
||||||
model_config = dict(
|
model_config = dict(
|
||||||
level_1_models = regression_models if data_config['method'] == 'regression' else classification_models,
|
level_1_models = regression_models if data_config['method'] == 'regression' else classification_models,
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ def run_single_asset_trainig_pipeline(
|
|||||||
)
|
)
|
||||||
column_name = ticker_to_predict + "_" + model_name
|
column_name = ticker_to_predict + "_" + model_name
|
||||||
results[column_name] = result
|
results[column_name] = result
|
||||||
predictions[column_name] = preds
|
# column names for model outputs should be different, so we can differentiate between original data and model predictions later, where necessary
|
||||||
|
predictions["model_" + column_name] = preds
|
||||||
|
|
||||||
if wandb_active:
|
if wandb_active:
|
||||||
run = wandb.init(project="price-forecasting", config={"model_type": model_name, "ticker": ticker_to_predict}, reinit=True)
|
run = wandb.init(project="price-forecasting", config={"model_type": model_name, "ticker": ticker_to_predict}, reinit=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user