Overall Statistics |
Total Trades 98 Average Win 0.02% Average Loss -0.02% Compounding Annual Return -1.405% Drawdown 0.400% Expectancy -0.084 Net Profit -0.070% Sharpe Ratio -0.965 Probabilistic Sharpe Ratio 31.232% Loss Rate 62% Win Rate 38% Profit-Loss Ratio 1.44 Alpha -0.013 Beta -0.002 Annual Standard Deviation 0.011 Annual Variance 0 Information Ratio 0.987 Tracking Error 0.941 Treynor Ratio 5.689 Total Fees $58.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; } private List<OneCancelsOtherTicketSetUp1> OCOSets1 = new List<OneCancelsOtherTicketSetUp1>(); private List<OneCancelsOtherTicketSetUp2> OCOSets2 = new List<OneCancelsOtherTicketSetUp2>(); 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",*/ }; ///////////////// ///////Average Spread int sprdEURUSD = 13 ; int sprdEURAUD = 30 ; int sprdEURNZD = 43 ; int sprdEURJPY = 20 ; int sprdEURCAD = 26 ; int sprdEURGBP = 23 ; int sprdEURSEK = 360 ; int sprdEURTRY = 780 ; ////MArgin decimal MarEURUSD = 33.3m ; decimal MarEURAUD = 50m ; decimal MarEURNZD = 50m ; decimal MarEURJPY = 33.3m ; decimal MarEURCAD = 33.3m ; decimal MarEURCHF = 33.3m ; decimal MarEURGBP = 33.3m ; decimal MarEURSEK = 50m ; decimal MarEURTRY = 120m ; ////PVALUE decimal PValue_EURUSD = 0.09m ; decimal PValue_EURAUD = 0.06m ; decimal PValue_EURNZD = 0.06m ; decimal PValue_EURJPY = 0.09m ; decimal PValue_EURCAD = 0.07m ; decimal PValue_EURCHF = 0.09m ; decimal PValue_EURGBP = 0.11m ; decimal PValue_EURSEK = 0.009m ; decimal PValue_EURTRY = 0.01m ; public override void Initialize() { SetStartDate(2020,03, 1); SetEndDate(2020,03, 18); //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; 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.OCOSets1.Add( this.OnOrderFilledEventUp1(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime) ); EntryOrderUp1OrderId = -1; } if (orderEvent.OrderId == this.EntryOrderUp2OrderId) { OCOSets2.Add( this.OnOrderFilledEventUp2(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime) ); EntryOrderUp2OrderId = -1; } int i = 0; for (; i < OCOSets1.Count; i++) if (OCOSets1[i].InOrders(orderEvent.OrderId)) { OCOSets1[i].Filled(); OCOSets1.RemoveAt(i); break; } i = 0; for (; i < OCOSets2.Count; i++) if (OCOSets2[i].InOrders(orderEvent.OrderId)) { OCOSets2[i].Filled(); OCOSets2.RemoveAt(i); break; } } } } 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; } } }