Overall Statistics
Total Trades
7880
Average Win
0.47%
Average Loss
-0.20%
Compounding Annual Return
7.332%
Drawdown
58.800%
Expectancy
0.278
Net Profit
328.552%
Sharpe Ratio
0.369
Probabilistic Sharpe Ratio
0.019%
Loss Rate
62%
Win Rate
38%
Profit-Loss Ratio
2.40
Alpha
0.075
Beta
-0.016
Annual Standard Deviation
0.201
Annual Variance
0.04
Information Ratio
0.062
Tracking Error
0.264
Treynor Ratio
-4.711
Total Fees
$0.00
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using System;
using System.Collections.Generic;
using QuantConnect.Data.Market;

namespace QuantConnect.Indicators
{
        /// <summary>
        /// Represents the traditional simple moving average indicator (SMA)
        /// </summary>
        public class SkewIndicator : BarIndicator
        {

        public RollingWindow<decimal> bars;

        /// <summary>
        /// Gets a flag indicating when this indicator is ready and fully initialized
        /// </summary>
        public override bool IsReady => bars.IsReady;

        int Period;
            /// <summary>
            /// Resets this indicator to its initial state
            /// </summary>
            public override void Reset()
            {
            bars.Reset();
                base.Reset();
            }

            /// <summary>
            /// Initializes a new instance of the SimpleMovingAverage class with the specified name and period
            /// </summary>
            /// <param name="name">The name of this indicator</param>
            /// <param name="period">The period of the SMA</param>
            public SkewIndicator(string name, int period)
                : base(name)
            {
            bars = new RollingWindow<decimal>(period);
            Period = period;
        }

            /// <summary>
            /// Initializes a new instance of the SimpleMovingAverage class with the default name and period
            /// </summary>
            /// <param name="period">The period of the SMA</param>
            public SkewIndicator(int period)
                : this("Skew" + period, period)
            {
            }

            /// <summary>
            /// Computes the next value for this indicator from the given state.
            /// </summary>
            /// <param name="window">The window of data held in this indicator</param>
            /// <param name="input">The input value to this indicator on this time step</param>
            /// <returns>A new value for this indicator</returns>
            protected override decimal ComputeNextValue(IBaseDataBar input)
            {
                bars.Add(input.Close);
                if (!bars.IsReady) return 0;
                return Skewness(ToIEnumerable());
            }


        public decimal Skewness(IEnumerable<double> list)
        {
            try
            {
                var d = MathNet.Numerics.Statistics.Statistics.Skewness(list);
                if (d >= (double)Decimal.MaxValue) return Decimal.MaxValue;
                if (d <= (double)Decimal.MinValue) return Decimal.MinValue;

                return Convert.ToDecimal(d);
            }
            catch(OverflowException)
            {
                return 0;
            }
        }

        private IEnumerable<double> ToIEnumerable()
        {
            var e = bars.GetEnumerator();
            while (e.MoveNext())
            {
                yield return (double)e.Current;
            }
        }

    }
}
using System;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using QuantConnect.Algorithm.CSharp;
namespace QuantConnect.Algorithm.Framework.Alphas
{
    /// <summary>
    /// Alpha model that uses an Skewness cross to create insights
    /// </summary>
    public class AlphaSkew : AlphaModel
    {
        private readonly int _periods;
        private readonly Resolution _resolution;
        private readonly int _predictionInterval;
        private readonly Dictionary<Symbol, SymbolData> _symbolDataBySymbol;
		private List<Insight> lastinsights = new List<Insight>();
		private DateTime lastInsightDate;
		
        /// <summary>
        /// Initializes a new instance of the <see cref="EmaCrossAlphaModel"/> class
        /// </summary>
        /// <param name="fastPeriod">The fast EMA period</param>
        /// <param name="slowPeriod">The slow EMA period</param>
        /// <param name="resolution">The resolution of data sent into the EMA indicators</param>
        public AlphaSkew(
            Resolution resolution = Resolution.Minute,
            int periods = 1440,
            int predictionInterval = 1440
            )
        {
            _resolution = resolution;
            _periods = periods;
            _predictionInterval = predictionInterval;
            _symbolDataBySymbol = new Dictionary<Symbol, SymbolData>();
            Name = $"{nameof(AlphaSkew)}({periods},{resolution})";
        }

