Overall Statistics
Total Trades
2009
Average Win
2.14%
Average Loss
-0.75%
Compounding Annual Return
-10.108%
Drawdown
99.700%
Expectancy
-0.011
Net Profit
-21.954%
Sharpe Ratio
0.095
Probabilistic Sharpe Ratio
4.704%
Loss Rate
74%
Win Rate
26%
Profit-Loss Ratio
2.84
Alpha
0.054
Beta
-0.055
Annual Standard Deviation
0.506
Annual Variance
0.256
Information Ratio
-0.099
Tracking Error
0.52
Treynor Ratio
-0.878
Total Fees
$23723.94
using System;
using System.Collections.Generic;
using System.Globalization;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;

namespace QuantConnect.Algorithm.CSharp
{
    public class MultiSymboleEMACrossFramework: QCAlgorithm
    {
        private const Resolution resolution = Resolution.Hour;
        public int fastPeriod = 12;
        public int slowPeriod = 26;
        // list of symbols (universe)
        /* private List<string> CryptoSymbols = new List<string>
        {
            "BTCUSD",
            "ETHUSD",
            "LTCUSD"
        };
        */
        private Dictionary<string, string> CryptoSymbols = new Dictionary<string, string>()
        {
            {"BTCUSD", "BTC"},
            {"ETHUSD", "ETH"},
            {"LTCUSD", "LTC"}
        };

        public Dictionary<string, string> CryptoSymbols1 = new Dictionary<string, string>();
        
        public override void Initialize()
        {
            SetStartDate(2017, 9, 1);  //Set Start Date
            //SetEndDate(2017, 1, 28);  //Set End Date
            SetEndDate(2019, 12, 28);  //Set End Date
            SetCash(10000);             //Set Strategy Cash
            
            // AddEquity("SPY", Resolution.Minute);

			AddAlpha(new EmaCrossAlphaModel(fastPeriod, slowPeriod, resolution));

			SetExecution(new ImmediateExecutionModel());

			//SetPortfolioConstruction(new NullPortfolioConstructionModel());
            // SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel(resolution));
            SimpleEqualWeightPortfolioConstructionModel portfolioModel = new SimpleEqualWeightPortfolioConstructionModel(); 
            SetPortfolioConstruction(portfolioModel);
            portfolioModel.SetSymbols(CryptoSymbols);

            UniverseSettings.Resolution = resolution;
            var symbols = new Symbol[CryptoSymbols.Count];
            var baseSymbols = new string[CryptoSymbols.Count];
            int i = 0;
            foreach(var symbol in CryptoSymbols)
            {
                symbols[i] = QuantConnect.Symbol.Create(symbol.Key, SecurityType.Crypto, Market.GDAX); 
                CryptoSymbols1.Add(symbol.Key,symbol.Value);
                i++;
            }
			SetUniverseSelection( new ManualUniverseSelectionModel(symbols) );
            //SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash);
            foreach (var security in ActiveSecurities)
            {
                Log($"Securities {security.Value.ToString()}");
            }
        }

        /// 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 (!Portfolio.Invested)
            // {
            //    SetHoldings(_spy, 1);
            //    Debug("Purchased Stock");
            //}
        }
        
        public override void OnSecuritiesChanged(SecurityChanges changes)
        {
            foreach (var security in changes.AddedSecurities)
            {
                Log($"Securities {security.ToString()}");
                security.FeeModel = new GDAXFeeModel();
            }
        }
        public override void OnOrderEvent(OrderEvent orderEvent)
        {
            var order = Transactions.GetOrderById(orderEvent.OrderId);
            // if (orderEvent.Status == OrderStatus.Submitted)
            // {
            //     Log(
            //         $" Order {orderEvent.Status} [{orderEvent.Symbol}] {order.Type} {order.Direction}" +
            //         $" Quantity {order.Quantity} Current Price {Portfolio.Securities[orderEvent.Symbol].Close}" +
            //         $" Cash {Portfolio.CashBook["USD"].Amount}"
            //     );
            // }
            
            if (orderEvent.Status == OrderStatus.Filled)
            {
                if (order.Direction == OrderDirection.Buy)
                {
                    Log(
                        $" Order {orderEvent.Status} [{orderEvent.Symbol}] {order.Type} {order.Direction}" +
                        $" Quantity {orderEvent.FillQuantity} Price {orderEvent.FillPrice} Commission {orderEvent.OrderFee}" +
                        $" Cash {Portfolio.CashBook["USD"].Amount}" +
                        $" Equity {Portfolio.TotalPortfolioValue}"
                    );
                }
                else
                {
                    var holdings = Portfolio.Securities[orderEvent.Symbol].Holdings;
                    Log(
                        $" Order {orderEvent.Status} [{orderEvent.Symbol}] {order.Type} {order.Direction}" +
                        $" Quantity {orderEvent.FillQuantity} Price {orderEvent.FillPrice} Commission {orderEvent.OrderFee}" +
//                        $" CostBase {holdings.AveragePrice}" +
                        $" P&L {holdings.LastTradeProfit}" +
                        $" Cash {Portfolio.CashBook["USD"].Amount}" +
                        $" Equity {Portfolio.TotalPortfolioValue}"
                    );
                    
                }
                
            }
        }

        /// <summary>
        /// Portfolio construction model that equally distribute cash among non-holding securities.
        /// Long only. Go flat if there is Down signal
        /// </summary>
        class SimpleEqualWeightPortfolioConstructionModel : PortfolioConstructionModel
        {
            Dictionary<string,string> CryptoSymbols = new Dictionary<string, string>();
            public override IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
            {
                foreach (var insight in insights)
                {
                    /*algorithm.Log(
                         $"Insight Symbol {insight.Symbol}" +
                         //$" CashBook {algorithm.Portfolio.CashBook.ToString()}" +
                         $" Price {algorithm.Portfolio.Securities[insight.Symbol].Close}" +
                         $" Amount {algorithm.Portfolio.CashBook[CryptoSymbols[insight.Symbol]].Amount}"
                                    // $" direction {insight.Direction} " +
                                    $" Type {insight.Type}  Model {insight.SourceModel}");
                    );*/
                    if (algorithm.Portfolio.CashBook[CryptoSymbols[insight.Symbol]].Amount != 0 &&
                        (int) insight.Direction == -1)
                    {
                        yield return new PortfolioTarget(insight.Symbol, 0);
                    }
                    else if (algorithm.Portfolio.CashBook[CryptoSymbols[insight.Symbol]].Amount == 0 &&
                             (int) insight.Direction == 1)
                    {
                        var cash = algorithm.Portfolio.CashBook["USD"].Amount;
                        int holdings = 0;
                        foreach (var x in CryptoSymbols)
                        {
                            if (algorithm.Portfolio.CashBook[x.Value].Amount > 0)
                            {
                                holdings++;
                            }
                        }

                        int openSlots = CryptoSymbols.Count - holdings;

                        decimal targetQuant = Math.Round(
                            cash / openSlots / algorithm.Portfolio.Securities[insight.Symbol].Close * 0.95m,
                            2
                        );
                        yield return new PortfolioTarget(insight.Symbol, targetQuant);
                        //yield return new PortfolioTarget(insight.Symbol, 1.5m);
                    }
                }
            }

            public void SetSymbols(Dictionary<string, string> cryptoSymbols)
            {
                CryptoSymbols = cryptoSymbols;
            }
        }
    }
}