Overall Statistics
Total Trades
126
Average Win
0.10%
Average Loss
-0.13%
Compounding Annual Return
-8.209%
Drawdown
3.000%
Expectancy
0.013
Net Profit
-0.164%
Sharpe Ratio
0.132
Probabilistic Sharpe Ratio
45.110%
Loss Rate
44%
Win Rate
56%
Profit-Loss Ratio
0.79
Alpha
-2.15
Beta
1.3
Annual Standard Deviation
0.223
Annual Variance
0.05
Information Ratio
-8.766
Tracking Error
0.188
Treynor Ratio
0.023
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 _predictionPeriods;
        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 predictionperiods = 1
            )
        {
            _resolution = resolution;
            _periods = periods;
            _predictionPeriods = predictionperiods;
            _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).TotalMinutes > _resolution.ToTimeSpan().Multiply(_periods* SkewnessCommoditiesAlgo.alpharollingperiods).TotalMinutes )
			{
		    	var insightPeriod = _resolution.ToTimeSpan().Multiply(_periods*_predictionPeriods).Add(new TimeSpan(0,5,0));
			  	lastInsightDate = algorithm.Time;

				Dictionary<SymbolData, decimal> skews = new Dictionary<SymbolData, decimal>();
				foreach (var symbolData in _symbolDataBySymbol.Values)
	            {
	            	if(symbolData.Skew.IsReady && symbolData.Skew2.IsReady && algorithm.Securities[symbolData.Symbol].Price>0)
	            	
	            		skews[symbolData] = symbolData.Skew+symbolData.Skew2;
	            }
	            var ascskews = skews.Where(x=> x.Value>SkewnessCommoditiesAlgo.longSkew).OrderByDescending(pair => pair.Value).Take(SkewnessCommoditiesAlgo.longInstruments).ToDictionary(pair => pair.Key, pair => pair.Value).Keys;
	            var desskews = skews.Where(x=> x.Value<SkewnessCommoditiesAlgo.shortSkew).OrderBy(pair => pair.Value).Take(SkewnessCommoditiesAlgo.shortInstruments).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) && algorithm.Securities[symbolData.Symbol].Price>symbolData.EMAfast)//>symbolData.EMAslow)
						{
	                    	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) && algorithm.Securities[symbolData.Symbol].Price<symbolData.EMAfast)//<symbolData.EMAslow)
						{
	                    	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(_periods*_predictionPeriods).Add(new TimeSpan(0,5,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<SkewnessCommoditiesAlgo.stopprofit) 
		  		|| (i.Direction==InsightDirection.Down && _symbolDataBySymbol[i.Symbol].MaxPrice/algorithm.Securities[i.Symbol].Price<SkewnessCommoditiesAlgo.stopprofit)))
		
		//	   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 && _symbolDataBySymbol[i.Symbol].Skew>SkewnessCommoditiesAlgo.stoplongSkew) 
		  		|| (i.Direction==InsightDirection.Down && _symbolDataBySymbol[i.Symbol].Skew<SkewnessCommoditiesAlgo.stopshortSkew)))
			    {
					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>SkewnessCommoditiesAlgo.stoploss) 
		  		|| (i.Direction==InsightDirection.Down && _symbolDataBySymbol[i.Symbol].TradePrice/algorithm.Securities[i.Symbol].Price>SkewnessCommoditiesAlgo.stoploss)))
			    {
		
			    	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(_periods*_predictionPeriods).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);
                    algorithm.RegisterIndicator(security.Symbol, new Identity(security.Symbol), _resolution);
                    security.SetLeverage(SkewnessCommoditiesAlgo.leverage);
                    symbolData = new SymbolData(algorithm, _resolution, security, _periods);
                    symbolData.insightDate = algorithm.Time;
                    symbolData.Security = added;

                     _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*1440, _resolution)
                .PushThrough(bar =>
                {
                    SymbolData symbolData;
                    if (_symbolDataBySymbol.TryGetValue(bar.Symbol, out symbolData))
                    {
                        symbolData.ROC.Update(bar.EndTime, bar.Value);
                        symbolData.Skew.Update(bar);
                        symbolData.Skew2.Update(bar);
                        symbolData.EMAfast.Update(bar.EndTime, bar.Value);
                        symbolData.EMAslow.Update(bar.EndTime, bar.Value);
                    }
                });
                algorithm.History(addedSymbols, 200*SkewnessCommoditiesAlgo.periods, _resolution)
                .PushThrough(bar =>
                {
                    SymbolData symbolData;
                    if (_symbolDataBySymbol.TryGetValue(bar.Symbol, out symbolData))
                    {
                        symbolData.EMAfast.Update(bar.EndTime, bar.Value);
                        symbolData.EMAslow.Update(bar.EndTime, bar.Value);
                    }
                });
            }

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


        class SymbolData
        {
            public RateOfChange ROC;
            public RollingWindow<RateOfChange> RollingROC;
            public SimpleMovingAverage EMAfast;
            public SimpleMovingAverage EMAslow;
            public Security Security { get; set; }
            public Symbol Symbol => Security.Symbol;

            public SkewIndicator Skew;
            public SkewIndicator Skew2;

            public string Ticker;

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

                Skew = new SkewIndicator(Ticker,SkewnessCommoditiesAlgo.skewperiods);//251);
                Skew2 = new SkewIndicator(Ticker,SkewnessCommoditiesAlgo.skew2periods);//251);
                
                ROC = new RateOfChange(Ticker, SkewnessCommoditiesAlgo.alphaperiods);
                RollingROC = new RollingWindow<RateOfChange>(24/SkewnessCommoditiesAlgo.alphaperiods+1);
                EMAfast = new SimpleMovingAverage(Ticker, 50);
				EMAslow = new SimpleMovingAverage(Ticker, 200);
                //Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution);
                //algorithm.SubscriptionManager.AddConsolidator(security.Symbol, Consolidator);
 
                algorithm.RegisterIndicator(security.Symbol, Skew, resolution.ToTimeSpan().Multiply(_periods));
                algorithm.RegisterIndicator(security.Symbol, Skew2, resolution.ToTimeSpan().Multiply(_periods));
                algorithm.RegisterIndicator(security.Symbol, ROC, resolution.ToTimeSpan().Multiply(_periods*SkewnessCommoditiesAlgo.alphaperiods));//_resolution);
                algorithm.RegisterIndicator(security.Symbol, EMAfast, resolution.ToTimeSpan().Multiply(_periods));//resolution.ToTimeSpan().Multiply(_periods));//_resolution);
                algorithm.RegisterIndicator(security.Symbol, EMAslow, resolution.ToTimeSpan().Multiply(_periods));//resolution.ToTimeSpan().Multiply(_periods));//_resolution);
				ROC.Updated += (sender, updated) =>
	            {
	                RollingROC.Add(ROC);
	            };
            }


            public InsightDirection _insight_dir = InsightDirection.Flat;
            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()
			{
				if(!RollingROC.IsReady) return 0;
				return double.IsNaN((double)RollingROC[(24/SkewnessCommoditiesAlgo.alphaperiods)-1].Current.Value)?(double)0d: (double)RollingROC[(24/SkewnessCommoditiesAlgo.alphaperiods)-1].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, ReturnsSymbolData2> _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, ReturnsSymbolData2>();
        }

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

            ReturnsSymbolData2 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)
                {
                	var insightSimbol = activeInsights.First(insight => insight.Symbol == symbol);

                	double weight = 0;
                	if(sidx<w.Length) weight = w[sidx];
					if(double.IsNaN(weight))
					{
						weight = 0;
					}
					else if(insightSimbol.Direction==InsightDirection.Up && Math.Sign(weight) != 1)
                    {
                    	weight = weight/2;
                    }
                    else if(insightSimbol.Direction==InsightDirection.Down && Math.Sign(weight) != -1)
                    {
                    	weight = weight/2;
                    }
                    // don't trust the optimizer
                    else if (_portfolioBias != PortfolioBias.LongShort
                        && Math.Sign(weight) != (int)_portfolioBias)
                    {
                        weight = 0;
                    }
                    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)
            {
                ReturnsSymbolData2 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 ReturnsSymbolData2(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 =>
                {
                    ReturnsSymbolData2 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 double WeightMultiplierLong = 1; //use 1 if no leverage
		public static double WeightMultiplierShort = 1; //use 1 if no leverage

		public IEnumerable<Symbol> symbols;
		Resolution resolution = Resolution.Minute;
		public static int periods =60;
		public static int alphaperiods =4;
		public static int alpharollingperiods =4;
		public static int skewperiods =4;
		public static int skew2periods =12;
		public static int longInstruments = 4;
		public static int shortInstruments = 4;
		public static decimal longSkew = 1.0m;
		public static Decimal shortSkew = -1.0m;
		public static decimal stoplongSkew = 2.0m;
		public static Decimal stopshortSkew = -2.0m;
		public static decimal stoploss = 0.8m;
		public static decimal stopprofit = 0.8m;
		public static int leverage = 100;
		
		public static IEnumerable<DateTime> EachHourMostLiquidity(DateTime from, DateTime thru)
        {
            for (var day = from; day <= thru; )
            {
            	day = day.AddHours(1);
            	if(day.Hour >=9 && day.Hour <21)
	                yield return day;
            }
        }
        
		public override void Initialize()
		{
			//Start and End Date range for the backtest:
			SetStartDate(2020, 7, 28);
			SetEndDate(2020, 8, 4);
			SetCash(1500);
			SetBenchmark("SPY");

            SetAlpha(new AlphaSkew(resolution, periods,alphaperiods));
			SetExecution(new ImmediateExecutionModel2());
			SetPortfolioConstruction(new MeanVarianceOptimizationPortfolioConstructionModel2( 
				//timeSpan:new TimeSpan(1,0,0), 
				rebalancingDateRules:new FuncDateRule("EachHourMostLiquidity", EachHourMostLiquidity),
				portfolioBias: PortfolioBias.LongShort,
				//optimizer:new MaximumSharpeRatioPortfolioOptimizer(),
				period:63*24,
				lookback:24,
				targetReturn:0.1d));

			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)/*,
			QuantConnect.Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda),
			QuantConnect.Symbol.Create("USDJPY", SecurityType.Forex, Market.Oanda),
			QuantConnect.Symbol.Create("GBPUSD", SecurityType.Forex, Market.Oanda),
			QuantConnect.Symbol.Create("USDMXN", SecurityType.Forex, Market.Oanda),
			QuantConnect.Symbol.Create("AUDUSD", SecurityType.Forex, 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)
		{
		}
	}
}
/*
 * 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 QuantConnect.Indicators;
using QuantConnect.Util;

namespace QuantConnect.Algorithm.Framework.Portfolio
{
    /// <summary>
    /// Contains returns specific to a symbol required for optimization model
    /// </summary>
    public class ReturnsSymbolData2
    {
        private readonly Symbol _symbol;
        private readonly RateOfChange _roc;
        private readonly RollingWindow<IndicatorDataPoint> _window;

        /// <summary>
        /// Initializes a new instance of the <see cref="ReturnsSymbolData"/> class
        /// </summary>
        /// <param name="symbol">The symbol of the data that updates the indicators</param>
        /// <param name="lookback">Look-back period for the RateOfChange indicator</param>
        /// <param name="period">Size of rolling window that contains historical RateOfChange</param>
        public ReturnsSymbolData2(Symbol symbol, int lookback, int period)
        {
            _symbol = symbol;
            _roc = new RateOfChange($"{_symbol}.ROC({lookback})", lookback);
            _window = new RollingWindow<IndicatorDataPoint>(period);
            _roc.Updated += OnRateOfChangeUpdated;
        }

        /// <summary>
        /// Historical returns
        /// </summary>
        public Dictionary<DateTime, double> Returns => _window.ToDictionary(x => x.EndTime, x => (double) x.Value);

        /// <summary>
        /// Adds an item to this window and shifts all other elements
        /// </summary>
        /// <param name="time">The time associated with the value</param>
        /// <param name="value">The value to use to update this window</param>
        public void Add(DateTime time, decimal value)
        {
            var item = new IndicatorDataPoint(_symbol, time, value);
            AddToWindow(item);
        }

        /// <summary>
        /// Updates the state of the RateOfChange with the given value and returns true
        /// if this indicator is ready, false otherwise
        /// </summary>
        /// <param name="time">The time associated with the value</param>
        /// <param name="value">The value to use to update this indicator</param>
        /// <returns>True if this indicator is ready, false otherwise</returns>
        public bool Update(DateTime time, decimal value)
        {
            return _roc.Update(time, value);
        }

        /// <summary>
        /// Resets all indicators of this object to its initial state
        /// </summary>
        public void Reset()
        {
            _roc.Updated -= OnRateOfChangeUpdated;
            _roc.Reset();
            _window.Reset();
        }

        /// <summary>
        /// When the RateOfChange is updated, adds the new value to the RollingWindow
        /// </summary>
        /// <param name="roc"></param>
        /// <param name="updated"></param>
        private void OnRateOfChangeUpdated(object roc, IndicatorDataPoint updated)
        {
            if (_roc.IsReady)
            {
                AddToWindow(updated);
            }
        }

        private void AddToWindow(IndicatorDataPoint updated)
        {
            if (_window.Samples > 0 && _window[0].EndTime >= updated.EndTime)
            {
                // this could happen with fill forward bars in the history request
                return;
            }

            _window.Add(updated);
        }
    }

    /// <summary>
    /// Extension methods for <see cref="ReturnsSymbolData"/>
    /// </summary>
    public static class ReturnsSymbolDataExtensions
    {
        /// <summary>
        /// Converts a dictionary of <see cref="ReturnsSymbolData"/> keyed by <see cref="Symbol"/> into a matrix
        /// </summary>
        /// <param name="symbolData">Dictionary of <see cref="ReturnsSymbolData"/> keyed by <see cref="Symbol"/> to be converted into a matrix</param>
        /// <param name="symbols">List of <see cref="Symbol"/> to be included in the matrix</param>
        public static double[,] FormReturnsMatrix(this Dictionary<Symbol, ReturnsSymbolData2> symbolData, IEnumerable<Symbol> symbols)
        {
            var returnsByDate = (from s in symbols join sd in symbolData on s equals sd.Key select sd.Value.Returns).ToList();

            // Consolidate by date
            var alldates = returnsByDate.SelectMany(r => r.Keys).Distinct().ToList();

            var max = symbolData.Count == 0 ? 0 : symbolData.Max(kvp => kvp.Value.Returns.Count);
			double obj;
            // Perfect match between the dates in the ReturnsSymbolData objects
            if (max == alldates.Count)
            {
                return Accord.Math.Matrix.Create(alldates
                    // if a return date isn't found for a symbol we use 'double.NaN'
                    .Select(d => returnsByDate.Select(s => s.TryGetValue(d, out obj) ? obj : double.NaN).ToArray())
                    .Where(r => !r.Select(Math.Abs).Sum().IsNaNOrZero()) // remove empty rows
                    .ToArray());
            }

            // If it is not a match, we assume that each index correspond to the same point in time
            var returnsByIndex = returnsByDate.Select((doubles, i) => doubles.Values.ToArray());

            return Accord.Math.Matrix.Create(Enumerable.Range(0, max)
                // there is no guarantee that all symbols have the same amount of returns so we need to check range and use 'double.NaN' if required as above
                .Select(d => returnsByIndex.Select(s => s.Length < (d + 1) ? double.NaN : s[d]).ToArray())
                .Where(r => !r.Select(Math.Abs).Sum().IsNaNOrZero()) // remove empty rows
                .ToArray());
        }
    }
}