        /// <summary>
        /// Updates this alpha model with the latest data from the algorithm.
        /// This is called each time the algorithm receives data for subscribed securities
        /// </summary>
        /// <param name="algorithm">The algorithm instance</param>
        /// <param name="data">The new data available</param>
        /// <returns>The new insights generated</returns>
        public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
        {
        	var insights = new List<Insight>();

            if(data==null) return insights;

 
			if(lastInsightDate==null || algorithm.Time.Subtract(lastInsightDate).TotalDays > 2)
			{
		    	var insightPeriod = _resolution.ToTimeSpan().Multiply(_predictionInterval).Add(new TimeSpan(0,10,0));
			  	lastInsightDate = algorithm.Time;

				Dictionary<SymbolData, decimal> skews = new Dictionary<SymbolData, decimal>();
				foreach (var symbolData in _symbolDataBySymbol.Values)
	            {
	            	if(symbolData.Skew.IsReady && algorithm.Securities[symbolData.Symbol].Price>0)
	            	
	            		skews[symbolData] = symbolData.Skew;
	            }
	            var ascskews = skews.Where(x=> x.Value>1m).OrderByDescending(pair => pair.Value).Take(2).ToDictionary(pair => pair.Key, pair => pair.Value).Keys;
	            var desskews = skews.Where(x=> x.Value<-1m).OrderBy(pair => pair.Value).Take(2).ToDictionary(pair => pair.Key, pair => pair.Value).Keys;
	 
	            foreach (var symbolData in ascskews)
				{
	            
	                if (symbolData == null) continue;
	                var symbol = symbolData.Ticker;
	
	    
	                if(algorithm.IsMarketOpen(symbol))
	                {
	
						if(IsDateOK(algorithm.Time,symbolData.insightDate) )
						{
							
	
	                    	insights.Add(Insight.Price(symbolData.Symbol, insightPeriod, InsightDirection.Up, Math.Abs(symbolData.ROCValue()), null));
	                    	symbolData.insightDate = algorithm.Time.Add(insightPeriod);
	                    	symbolData.TradePrice = algorithm.Securities[symbolData.Symbol].Price;
	
						}
	                }
	
	            }
	            
	            foreach (var symbolData in desskews)
	            {
	                if (symbolData == null) continue;
	                var symbol = symbolData.Ticker;
	
	    
	                if(algorithm.IsMarketOpen(symbol))
	                {
	
						if(IsDateOK(algorithm.Time,symbolData.insightDate) )
						{
	
	                    	insights.Add(Insight.Price(symbolData.Symbol, insightPeriod, InsightDirection.Down, Math.Abs(symbolData.ROCValue()), null));
	                    	symbolData.insightDate = algorithm.Time.Add(insightPeriod);
	                    	symbolData.TradePrice = algorithm.Securities[symbolData.Symbol].Price;
	                    	
						}
	                }
	
	            }
	            
	            var toFlat = _symbolDataBySymbol.Values.ToList().Except(ascskews).ToList().Except(desskews).ToList();
            	foreach (var symbolData in toFlat)
            	{
	            	if(algorithm.IsMarketOpen(symbolData.Symbol))
	                {
						if(IsDateOK(algorithm.Time,symbolData.insightDate) && algorithm.Securities[symbolData.Symbol].Price>0)
						{
	                    	insights.Add(Insight.Price(symbolData.Symbol, insightPeriod, InsightDirection.Flat, Math.Abs(symbolData.ROCValue()), null));
	                    	symbolData.insightDate = algorithm.Time.Add(insightPeriod);
	                    	symbolData.TradePrice = 0;
	                    	symbolData.MaxPrice = 0;
						}
	            	}
            	}
	            lastinsights = insights;
	            return insights;
			}
			else
			{
				
				return RollOrCutOffAlpha(algorithm);
			}
        }

