Overall Statistics |
Total Trades 4245 Average Win 0.07% Average Loss -0.03% Compounding Annual Return 0.778% Drawdown 21.800% Expectancy 0.031 Net Profit 1.456% Sharpe Ratio 0.113 Probabilistic Sharpe Ratio 9.028% Loss Rate 68% Win Rate 32% Profit-Loss Ratio 2.18 Alpha 0.011 Beta 0.019 Annual Standard Deviation 0.109 Annual Variance 0.012 Information Ratio -0.436 Tracking Error 0.174 Treynor Ratio 0.629 Total Fees $26540.19 |
from QuantConnect.Data.UniverseSelection import * from QuantConnect.Data.Custom.USTreasury import * import numpy as np import statsmodels.api as sm from sklearn.decomposition import PCA from sklearn.ensemble import RandomForestRegressor from sklearn.linear_model import Ridge, LinearRegression from sklearn.model_selection import cross_val_score, GridSearchCV # Import our custom functions from RegressionFunction import FitRegressionModel class VerticalParticleShield(QCAlgorithm): def Initialize(self): self.SetStartDate(2018, 1, 1) # Set Start Date self.SetCash(1000000) # Set Strategy Cash self.SetBrokerageModel(AlphaStreamsBrokerageModel()) self.SetBenchmark('SPY') self.SetExecution(ImmediateExecutionModel()) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) self.UniverseSettings.Resolution = Resolution.Minute self.SetUniverseSelection(LiquidETFUniverse()) self.AddEquity('TLT') self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.AfterMarketOpen('TLT', 5), self.RunRegression) self.yieldCurve = self.AddData(USTreasuryYieldCurveRate, "USTYCR", Resolution.Daily).Symbol def RunRegression(self): qb = self symbols = [x for x in LiquidETFUniverse.Treasuries] ids = {str(symbol.ID): symbol for symbol in LiquidETFUniverse.Treasuries} # Get history history = qb.History(self.yieldCurve, 100, Resolution.Daily) # Get prices and returns bonds = history.loc[self.yieldCurve].pct_change().fillna(method='ffill').fillna(method='bfill').fillna(value = 0) #### Prepare data set -- feature names, training set, and testing set training = bonds.iloc[:len(bonds)-1].copy() testing = bonds.iloc[len(bonds)-1:].copy() # Find number of components to explain > 95% of variance of treasury prices pca = PCA(n_components=0.95) # Fit the PCA model to our training data pca.fit(training) # Initialize the regression model selected in the research notebook model = RandomForestRegressor(random_state=0, n_estimators = 100) # Fit the regression model and return predictions results = FitRegressionModel(self, pca, model, training, testing) # Find out if the prediction is up or down relative to current price # Generate Insights insights = [] if results.mean(axis = 1).values[0] > 0: insights += [Insight.Price(symbol, timedelta(days = 7), InsightDirection.Up) for symbol in LiquidETFUniverse.Treasuries.Long] insights += [Insight.Price(symbol, timedelta(1), InsightDirection.Flat) for symbol in LiquidETFUniverse.Treasuries.Inverse] else: insights += [Insight.Price(symbol, timedelta(1), InsightDirection.Flat) for symbol in LiquidETFUniverse.Treasuries.Long] insights += [Insight.Price(symbol, timedelta(days = 7), InsightDirection.Up) for symbol in LiquidETFUniverse.Treasuries.Inverse] # Emit Insights self.EmitInsights(insights)
import numpy as np import pandas as pd import statsmodels.api as sm from sklearn.decomposition import PCA from sklearn.ensemble import RandomForestRegressor from sklearn.linear_model import Ridge, LinearRegression from sklearn.model_selection import cross_val_score, GridSearchCV def FitRegressionModel(algorithm, pca, model, training, testing, alpha = False): estimators = [] y_predicted = [] y_actual = [] # Project the data onto the components x_projected = pca.transform(training) # Iterate over all principle components: for i in range(pca.n_components_): # Here, we lag X compared to Y. X will be one time period behind Y X = x_projected[:-1, i] Y = x_projected[1:, i] y_actual.append(Y) X = sm.add_constant(X) # Add necessaary components if using RandomForestRegressor if alpha: test_range = np.arange(10) param_grid = {"alpha": test_range} grid_search = GridSearchCV(model,param_grid) grid_search.fit(X, Y) best_params = grid_search.best_params_ # Fit model and make predictions est = model.fit(X, Y) estimators.append(est) y_predicted.append(model.predict(X)) algorithm.Log("Estimator {}: R2 = {:.3f}\n".format(i, model.score(X,Y))) y_predicted = np.array(y_predicted).transpose() y_actual = np.array(y_actual).transpose() # Transform back into original space y_actual_original_space = pca.inverse_transform(y_actual) y_predicted_original_space = pca.inverse_transform(y_predicted) # Compute sum of squared error: train_sse = np.sum((y_predicted_original_space - y_actual_original_space)** 2) algorithm.Log(f'Sum of squared error: {train_sse}\n') # Transform testing data testing_proj = pca.transform(testing) testing_prediction = [] for i in range(pca.n_components_): # Create a data row row = [1, testing_proj[:,i]] row = np.reshape(row, (1, 2)) # Predict this row p = model.predict(row) testing_prediction.append(p[0]) # Project predictions back to original space predictions = pca.inverse_transform(testing_prediction) actual_pred = pd.DataFrame({'Predicted':predictions}, index = testing.columns) return actual_pred