Overall Statistics |
Total Trades 193 Average Win 0.03% Average Loss -0.02% Compounding Annual Return 1.108% Drawdown 1.800% Expectancy 0.166 Net Profit 0.139% Sharpe Ratio 0.179 Probabilistic Sharpe Ratio 37.284% Loss Rate 62% Win Rate 38% Profit-Loss Ratio 2.05 Alpha 0.009 Beta -0.019 Annual Standard Deviation 0.059 Annual Variance 0.003 Information Ratio 0.148 Tracking Error 0.746 Treynor Ratio -0.54 Total Fees $115.80 |
using System; using System.Collections.Generic; using System.Linq; using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; namespace QuantConnect { public class BasicTemplateAlgorithm : QCAlgorithm { private OrderTicket EntryOrderUp1 { get; set; } private OrderTicket EntryOrderUp2 { get; set; } private int EntryOrderUp1OrderId { get; set; } private int EntryOrderUp2OrderId { get; set; } private bool EntryOrderUp1Order { get; set; } private bool EntryOrderUp2Order { get; set; } private OrderTicket EntryOrderUpLAST { get; set; } private Func<QCAlgorithm, string, decimal, DateTime, OneCancelsOtherTicketSetUp1> OnOrderFilledEventUp1 { get; set; } private Func<QCAlgorithm, string, decimal, DateTime, OneCancelsOtherTicketSetUp2> OnOrderFilledEventUp2 { get; set; } private OneCancelsOtherTicketSetUp1 ProfitLossOrdersUp1 { get; set; } private OneCancelsOtherTicketSetUp2 ProfitLossOrdersUp2 { get; set; } public readonly TimeSpan BarPeriod1D = TimeSpan.FromMinutes(240); // 24 hours public readonly int RollingWindowSize = 3; public readonly Dictionary<string, SymbolData1D> Data1D = new Dictionary<string, SymbolData1D>(); public readonly IReadOnlyList<string> ForexSymbols = new List<string> { "EURUSD", /*"USDJPY", "EURGBP", "EURCHF", "USDCAD", "USDCHF", "AUDUSD", "NZDUSD",*/ }; public override void Initialize() { SetStartDate(2020,03, 1); SetEndDate(2020,4, 15); //SetEndDate(DateTime.Now.Date.AddDays(-1)); SetCash(250000); SetBrokerageModel(BrokerageName.FxcmBrokerage); foreach (var symbol in ForexSymbols) { var forex = AddForex(symbol); Data1D.Add(symbol, new SymbolData1D(forex.Symbol, BarPeriod1D, RollingWindowSize)); } foreach (var kvp in Data1D) { var symbolData1D = kvp.Value; var consolidator1D = symbolData1D.Symbol.SecurityType == SecurityType.Equity ? (IDataConsolidator)new TradeBarConsolidator(BarPeriod1D) : (IDataConsolidator)new QuoteBarConsolidator(BarPeriod1D); consolidator1D.DataConsolidated += (sender, baseData) => { var bar = (IBaseDataBar)baseData; symbolData1D.Bars.Add(bar); }; SubscriptionManager.AddConsolidator(symbolData1D.Symbol, consolidator1D); } } public void OnData(Slice slice) { foreach (var symbolData1D in Data1D.Values) { if (symbolData1D.IsReady && symbolData1D.WasJustUpdated(Time)) { bool BarPrecRed = symbolData1D.Bars[1].Open - symbolData1D.Bars[1].Close > 0 ; bool BarPrecGreen = symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Open > 0 ; bool BarCurrentGreen = symbolData1D.Bars[0].Close - symbolData1D.Bars[0].Open > 0 ; bool Signal_Condition_Up = BarCurrentGreen && (symbolData1D.Bars[0].Close - symbolData1D.Bars[0].Open > symbolData1D.Bars[0].Open * 0.001m) ; decimal UP_SL = (symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Low); decimal UP_TP1 = (symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Low); decimal UP_TP2 = ((symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Low) * 2) ; int quantity = (int)Math.Floor(Portfolio.Cash / 4); int quantity_SL = quantity; int quantity_TP1 = (int)Math.Floor(quantity * 0.25m); int quantity_TP2 = (int)Math.Floor(quantity_TP1 * 1m); if (Signal_Condition_Up) { this.OnOrderFilledEventUp1 = (algo1, symbol, filledPrice, dt) => { return new OneCancelsOtherTicketSetUp1( algo1.LimitOrder(symbolData1D.Symbol, -quantity_TP1, filledPrice + UP_TP1, "TP1"), algo1.StopMarketOrder(symbolData1D.Symbol, -quantity_TP1, filledPrice - UP_SL, "SL_TP1")); }; this.EntryOrderUp1Order = true; MarketOrder(symbolData1D.Symbol, quantity_TP1, false, "Entry_TP1 : " + Time); this.EntryOrderUp1Order = false; } if (Signal_Condition_Up) { this.OnOrderFilledEventUp2 = (algo2, symbol, filledPrice, dt) => { return new OneCancelsOtherTicketSetUp2( algo2.LimitOrder(symbolData1D.Symbol, -quantity_TP2, filledPrice + UP_TP2, "TP2"), algo2.StopMarketOrder(symbolData1D.Symbol, -quantity_TP2, filledPrice - UP_SL, "SL_TP2")); }; this.EntryOrderUp2Order = true; MarketOrder(symbolData1D.Symbol, quantity_TP2, false, "Entry_TP2 : " + Time); this.EntryOrderUp2Order = false; } } } } public override void OnOrderEvent(OrderEvent orderEvent) { if (this.EntryOrderUp1Order) this.EntryOrderUp1OrderId = orderEvent.OrderId; if (this.EntryOrderUp2Order) this.EntryOrderUp2OrderId = orderEvent.OrderId; if (orderEvent.Status == OrderStatus.Filled || orderEvent.Status == OrderStatus.PartiallyFilled) { if (orderEvent.OrderId == this.EntryOrderUp1OrderId) { this.ProfitLossOrdersUp1 = this.OnOrderFilledEventUp1(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime); OnOrderFilledEventUp1 = null; EntryOrderUp1OrderId = -1; } if (orderEvent.OrderId == this.EntryOrderUp2OrderId) { this.ProfitLossOrdersUp2 = OnOrderFilledEventUp2(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime); OnOrderFilledEventUp2 = null; EntryOrderUp2OrderId = -1; } if (this.ProfitLossOrdersUp1 != null && this.ProfitLossOrdersUp1.InOrders(orderEvent.OrderId)) { this.ProfitLossOrdersUp1.Filled(); this.ProfitLossOrdersUp1 = null; } if (this.ProfitLossOrdersUp2 != null && this.ProfitLossOrdersUp2.InOrders(orderEvent.OrderId)) { this.ProfitLossOrdersUp2.Filled(); this.ProfitLossOrdersUp2 = null; } } } } public class SymbolData1D { public readonly Symbol Symbol; public readonly RollingWindow<IBaseDataBar> Bars; public readonly TimeSpan BarPeriod1D; public SymbolData1D(Symbol symbol, TimeSpan barPeriod1D, int windowSize) { Symbol = symbol; BarPeriod1D = barPeriod1D; Bars = new RollingWindow<IBaseDataBar>(windowSize); } public bool IsReady { get { return Bars.IsReady;} } public bool WasJustUpdated(DateTime current) { return Bars.Count > 0 && Bars[0].Time == current - BarPeriod1D; } } }
using System.Linq; namespace QuantConnect { public class OneCancelsOtherTicketSetUp1 { public OneCancelsOtherTicketSetUp1(params OrderTicket[] orderTicketsUp1) { this.OrderTicketsUp1 = orderTicketsUp1; } private OrderTicket[] OrderTicketsUp1 { get; set; } public void Filled() { // Cancel all the outstanding tickets. foreach (var orderTicket in this.OrderTicketsUp1) { if (orderTicket.Status == OrderStatus.Submitted) { orderTicket.Cancel("CANCEL 1"); } } } public bool InOrders(int orderId) { foreach (var orderTicket in this.OrderTicketsUp1) if (orderTicket.OrderId == orderId) return true; return false; } } public class OneCancelsOtherTicketSetUp2 { public OneCancelsOtherTicketSetUp2(params OrderTicket[] orderTicketsUp2) { this.OrderTicketsUp2 = orderTicketsUp2; } private OrderTicket[] OrderTicketsUp2 { get; set; } public void Filled() { // Cancel all the outstanding tickets. foreach (var orderTicket in this.OrderTicketsUp2) { if (orderTicket.Status == OrderStatus.Submitted) { orderTicket.Cancel("CANCEL 2"); } } } public bool InOrders(int orderId) { foreach (var orderTicket in this.OrderTicketsUp2) if (orderTicket.OrderId == orderId) return true; return false; } } }