Overall Statistics |
Total Trades 326 Average Win 0.05% Average Loss -0.07% Compounding Annual Return 41.974% Drawdown 5.600% Expectancy 0.410 Net Profit 8.261% Sharpe Ratio 1.796 Probabilistic Sharpe Ratio 61.645% Loss Rate 18% Win Rate 82% Profit-Loss Ratio 0.72 Alpha 0.345 Beta 0.028 Annual Standard Deviation 0.195 Annual Variance 0.038 Information Ratio 0.277 Tracking Error 0.585 Treynor Ratio 12.425 Total Fees $243.84 |
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 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(1440); 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(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 && EntryOrderUp1 == null) { 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.EntryOrderUp1 = MarketOrder(symbolData1D.Symbol, quantity_TP1, false, "Entry_TP1 : " + Time); } if (Signal_Condition_Up && EntryOrderUp2 == null) { 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.EntryOrderUp2 = MarketOrder(symbolData1D.Symbol, quantity_TP2, false, "Entry_TP2 : " + Time); } } } } 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; } } public override void OnOrderEvent(OrderEvent orderEvent) { if (EntryOrderUp1 != null) { this.EntryOrderUp1 = null; } if (EntryOrderUp2 != null) { this.EntryOrderUp2 = null; } if (orderEvent.Status == OrderStatus.Filled || orderEvent.Status == OrderStatus.PartiallyFilled) { if (this.OnOrderFilledEventUp1 != null) { this.ProfitLossOrdersUp1 = OnOrderFilledEventUp1(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime); OnOrderFilledEventUp1 = null; } else if (this.ProfitLossOrdersUp1 != null) { this.ProfitLossOrdersUp1.Filled(); this.ProfitLossOrdersUp1 = null; } if (this.OnOrderFilledEventUp2 != null) { this.ProfitLossOrdersUp2 = OnOrderFilledEventUp2(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime); OnOrderFilledEventUp2 = null; } else if (this.ProfitLossOrdersUp2 != null) { this.ProfitLossOrdersUp2.Filled(); this.ProfitLossOrdersUp2 = null; } } } } }
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(); } } } } 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(); } } } } }