Overall Statistics
Total Trades
9522
Average Win
0.06%
Average Loss
-0.08%
Compounding Annual Return
190.724%
Drawdown
34.700%
Expectancy
0.481
Net Profit
549.569%
Sharpe Ratio
0.779
Loss Rate
14%
Win Rate
86%
Profit-Loss Ratio
0.72
Alpha
1.489
Beta
0.316
Annual Standard Deviation
1.933
Annual Variance
3.735
Information Ratio
0.752
Tracking Error
1.934
Treynor Ratio
4.769
Total Fees
$34746.70
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.Slippage;
using QuantConnect.Orders;
using QuantConnect.Data.Consolidators;

namespace Test
{
    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);
 
        private OrderTicket EntryOrder { get; set; }
        private Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; }
        private OneCancelsOtherTicketSet ProfitLossOrders { get; set; }
        
        
        private const string Testalgo = Futures.Metals.Palladium ;
        public Symbol contract = QuantConnect.Symbol.Create(Testalgo, SecurityType.Future, Market.USA);

        public override void Initialize() 
        {
            SetStartDate(2018, 01, 01);
            SetEndDate(DateTime.Now);
            SetCash(1000000);
            
            var contract = AddFuture(Testalgo, Resolution.Minute);
            contract.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(365));
            
            contract.SetSlippageModel(new CustomSlippageModel(this));
        }

        public override void OnData(Slice slice)
        {	
                foreach(var chain in slice.FutureChains)
                {

                    if (chain.Value.Symbol.StartsWith("PA"))
                	{

                    var test = (from futuresContract in chain.Value.OrderBy(x => x.Expiry) 
                    			where futuresContract.Expiry > Time.Date.AddDays(1) 
                    			select futuresContract).FirstOrDefault();

                    AskPrice.Add(test.AskPrice);
					BidPrice.Add(test.BidPrice);
            		Volume.Add(test.Volume);

            		if (!AskPrice.IsReady || !BidPrice.IsReady || !Volume.IsReady)
					continue;

						if (test != null)
						{
                    		if (test.LastPrice != 0)
							{
        					        	var _CashLoss = 50000 ;	
        					        	var _valpoint = 5 ; 	
        					        	var _minprizefluc = 0.05m ;
										var _TPLong = 1.0002m ;	
										var _SLLong = 0.8m ;	
										var _TPShort = 1.0002m ; 	
										var _SLShort = 0.8m ;	
										var _quantity = (_CashLoss/(_valpoint*(((AskPrice[0]+BidPrice[0])/2)-_SLShort*((AskPrice[0]+BidPrice[0])/2))/_minprizefluc)) ;	
										
										
										if (BidPrice[0]>AskPrice[1])
										{
										if (BidPrice[2]>AskPrice[1])
										{
										this.OnOrderFilledEvent = (Testalgo, Symbol, FillPrice) =>
   	            						{
   	            							return new OneCancelsOtherTicketSet(
	                    					Testalgo.LimitOrder(test.Symbol, -_quantity, FillPrice * _TPLong, "Profit Long _Target"),
	                    					Testalgo.StopMarketOrder(test.Symbol, -_quantity, FillPrice * _SLLong, "Stop Long _Loss"));
	            						};
	            						this.EntryOrder = MarketOrder(test.Symbol, _quantity, false, "Entry");
        								}}
        								

        								if (AskPrice[0]<BidPrice[1])
										{
										if (AskPrice[2]<BidPrice[1])
										{
    									this.OnOrderFilledEvent = (Testalgo, Symbol, FillPrice) =>
   	            						{
   	            							return new OneCancelsOtherTicketSet(
	                    					Testalgo.LimitOrder(test.Symbol, -_quantity, FillPrice * _TPLong, "Profit Short _Target"),
	                    					Testalgo.StopMarketOrder(test.Symbol, -_quantity, FillPrice * _SLLong, "Stop Short _Loss"));
	            						};
	            							this.EntryOrder = MarketOrder(test.Symbol, _quantity, false, "Entry");
        								}}
							}
						}
                	}
                }
        }

        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 CustomSlippageModel(QCAlgorithm algorithm)
            {
                _algorithm = algorithm;
            }

            public decimal GetSlippageApproximation(Security asset, Order order)
            {
                // custom slippage math
                var slippage = asset.Price*0.01m*(decimal) Math.Log10(2*(double) order.AbsoluteQuantity);

                _algorithm.Log("CustomSlippageModel: " + slippage);
                return slippage;
            }
        }

        /// <summary>
        /// Margin call warning event handler. This method is called when Portfolio.MarginRemaining is under 5% of your Portfolio.TotalPortfolioValue
        /// </summary>
        public override void OnMarginCallWarning()
        {
            // this code gets called when the margin remaining drops below 5% of our total portfolio value, it gives the algorithm
            // a chance to prevent a margin call from occurring

            // prevent margin calls by responding to the warning and increasing margin remaining
            var contractHoldings = Securities["DOW30, SP500"].Holdings.Quantity;
            var shares = (int)(-contractHoldings * .005m);
            Error(string.Format("{0} - OnMarginCallWarning(): Liquidating {1} shares of SPY to avoid margin call.", Time, shares));
            MarketOrder("DOW30, SP500", shares);
        }
        
        /// <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 QuantConnect {

    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();
                }
            }
        }
    }

}