| Overall Statistics |
|
Total Trades 13445 Average Win 0.27% Average Loss -0.07% Compounding Annual Return -10.332% Drawdown 74.600% Expectancy -0.166 Net Profit -62.888% Sharpe Ratio -0.26 Probabilistic Sharpe Ratio 0.000% Loss Rate 82% Win Rate 18% Profit-Loss Ratio 3.57 Alpha -0.077 Beta 0.274 Annual Standard Deviation 0.204 Annual Variance 0.042 Information Ratio -0.618 Tracking Error 0.227 Treynor Ratio -0.193 Total Fees $86686.70 Estimated Strategy Capacity $180000.00 Lowest Capacity Asset TMV UBTUG7D0B7TX |
/// Please refer to Research.ipynb
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Brokerages;
using System;
using System.Collections.Generic;
using System.Linq;
using MathNet.Numerics.Distributions;
namespace QuantConnect.Algorithm.Csharp
{
public class MeanReversionDemo : QCAlgorithm
{
List<string> _asset = new List<string>{"SHY", "TLT", "IEI", "SHV", "TLH", "EDV", "BIL",
"SPTL", "TBT", "TMF", "TMV", "TBF", "VGSH", "VGIT",
"VGLT", "SCHO", "SCHR", "SPTS", "GOVT"};
public override void Initialize()
{
// 1. Required: Five years of backtest history
SetStartDate(2014, 1, 1);
// 2. Required: Alpha Streams Models:
SetBrokerageModel(BrokerageName.AlphaStreams);
// 3. Required: Significant AUM Capacity
SetCash(1000000);
// 4. Required: Benchmark to SPY
SetBenchmark("SPY");
SetPortfolioConstruction(new InsightWeightingPortfolioConstructionModel());
SetExecution(new ImmediateExecutionModel());
// Add Equity ------------------------------------------------
foreach(var ticker in _asset)
{
AddEquity(ticker, Resolution.Minute);
}
// Set Scheduled Event Method For Our Model
Schedule.On(DateRules.EveryDay(),
TimeRules.BeforeMarketClose("SHY", 5),
EveryDayBeforeMarketClose);
}
private void EveryDayBeforeMarketClose()
{
// Fetch history on our universe
var history = History(Securities.Keys, 30, Resolution.Daily);
if (history.Count() < 0) return;
// Extract close prices for each Symbol from Slice data
var closes = new Dictionary<Symbol, List<Decimal>>();
foreach(var slice in history){
foreach(var symbol in slice.Keys){
if(!closes.ContainsKey(symbol)){
closes.Add(symbol, new List<Decimal>());
}
closes[symbol].Add(slice.Bars[symbol].Close);
}
}
// Get the 30-day rolling mean, standard deviation series, z-score and filtration for each Symbol
var rollingMean = new Dictionary<string, double>();
var rollingStd = new Dictionary<string, double>();
var filter = new Dictionary<string, bool>();
var zScore = new Dictionary<string, double>();
foreach(var kvp in closes)
{
var symbol = kvp.Key;
if(!rollingMean.ContainsKey(symbol)){
rollingMean.Add(symbol, decimal.ToDouble(kvp.Value.Average()));
rollingStd.Add(symbol, Math.Sqrt(kvp.Value.Average(v => Math.Pow(decimal.ToDouble(v-kvp.Value.Average()), 2))));
zScore.Add(symbol, (decimal.ToDouble(kvp.Value.Last()) - rollingMean[symbol]) / rollingStd[symbol]);
filter.Add(symbol, zScore[symbol] < -1);
}
}
// Calculate the expected return and its probability, then calculate the weight
var magnitude = new Dictionary<Symbol, double>();
var confidence = new Dictionary<Symbol, double>();
var weights = new Dictionary<Symbol, double>();
foreach(var kvp in rollingMean)
{
var symbol = kvp.Key;
if(!magnitude.ContainsKey(symbol)){
magnitude.Add(symbol, -zScore[symbol] * rollingStd[symbol] / decimal.ToDouble(closes[symbol].Last()));
confidence.Add(symbol, Normal.CDF(0, 1, -zScore[symbol]));
// Filter if trade or not
var trade = filter[symbol] ? 1d : 0d;
weights.Add(symbol, trade * Math.Max(confidence[symbol] - 1 / (magnitude[symbol] + 1), 0));
}
}
// Normalize the weights, then emit insights
List<Insight> insights = new List<Insight>{};
var sum = weights.Sum(x => x.Value);
if (sum == 0) return;
foreach(var kvp in weights)
{
var symbol = kvp.Key;
weights[symbol] = kvp.Value / sum;
var insight = new Insight(symbol, TimeSpan.FromDays(1), InsightType.Price, InsightDirection.Up, magnitude[symbol], confidence[symbol], null, weights[symbol]);
EmitInsights(insight);
}
}
}
}