Overall Statistics
Total Trades
6
Average Win
8.87%
Average Loss
-2.48%
Compounding Annual Return
0.054%
Drawdown
20.400%
Expectancy
-0.083
Net Profit
0.018%
Sharpe Ratio
0.181
Probabilistic Sharpe Ratio
28.174%
Loss Rate
80%
Win Rate
20%
Profit-Loss Ratio
3.58
Alpha
0.066
Beta
0.015
Annual Standard Deviation
0.366
Annual Variance
0.134
Information Ratio
0.119
Tracking Error
0.563
Treynor Ratio
4.333
Total Fees
$265.44
Estimated Strategy Capacity
$12000.00
Lowest Capacity Asset
CERU VPLW2D47KBXH
/*
 * 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.Collections.Generic;
using QuantConnect.Data;
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 EMA cross to create insights
    /// </summary>
    public class MyEmaCrossAlphaModel : AlphaModel
    {
        private readonly int _fastPeriod;
        private readonly int _slowPeriod;
        private readonly Resolution _resolution;
        private readonly Dictionary<Symbol, SymbolData> _symbolDataBySymbol;
        
        private static int numDays = 0;

        /// <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 MyEmaCrossAlphaModel(
            int fastPeriod,
            int slowPeriod,
            Resolution resolution
            )
        {
            _fastPeriod = fastPeriod;
            _slowPeriod = slowPeriod;
            _resolution = resolution;
            _symbolDataBySymbol = new Dictionary<Symbol, SymbolData>();
            Name = $"{nameof(EmaCrossAlphaModel)}({fastPeriod},{slowPeriod},{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)
        {
        	
        	EnergeticYellowGreenPelican algorithm = (EnergeticYellowGreenPelican) _algorithm;
        	
        	algorithm.Log("EmaCrossAlphaModel.Update() - data.len=" + data.Count + ", _symbolDataBySymbol.len=" + _symbolDataBySymbol.Count);
        	object x = algorithm.Portfolio.GetType();
        	object y = data.Keys;
        	
        	// update stop loss
        	foreach (KeyValuePair<Symbol, SecurityHolding> stock in algorithm.Portfolio) {
        		var stopLoss = stock.Value.Price * (1.0m - algorithm.stopLossPercent);
        		if (stock.Key != "dave")
        			x = null;
        	}
        	
            var insights = new List<Insight>();
            var insightPeriod = _resolution.ToTimeSpan().Multiply(20);
            foreach (var symbolData in _symbolDataBySymbol.Values)
            {
                if (symbolData.Fast.IsReady && symbolData.Slow.IsReady)
                {
                    if (symbolData.FastIsOverSlow)
                    {
                        if (symbolData.Slow > symbolData.Fast)
                        {
                            insights.Add(Insight.Price(symbolData.Symbol, insightPeriod, InsightDirection.Down));
                            algorithm.Log(symbolData.Symbol + " crossed to down");
                        }
                    }
                    else if (symbolData.SlowIsOverFast)
                    {
                        if (symbolData.Fast > symbolData.Slow)
                        {
                            insights.Add(Insight.Price(symbolData.Symbol, insightPeriod, InsightDirection.Up));
                            algorithm.Log(symbolData.Symbol + " crossed to up");
                        }
                    }
                } else
	        		algorithm.Log(symbolData.Symbol + " symbolData.Fast.IsReady=" + symbolData.Fast.IsReady + ", symbolData.Slow.IsReady=" + symbolData.Slow.IsReady);

                symbolData.FastIsOverSlow = symbolData.Fast > symbolData.Slow;
            }
            
            numDays ++;
            if (numDays == 10) {
                insights.Add(Insight.Price("DARE", _resolution.ToTimeSpan(), InsightDirection.Down));
 	        	algorithm.Log("sell DARE");
           }

			if (insights.Count > 0) {
				algorithm.Log("returning insights, len=" + insights.Count);
				foreach (var i in insights)
					algorithm.Log("     " + i.Symbol + " direction=" + i.Direction + " period=" + i.Period);
			}
				
            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)
        {
        	
        	algorithm.Log("EmaCrossAlphaModel.OnSecuritiesChanged()");
        	
            foreach (var added in changes.AddedSecurities)
            {
                SymbolData symbolData;
                if (!_symbolDataBySymbol.TryGetValue(added.Symbol, out symbolData))
                {
            		algorithm.Log("AddedSecurities new " + added.Symbol);
                    // create fast/slow EMAs
                    var fast = algorithm.EMA(added.Symbol, _fastPeriod, _resolution);
                    algorithm.WarmUpIndicator(added.Symbol, fast, _resolution);
                    var slow = algorithm.EMA(added.Symbol, _slowPeriod, _resolution);
                    algorithm.WarmUpIndicator(added.Symbol, slow, _resolution);
                    _symbolDataBySymbol[added.Symbol] = new SymbolData
                    {
                        Security = added,
                        Fast = fast,
                        Slow = slow
                    };
                }
                else
                {
                    algorithm.Log("AddedSecurities reset " + added.Symbol);
            		// a security that was already initialized was re-added, reset the indicators
                    symbolData.Fast.Reset();
                    symbolData.Slow.Reset();
                }
            }
            
        foreach (var removed in changes.RemovedSecurities) {
            algorithm.Log("RemovedSecurities " + removed.Symbol);
            SymbolData data;
            //if (_symbolDataBySymbol.Remove(removed.Symbol, out data))
                //data.Dispose();
        	}
        }

        /// <summary>
        /// Contains data specific to a symbol required by this model
        /// </summary>
        private class SymbolData
        {
            public Security Security { get; set; }
            public Symbol Symbol => Security.Symbol;
            public ExponentialMovingAverage Fast { get; set; }
            public ExponentialMovingAverage Slow { get; set; }

            /// <summary>
            /// True if the fast is above the slow, otherwise false.
            /// This is used to prevent emitting the same signal repeatedly
            /// </summary>
            public bool FastIsOverSlow { get; set; }
            public bool SlowIsOverFast => !FastIsOverSlow;
        }
    }
}
using QuantConnect.Algorithm.Framework.Alphas;

namespace QuantConnect.Algorithm.CSharp
{
    public class EnergeticYellowGreenPelican : QCAlgorithm
    {
    	
    	public decimal stopLossPercent = 0.02m;

        public override void Initialize()
        {
            SetStartDate(2020, 2, 1);  //Set Start Date
            SetEndDate(2020, 6, 1);  //Set End Date
            SetCash(10000);             //Set Strategy Cash
            SetBenchmark("SPY");
            
            AddEquity("DARE", Resolution.Daily);

			AddAlpha(new MyEmaCrossAlphaModel(50, 200, Resolution.Daily));

			SetExecution(new ImmediateExecutionModel());

			SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());

//			SetRiskManagement(new MaximumDrawdownPercentPerSecurity(stopLossPercent));

//			SetUniverseSelection(new FineFundamentalUniverseSelectionModel(CoarseSelectionFunction, FineSelectionFunction));
			
			Log("Initialize complete");
        }

        /// 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)
        {
        	Log("OnData");
            // if (!Portfolio.Invested)
            // {
            //    SetHoldings("SPY", 1);
            //    Debug("Purchased Stock");
            //}
        }

    }
}