| Overall Statistics |
|
Total Trades 5835 Average Win 0.34% Average Loss -0.20% Compounding Annual Return -10.596% Drawdown 75.500% Expectancy -0.140 Net Profit -63.869% Sharpe Ratio -0.269 Probabilistic Sharpe Ratio 0.000% Loss Rate 68% Win Rate 32% Profit-Loss Ratio 1.67 Alpha -0.079 Beta 0.275 Annual Standard Deviation 0.204 Annual Variance 0.042 Information Ratio -0.626 Tracking Error 0.227 Treynor Ratio -0.199 Total Fees $78061.92 Estimated Strategy Capacity $9300000.00 Lowest Capacity Asset TMV UBTUG7D0B7TX |
#region imports
from AlgorithmImports import *
from scipy.stats import norm, zscore
#endregion
class MeanReversionDemo(QCAlgorithm):
def Initialize(self):
#1. Required: Five years of backtest history
self.SetStartDate(2014, 1, 1)
#2. Required: Alpha Streams Models:
self.SetBrokerageModel(BrokerageName.AlphaStreams)
#3. Required: Significant AUM Capacity
self.SetCash(1000000)
#4. Required: Benchmark to SPY
self.SetBenchmark("SPY")
self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.assets = ["SHY", "TLT", "IEI", "SHV", "TLH", "EDV", "BIL",
"SPTL", "TBT", "TMF", "TMV", "TBF", "VGSH", "VGIT",
"VGLT", "SCHO", "SCHR", "SPTS", "GOVT"]
# Add Equity ------------------------------------------------
for i in range(len(self.assets)):
self.AddEquity(self.assets[i], Resolution.Minute)
# Set Scheduled Event Method For Our Model
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose("SHY", 5), self.EveryDayBeforeMarketClose)
def EveryDayBeforeMarketClose(self):
qb = self
# Fetch history on our universe
df = qb.History(qb.Securities.Keys, 30, Resolution.Daily)
if df.empty: return
# Make all of them into a single time index.
df = df.close.unstack(level=0)
# Calculate the truth value of the most recent price being less than 1 std away from the mean
classifier = df.le(df.mean().subtract(df.std())).iloc[-1]
if not classifier.any(): return
# Get the z-score for the True values, then compute the expected return and probability
z_score = df.apply(zscore)[[classifier.index[i] for i in range(classifier.size) if classifier.iloc[i]]]
magnitude = -z_score * df.std() / df
confidence = (-z_score).apply(norm.cdf)
# Get the latest values
magnitude = magnitude.iloc[-1].fillna(0)
confidence = confidence.iloc[-1].fillna(0)
# Get the weights, then zip together to iterate over later
weight = confidence - 1 / (magnitude + 1)
weight = weight[weight > 0].fillna(0)
sum_ = np.sum(weight)
if sum_ > 0:
weight = (weight) / sum_
selected = zip(weight.index, magnitude, confidence, weight)
else:
return
# ==============================
insights = []
for symbol, magnitude, confidence, weight in selected:
insights.append( Insight.Price(symbol, timedelta(days=1), InsightDirection.Up, magnitude, confidence, None, weight) )
self.EmitInsights(insights)