		private IEnumerable<Insight> RollOrCutOffAlpha(QCAlgorithm algorithm)
		{
			var insights = new List<Insight>();
			var insightPeriod = _resolution.ToTimeSpan().Multiply(_predictionInterval).Add(new TimeSpan(0,10,0));

			//push insights again
		  	foreach (var i in lastinsights)
		  	{
		  		var symbolData = _symbolDataBySymbol[i.Symbol];
		  		if(i.Direction==InsightDirection.Down)
			    	symbolData.MaxPrice = symbolData.MaxPrice==0?algorithm.Securities[i.Symbol].Price:Math.Min(symbolData.MaxPrice,algorithm.Securities[i.Symbol].Price);
			    else if(i.Direction==InsightDirection.Up)
			    	symbolData.MaxPrice = Math.Max(symbolData.MaxPrice,algorithm.Securities[i.Symbol].Price);
			   
			   if(_symbolDataBySymbol[i.Symbol].TradePrice>0 && 
		  		((i.Direction==InsightDirection.Up && algorithm.Securities[i.Symbol].Price/_symbolDataBySymbol[i.Symbol].MaxPrice<0.9m) 
		  		|| (i.Direction==InsightDirection.Down && _symbolDataBySymbol[i.Symbol].MaxPrice/algorithm.Securities[i.Symbol].Price<0.9m)))
		
		//	   if(algorithm.Securities[i.Symbol].Invested && algorithm.Securities[i.Symbol].Holdings.UnrealizedProfitPercent<-0.1m)
				{
					insights.Add(Insight.Price(i.Symbol, insightPeriod, InsightDirection.Flat, i.Magnitude, null));
			    	_symbolDataBySymbol[i.Symbol].insightDate = algorithm.Time.Add(insightPeriod);
			    	_symbolDataBySymbol[i.Symbol].TradePrice=0;
			    	_symbolDataBySymbol[i.Symbol].MaxPrice=0;
		
				}		
		  		else if(_symbolDataBySymbol[i.Symbol].TradePrice>0 && 
		  		((i.Direction==InsightDirection.Up && algorithm.Securities[i.Symbol].Price/_symbolDataBySymbol[i.Symbol].TradePrice>0.98m) 
		  		|| (i.Direction==InsightDirection.Down && _symbolDataBySymbol[i.Symbol].TradePrice/algorithm.Securities[i.Symbol].Price>0.98m)))
			    {
		
			    	if(IsDateOK(algorithm.Time,_symbolDataBySymbol[i.Symbol].insightDate) )
			    		insights.Add(Insight.Price(i.Symbol, insightPeriod, i.Direction, i.Magnitude, null));
				}
			    else if (i.Direction!=InsightDirection.Flat )//&& ((i.Direction==InsightDirection.Up && _symbolDataBySymbol[i.Symbol].Skew.Current.Value<1)||(i.Direction==InsightDirection.Down && _symbolDataBySymbol[i.Symbol].Skew.Current.Value>-1)))
			    {
		    		insights.Add(Insight.Price(i.Symbol, insightPeriod, InsightDirection.Flat, i.Magnitude, null));
		    		_symbolDataBySymbol[i.Symbol].insightDate = algorithm.Time.Add(insightPeriod);
		    		_symbolDataBySymbol[i.Symbol].TradePrice=0;
		    		_symbolDataBySymbol[i.Symbol].MaxPrice=0;
		    		
		    	}	
		
		  	}
		
		  	lastinsights = insights;
		  	return insights;

		}
		
