Overall Statistics
Total Trades
80
Average Win
0.36%
Average Loss
-0.90%
Compounding Annual Return
0.666%
Drawdown
8.200%
Expectancy
0.366
Net Profit
14.096%
Sharpe Ratio
0.235
Probabilistic Sharpe Ratio
0.002%
Loss Rate
2%
Win Rate
98%
Profit-Loss Ratio
0.40
Alpha
0.006
Beta
-0.002
Annual Standard Deviation
0.024
Annual Variance
0.001
Information Ratio
-0.316
Tracking Error
0.17
Treynor Ratio
-3.637
Total Fees
$7914.30
using System;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using System.Linq;
using QuantConnect.Interfaces;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using QuantConnect.Orders;
using QuantConnect.Data.Consolidators;

namespace Quant 
{
	    public class TestAlgo : QCAlgorithm
	    {

    	public RollingWindow<decimal> BidPrice = new RollingWindow<decimal>(4);
    	public RollingWindow<decimal> AskPrice = new RollingWindow<decimal>(4);
    	public RollingWindow<decimal> Volume = new RollingWindow<decimal>(4);

        public OrderTicket EntryOrder { get; set; }
        public Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; }
        public OneCancelsOtherTicketSet ProfitLossOrders { get; set; }
        
        public override void Initialize() 
        {
        	
		SetStartDate(2000, 01, 01);
        SetEndDate(DateTime.Now);
        SetCash(1000000);

            var contract = AddFuture(Futures.Indices.SP500EMini, Resolution.Minute);
            contract.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));

		SetSecurityInitializer(x => x.SetSlippageModel(new CustomSlippageModel(this)));
		SetBrokerageModel(BrokerageName.AlphaStreams);
	    SetExecution(new VolumeWeightedAveragePriceExecutionModel());
	    
	    AddRiskManagement(new MaximumUnrealizedProfitPercentPerSecurity(0.09m));
	    AddRiskManagement(new MaximumDrawdownPercentPerSecurity(0.09m));

        }

        public override void OnData(Slice slice)
        {	
        	var accountCurrencyCash = Portfolio.TotalPortfolioValue;
        	
            foreach(var chain in slice.FutureChains)
            {

            // remplacer les lettre entre guillemet par l'abreviation correspondant au contract analysé. 
			if (chain.Value.Symbol.StartsWith("ES"))
            {
			var ES = (from futuresContract in chain.Value.OrderBy(x => x.Expiry)
			where futuresContract.Expiry > Time.Date.AddDays(1) 
			select futuresContract).FirstOrDefault();
            
            if ( ES != null)
			{
				
			BidPrice.Add(ES.BidPrice);
			AskPrice.Add(ES.AskPrice);
			Volume.Add(ES.Volume);
			
			if (!BidPrice.IsReady || !AskPrice.IsReady || !Volume.IsReady)
			continue;

			if (ES.BidPrice != 0 && ES.AskPrice != 0)
			{

			var _minSize = Var.Coefminsize ;
			var _quantity = ((Var.CentageLoss * accountCurrencyCash)/(Var.valpoint*(((AskPrice[0]+BidPrice[0])/2)-Var.SLShort*((AskPrice[0]+BidPrice[0])/2))/Var.minprizefluct)) ;
			var _quantityy = (decimal)(Volume[0]+Volume[1]) * 0.01m;
			
			if (AskPrice[0]-BidPrice[0] <= Var.minprizefluct || (AskPrice[0]-BidPrice[0]) > 0)
			{
			if (Volume[1] > Var.minVolume) 
			{
			if (Volume[0]>(Var.coefVolume*Volume[1])) 
			{
			
		
			if (BidPrice[0]>AskPrice[1]) 
			{
			if (AskPrice[1]<BidPrice[2]) 
			{
			if ((BidPrice[0]-AskPrice[1]) >= _minSize) 
			{
			if ((BidPrice[0]-AskPrice[1])*Var.coefBidAskSize < (BidPrice[2]-AskPrice[1])) 
			{
		if (((decimal)(Volume[0]+Volume[1]) * 0.01m)<_quantity)
			{
			
			this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
			{
			return new OneCancelsOtherTicketSet(
			O_.LimitOrder(ES.Symbol, -_quantityy, FillPrice * Var.TPLong, "Profit Long _Target"),
			O_.StopMarketOrder(ES.Symbol, -_quantityy, FillPrice * Var.SLLong, "Stop Long _Loss"));
			};
			this.EntryOrder = MarketOrder(ES.Symbol, _quantityy, false, "Entry");
			break;
			}
			
		if (((decimal)(Volume[0]+Volume[1]) * 0.01m)>_quantity)
			{
			this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
			{
			return new OneCancelsOtherTicketSet(
			O_.LimitOrder(ES.Symbol, -_quantity, FillPrice * Var.TPLong, "Profit Long _Target"),
			O_.StopMarketOrder(ES.Symbol, -_quantity, FillPrice * Var.SLLong, "Stop Long _Loss"));
			};
			
			this.EntryOrder = MarketOrder(ES.Symbol, _quantity, false, "Entry");
			break;
			}	
			}}}}
			
			if (AskPrice[0]<BidPrice[1]) 
			{
			if (BidPrice[1]>AskPrice[2]) 
			{
			if ((BidPrice[1]-AskPrice[0]) >= _minSize) 
			{
			if ((BidPrice[1]-AskPrice[0])*Var.coefBidAskSize < (BidPrice[1]-AskPrice[2])) 
			{
		if (((decimal)(Volume[0]+Volume[1]) * 0.01m)<_quantity)
			{
			
			this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
			{
			return new OneCancelsOtherTicketSet(
			O_.LimitOrder(ES.Symbol, -_quantityy, FillPrice * Var.TPShort, "Profit Short _Target"),
			O_.StopMarketOrder(ES.Symbol, -_quantityy, FillPrice * Var.SLShort, "Stop Short _Loss"));
			};
			
			this.EntryOrder = MarketOrder(ES.Symbol, _quantityy, false, "Entry");
			break;	
			}
			
		if (((decimal)(Volume[0]+Volume[1]) * 0.01m)>_quantity)
			{
			this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
			{
			return new OneCancelsOtherTicketSet(
			O_.LimitOrder(ES.Symbol, -_quantity, FillPrice * Var.TPShort, "Profit Short _Target"),
			O_.StopMarketOrder(ES.Symbol, -_quantity, FillPrice * Var.SLShort, "Stop Short _Loss"));
			};
			
			this.EntryOrder = MarketOrder(ES.Symbol, _quantity, false, "Entry");
			break;	
			}
			}}}}
				
			}}}}}}
                }
        }

        public override void OnOrderEvent(OrderEvent orderEvent)
       	{
        	if (EntryOrder != null)
            {
                this.EntryOrder = null;
            }

            if (orderEvent.Status == OrderStatus.Filled || orderEvent.Status == OrderStatus.PartiallyFilled)
            {
                if (this.OnOrderFilledEvent != null)
                {
                    this.ProfitLossOrders = OnOrderFilledEvent(this, orderEvent.Symbol, orderEvent.FillPrice);
                    OnOrderFilledEvent = null;
                } 
                else if (this.ProfitLossOrders != null)
                {
                    this.ProfitLossOrders.Filled();
                    this.ProfitLossOrders = null;
                }
            }
       	}
       	
       	public class CustomSlippageModel : ISlippageModel
        {
            private readonly QCAlgorithm _algorithm;
            
            public RollingWindow<decimal> High = new RollingWindow<decimal>(2);
            public RollingWindow<decimal> Low = new RollingWindow<decimal>(2);
            public RollingWindow<decimal> Volume = new RollingWindow<decimal>(2);
			
            public CustomSlippageModel(QCAlgorithm algorithm)
            {
				_algorithm = algorithm;
			}

            public decimal GetSlippageApproximation(Security asset, Order order)
            {			
    			High.Add(asset.High);
    			Low.Add(asset.Low);
    			Volume.Add(asset.Volume);
    			
    			var orderVolume = order.AbsoluteQuantity;
    			var slippage = (High[0]-Low[0]) * 0.01m / (Volume[0]/orderVolume);
    			
    			if (asset.Symbol.StartsWith("ES"))
    			{
    			if (((High[0]-Low[0]) * 0.01m / (Volume[0]/orderVolume)) < Var.minprizefluct)
    			{
    				return 0.25m ;
    			}
    			}
  
				return slippage;
            }
            
        }

        /// <summary>
       	/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
       	/// </summary>
       	public bool CanRunLocally { get; } = true;

       	/// <summary>
       	/// This is used by the regression test system to indicate which languages this algorithm is written in.
       	/// </summary>
       	public Language[] Languages { get; } = { Language.CSharp };

    }
}
namespace Quant
{
    public class OneCancelsOtherTicketSet
    {
        public OneCancelsOtherTicketSet(params OrderTicket[] orderTickets)
        {
            this.OrderTickets = orderTickets;
        }

        private OrderTicket[] OrderTickets { get; set; }

        public void Filled()
        {
            // Cancel all the outstanding tickets.
            foreach (var orderTicket in this.OrderTickets)
            {
                if (orderTicket.Status == OrderStatus.Submitted)
                {
                    orderTicket.Cancel();
                }
            }
        }
    }

}
namespace Quant
{
public static class Var
{
	public const decimal MaxQuantity = 50m ;
	public const decimal CentageLoss = 0.1m ;
	public const decimal valpoint = 12.5m ;
	public const decimal minprizefluct = 0.25m ;
	
    public const decimal Coefminsize = minprizefluct ;
	public const decimal coefBidAskSize = 4m ;
	public const decimal coefVolume = 0.98m ;
	public const int	 minVolume = 15800 ;
	public const decimal TPLong = 1.001m ;
	public const decimal SLLong = 0.972m ;
	public const decimal TPShort = 1.001m ;
	public const decimal SLShort = 0.972m ;
}
}