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);
			}
    	}
    }
}