		private IEnumerable<Insight> RollAlpha(QCAlgorithm algorithm)
		{
			var insights = new List<Insight>();
			var insightPeriod = _resolution.ToTimeSpan().Multiply(_predictionInterval).Add(new TimeSpan(0,10,0));

			//push insights again
		  	foreach (var i in lastinsights)
		  	{
		  		var symbolData = _symbolDataBySymbol[i.Symbol];
		  		if(i.Direction==InsightDirection.Down)
			    	symbolData.MaxPrice = symbolData.MaxPrice==0?algorithm.Securities[i.Symbol].Price:Math.Min(symbolData.MaxPrice,algorithm.Securities[i.Symbol].Price);
			    else if(i.Direction==InsightDirection.Up)
			    	symbolData.MaxPrice = Math.Max(symbolData.MaxPrice,algorithm.Securities[i.Symbol].Price);

		    	if(IsDateOK(algorithm.Time,_symbolDataBySymbol[i.Symbol].insightDate) )
		    		insights.Add(Insight.Price(i.Symbol, insightPeriod, i.Direction, i.Magnitude, null));

		
		  	}
		
		  	lastinsights = insights;
		  	return insights;

		}
        /// <summary>
        /// Event fired each time the we add/remove securities from the data feed
        /// </summary>
        /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
        /// <param name="changes">The security additions and removals from the algorithm</param>
        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
            var addedSymbols = new List<Symbol>();
            foreach (var added in changes.AddedSecurities)
            {
                SymbolData symbolData;
                if (!_symbolDataBySymbol.TryGetValue(added.Symbol, out symbolData))
                {
                    var ticker = added.Symbol;
                    var security = algorithm.AddSecurity(added.Symbol.SecurityType, ticker, _resolution);
                    security.SetLeverage(100);
                    symbolData = new SymbolData(algorithm, _resolution, security);
                    symbolData.insightDate = algorithm.Time;
                    symbolData.Security = added;
 

                    algorithm.RegisterIndicator(ticker, symbolData.Skew, _resolution.ToTimeSpan().Multiply(_periods));
                    algorithm.RegisterIndicator(ticker, symbolData.ROC, _resolution.ToTimeSpan().Multiply(_periods));//_resolution);
                     _symbolDataBySymbol[added.Symbol] = symbolData;
                    addedSymbols.Add(added.Symbol);

                }
   
            }
            foreach (var removed in changes.RemovedSecurities)
	    	{
	        	SymbolData symbolData;
                if (!_symbolDataBySymbol.TryGetValue(removed.Symbol, out symbolData))
                {
		        	_symbolDataBySymbol.Remove(removed.Symbol); 
	        		algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, symbolData.Consolidator);
                }
	        	//algorithm.RemoveSecurity(removed.Symbol);
	    	}

            if (addedSymbols.Count > 0)
            {
                // warmup our indicators by pushing history through the consolidators
                algorithm.History(addedSymbols, 100, _resolution)
                .PushThrough(bar =>
                {
                    SymbolData symbolData;
                    if (_symbolDataBySymbol.TryGetValue(bar.Symbol, out symbolData))
                    {
                        symbolData.ROC.Update(bar.EndTime, bar.Value);
                    }
                });
            }

        }
        
        private bool IsDateOK(DateTime time, DateTime time2)
        {
        	return time.Subtract(time2).TotalMinutes>=-30;
        }


        class SymbolData
        {
            public RateOfChange ROC;
            public Security Security { get; set; }
            public Symbol Symbol => Security.Symbol;

             public SkewIndicator Skew;

            public string Ticker;


             public readonly IDataConsolidator Consolidator;
            public SymbolData(QCAlgorithm algorithm, Resolution resolution, Security security)
            {
                Ticker = security.Symbol;

                Skew = new SkewIndicator(Ticker,100);//251);
                ROC = new RateOfChange(Ticker, 20);
 
                Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution);
                algorithm.SubscriptionManager.AddConsolidator(security.Symbol, Consolidator);
            }

            public decimal _insight_price = 1;

            public InsightDirection _insight_dir = InsightDirection.Flat;
            public decimal pps = 0;
            public DateTime insightDate;

            public decimal TradePrice = 0;
             public decimal MaxPrice = 0;


            public bool IsReady()
            {
                if (!Skew.IsReady) return false;
                return true;
            }
            public void Reset()
            {
            }

			public double ROCValue()
			{
				return double.IsNaN((double)ROC.Current.Value)?(double)0d: (double)ROC.Current.Value;
			}
        }
    }
}
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using Accord.Math;
using Python.Runtime;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Scheduling;

namespace QuantConnect.Algorithm.Framework.Portfolio
{
    /// <summary>
    /// Provides an implementation of Mean-Variance portfolio optimization based on modern portfolio theory.
    /// The interval of weights in optimization method can be changed based on the long-short algorithm.
    /// The default model uses the last three months daily price to calculate the optimal weight
    /// with the weight range from -1 to 1 and minimize the portfolio variance with a target return of 2%
    /// </summary>
    public class MeanVarianceOptimizationPortfolioConstructionModel2 : PortfolioConstructionModel
    {
        private readonly int _lookback;
        private readonly int _period;
        private readonly Resolution _resolution;
        private readonly PortfolioBias _portfolioBias;
        private readonly IPortfolioOptimizer _optimizer;
        private readonly Dictionary<Symbol, ReturnsSymbolData> _symbolDataDict;

