Overall Statistics
Total Trades
322
Average Win
0.04%
Average Loss
-0.03%
Compounding Annual Return
7.422%
Drawdown
2.500%
Expectancy
0.286
Net Profit
0.906%
Sharpe Ratio
0.757
Probabilistic Sharpe Ratio
45.785%
Loss Rate
51%
Win Rate
49%
Profit-Loss Ratio
1.60
Alpha
0.06
Beta
-0.022
Annual Standard Deviation
0.082
Annual Variance
0.007
Information Ratio
0.216
Tracking Error
0.751
Treynor Ratio
-2.766
Total Fees
$193.72
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(1); // 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,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;
        }
    }
}