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