        /// <summary>
        /// Initialize the model
        /// </summary>
        /// <param name="rebalancingDateRules">The date rules used to define the next expected rebalance time
        /// in UTC</param>
        /// <param name="portfolioBias">Specifies the bias of the portfolio (Short, Long/Short, Long)</param>
        /// <param name="lookback">Historical return lookback period</param>
        /// <param name="period">The time interval of history price to calculate the weight</param>
        /// <param name="resolution">The resolution of the history price</param>
        /// <param name="targetReturn">The target portfolio return</param>
        /// <param name="optimizer">The portfolio optimization algorithm. If the algorithm is not provided then the default will be mean-variance optimization.</param>
        public MeanVarianceOptimizationPortfolioConstructionModel2(IDateRule rebalancingDateRules,
            PortfolioBias portfolioBias = PortfolioBias.Long,
            int lookback = 1,
            int period = 63,
            Resolution resolution = Resolution.Daily,
            double targetReturn = 0.02,
            IPortfolioOptimizer optimizer = null)
            : this(rebalancingDateRules.ToFunc(), portfolioBias, lookback, period, resolution, targetReturn, optimizer)
        {
        }

        /// <summary>
        /// Initialize the model
        /// </summary>
        /// <param name="rebalanceResolution">Rebalancing frequency</param>
        /// <param name="portfolioBias">Specifies the bias of the portfolio (Short, Long/Short, Long)</param>
        /// <param name="lookback">Historical return lookback period</param>
        /// <param name="period">The time interval of history price to calculate the weight</param>
        /// <param name="resolution">The resolution of the history price</param>
        /// <param name="targetReturn">The target portfolio return</param>
        /// <param name="optimizer">The portfolio optimization algorithm. If the algorithm is not provided then the default will be mean-variance optimization.</param>
        public MeanVarianceOptimizationPortfolioConstructionModel2(Resolution rebalanceResolution = Resolution.Daily,
            PortfolioBias portfolioBias = PortfolioBias.LongShort,
            int lookback = 1,
            int period = 63,
            Resolution resolution = Resolution.Daily,
            double targetReturn = 0.02,
            IPortfolioOptimizer optimizer = null)
            : this(rebalanceResolution.ToTimeSpan(), portfolioBias, lookback, period, resolution, targetReturn, optimizer)
        {
        }

        /// <summary>
        /// Initialize the model
        /// </summary>
        /// <param name="timeSpan">Rebalancing frequency</param>
        /// <param name="portfolioBias">Specifies the bias of the portfolio (Short, Long/Short, Long)</param>
        /// <param name="lookback">Historical return lookback period</param>
        /// <param name="period">The time interval of history price to calculate the weight</param>
        /// <param name="resolution">The resolution of the history price</param>
        /// <param name="targetReturn">The target portfolio return</param>
        /// <param name="optimizer">The portfolio optimization algorithm. If the algorithm is not provided then the default will be mean-variance optimization.</param>
        public MeanVarianceOptimizationPortfolioConstructionModel2(TimeSpan timeSpan,
            PortfolioBias portfolioBias = PortfolioBias.LongShort,
            int lookback = 1,
            int period = 63,
            Resolution resolution = Resolution.Daily,
            double targetReturn = 0.02,
            IPortfolioOptimizer optimizer = null)
            : this(dt => dt.Add(timeSpan), portfolioBias, lookback, period, resolution, targetReturn, optimizer)
        {
        }

        /// <summary>
        /// Initialize the model
        /// </summary>
        /// <param name="rebalance">Rebalancing func or if a date rule, timedelta will be converted into func.
        /// For a given algorithm UTC DateTime the func returns the next expected rebalance time
        /// or null if unknown, in which case the function will be called again in the next loop. Returning current time
        /// will trigger rebalance. If null will be ignored</param>
        /// <param name="portfolioBias">Specifies the bias of the portfolio (Short, Long/Short, Long)</param>
        /// <param name="lookback">Historical return lookback period</param>
        /// <param name="period">The time interval of history price to calculate the weight</param>
        /// <param name="resolution">The resolution of the history price</param>
        /// <param name="targetReturn">The target portfolio return</param>
        /// <param name="optimizer">The portfolio optimization algorithm. If the algorithm is not provided then the default will be mean-variance optimization.</param>
        /// <remarks>This is required since python net can not convert python methods into func nor resolve the correct
        /// constructor for the date rules parameter.
        /// For performance we prefer python algorithms using the C# implementation</remarks>
        public MeanVarianceOptimizationPortfolioConstructionModel2(PyObject rebalance,
            PortfolioBias portfolioBias = PortfolioBias.LongShort,
            int lookback = 1,
            int period = 63,
            Resolution resolution = Resolution.Daily,
            double targetReturn = 0.02,
            IPortfolioOptimizer optimizer = null)
            : this((Func<DateTime, DateTime?>)null, portfolioBias, lookback, period, resolution, targetReturn, optimizer)
        {
            SetRebalancingFunc(rebalance);
        }

        /// <summary>
        /// Initialize the model
        /// </summary>
        /// <param name="rebalancingFunc">For a given algorithm UTC DateTime returns the next expected rebalance UTC time.
        /// Returning current time will trigger rebalance. If null will be ignored</param>
        /// <param name="portfolioBias">Specifies the bias of the portfolio (Short, Long/Short, Long)</param>
        /// <param name="lookback">Historical return lookback period</param>
        /// <param name="period">The time interval of history price to calculate the weight</param>
        /// <param name="resolution">The resolution of the history price</param>
        /// <param name="targetReturn">The target portfolio return</param>
        /// <param name="optimizer">The portfolio optimization algorithm. If the algorithm is not provided then the default will be mean-variance optimization.</param>
        public MeanVarianceOptimizationPortfolioConstructionModel2(Func<DateTime, DateTime> rebalancingFunc,
            PortfolioBias portfolioBias = PortfolioBias.LongShort,
            int lookback = 1,
            int period = 63,
            Resolution resolution = Resolution.Daily,
            double targetReturn = 0.02,
            IPortfolioOptimizer optimizer = null)
            : this(rebalancingFunc != null ? (Func<DateTime, DateTime?>)(timeUtc => rebalancingFunc(timeUtc)) : null,
                portfolioBias,
                lookback,
                period,
                resolution,
                targetReturn,
                optimizer)
        {
        }

        /// <summary>
        /// Initialize the model
        /// </summary>
        /// <param name="rebalancingFunc">For a given algorithm UTC DateTime returns the next expected rebalance time
        /// or null if unknown, in which case the function will be called again in the next loop. Returning current time
        /// will trigger rebalance.</param>
        /// <param name="portfolioBias">Specifies the bias of the portfolio (Short, Long/Short, Long)</param>
        /// <param name="lookback">Historical return lookback period</param>
        /// <param name="period">The time interval of history price to calculate the weight</param>
        /// <param name="resolution">The resolution of the history price</param>
        /// <param name="targetReturn">The target portfolio return</param>
        /// <param name="optimizer">The portfolio optimization algorithm. If the algorithm is not provided then the default will be mean-variance optimization.</param>
        public MeanVarianceOptimizationPortfolioConstructionModel2(Func<DateTime, DateTime?> rebalancingFunc,
            PortfolioBias portfolioBias = PortfolioBias.LongShort,
            int lookback = 1,
            int period = 63,
            Resolution resolution = Resolution.Daily,
            double targetReturn = 0.02,
            IPortfolioOptimizer optimizer = null)
            : base(rebalancingFunc)
        {
            _lookback = lookback;
            _period = period;
            _resolution = resolution;
            _portfolioBias = portfolioBias;

            var lower = portfolioBias == PortfolioBias.Long ? 0 : -1;
            var upper = portfolioBias == PortfolioBias.Short ? 0 : 1;
            _optimizer = optimizer ?? new MinimumVariancePortfolioOptimizer(lower, upper, targetReturn);

            _symbolDataDict = new Dictionary<Symbol, ReturnsSymbolData>();
        }

        /// <summary>
        /// Method that will determine if the portfolio construction model should create a
        /// target for this insight
        /// </summary>
        /// <param name="insight">The insight to create a target for</param>
        /// <returns>True if the portfolio should create a target for the insight</returns>
        protected override bool ShouldCreateTargetForInsight(Insight insight)
        {
            var filteredInsight = FilterInvalidInsightMagnitude(Algorithm, new[] { insight }).FirstOrDefault();
            if (filteredInsight == null)
            {
                return false;
            }

            ReturnsSymbolData data;
            if (_symbolDataDict.TryGetValue(insight.Symbol, out data))
            {
                if (!insight.Magnitude.HasValue)
                {
                    Algorithm.SetRunTimeError(
                        new ArgumentNullException(
                            insight.Symbol.Value,
                            "MeanVarianceOptimizationPortfolioConstructionModel does not accept 'null' as Insight.Magnitude. " +
                            "Please checkout the selected Alpha Model specifications: " + insight.SourceModel));
                    return false;
                }
                data.Add(Algorithm.Time, insight.Magnitude.Value.SafeDecimalCast());
            }

            return true;
        }

        /// <summary>
        /// Will determine the target percent for each insight
        /// </summary>
        /// <param name="activeInsights">The active insights to generate a target for</param>
        /// <returns>A target percent for each insight</returns>
        protected override Dictionary<Insight, double> DetermineTargetPercent(List<Insight> activeInsights)
        {
            var targets = new Dictionary<Insight, double>();

            // Get the last generated active insight for each symbol
            var lastActiveInsights = from insight in activeInsights
                                     group insight by insight.Symbol into g
                                     select g.OrderBy(x => x.GeneratedTimeUtc).Last();
             
            var symbols = lastActiveInsights.Where(x=> x.Direction !=InsightDirection.Flat).Select(x => x.Symbol).ToList();

            // Get symbols' returns
            var returns = _symbolDataDict.FormReturnsMatrix(symbols);

            // Calculate rate of returns
            var rreturns = returns.Apply(e => Math.Pow(1.0 + e, 252.0) - 1.0);

            // The optimization method processes the data frame
            var w = _optimizer.Optimize(rreturns);

            // process results
            if (w.Length > 0)
            {
                var sidx = 0;
                foreach (var symbol in symbols)
                {
                	double weight = 0;
                	if(sidx<w.Length) weight = w[sidx];
					if(double.IsNaN(weight))
					{
						weight = 0;
					}
                    // don't trust the optimizer
                    else if (_portfolioBias != PortfolioBias.LongShort
                        && Math.Sign(weight) != (int)_portfolioBias)
                    {
                        weight = 0;
                    }
                    var insightSimbol = activeInsights.First(insight => insight.Symbol == symbol);
                    targets[insightSimbol] = (int)insightSimbol.Direction * Math.Abs(weight) * 
                    (int)((insightSimbol.Direction==InsightDirection.Up)?
                    QuantConnect.Algorithm.CSharp.SkewnessCommoditiesAlgo.WeightMultiplierLong:
                    QuantConnect.Algorithm.CSharp.SkewnessCommoditiesAlgo.WeightMultiplierShort);

                    sidx++;
                }
            }

        		symbols = lastActiveInsights.Where(x=> x.Direction ==InsightDirection.Flat).Select(x => x.Symbol).ToList();
                foreach (var symbol in symbols)
                {
                    targets[activeInsights.First(insight => insight.Symbol == symbol)] = 0;
                }
            return targets;
        }

        /// <summary>
        /// Event fired each time the we add/remove securities from the data feed
        /// </summary>
        /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
        /// <param name="changes">The security additions and removals from the algorithm</param>
        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
            base.OnSecuritiesChanged(algorithm, changes);
            // clean up data for removed securities
            foreach (var removed in changes.RemovedSecurities)
            {
                ReturnsSymbolData data;
                if (_symbolDataDict.TryGetValue(removed.Symbol, out data))
                {
                    _symbolDataDict.Remove(removed.Symbol);
                }
            }

            if (changes.AddedSecurities.Count == 0)
                return;

            // initialize data for added securities
            foreach (var added in changes.AddedSecurities)
            {
                if (!_symbolDataDict.ContainsKey(added.Symbol))
                {
                    var symbolData = new ReturnsSymbolData(added.Symbol, _lookback, _period);
                    _symbolDataDict[added.Symbol] = symbolData;
                }
            }

            // warmup our indicators by pushing history through the consolidators
            algorithm.History(changes.AddedSecurities.Select(security => security.Symbol), _lookback * _period, _resolution)
                .PushThrough(bar =>
                {
                    ReturnsSymbolData symbolData;
                    if (_symbolDataDict.TryGetValue(bar.Symbol, out symbolData))
                    {
                        symbolData.Update(bar.EndTime, bar.Value);
                    }
                });
        }
    }
}
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using System.Linq;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Data.UniverseSelection;

namespace QuantConnect.Algorithm.Framework.Execution
{
    /// <summary>
    /// Provides an implementation of <see cref="IExecutionModel"/> that immediately submits
    /// market orders to achieve the desired portfolio targets
    /// </summary>
    public class ImmediateExecutionModel2 : ExecutionModel
    {
        private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();

        /// <summary>
        /// Immediately submits orders for the specified portfolio targets.
        /// </summary>
        /// <param name="algorithm">The algorithm instance</param>
        /// <param name="targets">The portfolio targets to be ordered</param>
        public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
        {
            _targetsCollection.AddRange(targets);

            foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
            {
            	                    // calculate remaining quantity to be ordered
                    var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target);

                    	/*
                var existing = algorithm.Securities[target.Symbol].Holdings.Quantity
                    + algorithm.Transactions.GetOpenOrders(target.Symbol)
                        .Aggregate(0m, (d, order) => d + order.Quantity);
                var quantity = target.Quantity - existing;
                */
            
                var lastData = algorithm.Securities[target.Symbol].GetLastData();
                if (quantity != 0 && Math.Abs(algorithm.Time.Subtract ( lastData.EndTime ).TotalMinutes)<5 && algorithm.IsMarketOpen(target.Symbol))
                {
                    algorithm.MarketOrder(target.Symbol, quantity);
                }
            }

            _targetsCollection.ClearFulfilled(algorithm);
        }

        /// <summary>
        /// Event fired each time the we add/remove securities from the data feed
        /// </summary>
        /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
        /// <param name="changes">The security additions and removals from the algorithm</param>
        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Data;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Data.Custom.CBOE;
using System.Collections.Concurrent;

namespace QuantConnect.Algorithm.CSharp
{
	public class SkewnessCommoditiesAlgo : QCAlgorithm
	{

		public static int WeightMultiplierLong = 2; //use 1 if no leverage
		public static int WeightMultiplierShort = 2; //use 1 if no leverage
		public Symbol cboeVix;
		public decimal vix;
		public IEnumerable<Symbol> symbols;
		public RateOfChange vixROC;
		Resolution resolution = Resolution.Minute;
		int periods =1440;
		public override void Initialize()
		{
			//Start and End Date range for the backtest:
			SetStartDate(2000, 1, 1);
			SetEndDate(2020, 7, 20);
			SetCash(10000);
			SetBenchmark("SPY");

  			cboeVix = AddData<CBOE>("VIX", Resolution.Daily).Symbol;
            SetAlpha(new AlphaSkew(resolution, periods));
            vixROC = new RateOfChange(cboeVix, 9);
            RegisterIndicator(cboeVix, vixROC, Resolution.Daily);

			SetExecution(new ImmediateExecutionModel2());
			SetPortfolioConstruction(new MeanVarianceOptimizationPortfolioConstructionModel2( timeSpan:new TimeSpan(1,0,0), portfolioBias: PortfolioBias.LongShort,optimizer:new MaximumSharpeRatioPortfolioOptimizer()));

			AddUniverseSelection(new ManualUniverseSelectionModel(            
			QuantConnect.Symbol.Create("BCOUSD", SecurityType.Cfd, Market.Oanda),
			//QuantConnect.Symbol.Create("WTIUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("XAGUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("XAUUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("XCUUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("SOYBNUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("WHEATUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("CORNUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("XPTUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("CORNUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("NATGASUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("XPDUSD", SecurityType.Cfd, Market.Oanda),
			QuantConnect.Symbol.Create("SUGARUSD", SecurityType.Cfd, Market.Oanda)
			));
			SetBrokerageModel(QuantConnect.Brokerages.BrokerageName.OandaBrokerage);
			
			//either use this risk or the rollover alphas managed by alphaskew
			//AddRiskManagement(new MaximumUnrealizedProfitPercentPerSecurity(0.02m));
			//AddRiskManagement(new MaximumDrawdownPercentPerSecurity(0.01m));

		}

		/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
		/// Slice object keyed by symbol containing the stock data
		public override void OnData(Slice data)
		{

			if (data.ContainsKey(cboeVix))
            {
                 vix = data.Get<CBOE>(cboeVix).Close;
                 if(vix>1)
	                 vixROC.Update(new IndicatorDataPoint(data.Get<CBOE>(cboeVix).Time, data.Get<CBOE>(cboeVix).Close));
            }
		}
	}
}