Overall Statistics
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 Test
        {
    public class TestAlgo : QCAlgorithm
    {
    	public RollingWindow<decimal> BidPrice = new RollingWindow<decimal>(5);
    	
    	public RollingWindow<decimal> AskPrice = new RollingWindow<decimal>(5);
    	
    	public RollingWindow<decimal> Volume = new RollingWindow<decimal>(5);
 
        private OrderTicket EntryOrder { get; set; }
        private Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; }
        private OneCancelsOtherTicketSet ProfitLossOrders { get; set; }
        
        private const string Testalgo = Futures.Indices.Nikkei225Dollar;
        public Symbol test = QuantConnect.Symbol.Create(Testalgo, SecurityType.Future, Market.USA);

        public override void Initialize() 
        {
            SetStartDate(2010, 01, 01);
            SetEndDate(DateTime.Now);
            SetCash(1000000);
            
            var test = AddFuture(Testalgo, Resolution.Minute);
            test.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(365));
        }

        public override void OnData(Slice slice)
        {	
        	
        	if (Time.DayOfWeek == DayOfWeek.Friday)
                	{
                	if (Time.Hour >= 16)
                	{
                		return;
                	}}
                	
                	if (Time.DayOfWeek == DayOfWeek.Saturday && Time.DayOfWeek == DayOfWeek.Sunday)
                	{
                		return;
                	}
                	
                	
                	DateTime dt = Time;
                	if (dt.DayOfWeek == DayOfWeek.Friday)
                	{
                	if (Time.Hour == 15 && Time.Minute == 59)
                	{
                	foreach (var holding in Portfolio.Values)
            		{
            		if (holding.HoldStock)
            		{
            			MarketOnCloseOrder(holding.Symbol, -holding.Quantity, tag: "Liquidate Market Close");
            		}
            		}}}
            		
                foreach(var chain in slice.FutureChains)
                {
                    if (chain.Value.Symbol.StartsWith("NKD"))
                	{
                    
                    var contract = (from futuresContract in chain.Value.OrderBy(x => x.Expiry) 
                    					where futuresContract.Expiry > Time.Date.AddDays(9) 
                    					select futuresContract).FirstOrDefault();

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

						if (contract != null)
						{
                    				if (contract.LastPrice != 0)
										{

										var test_Leverage = 6.6m;
										var test_minSize = ((contract.LastPrice*1.001m)-contract.LastPrice) ;
										var test_TPLong = 1.001m ;
										var test_SLLong = 0.95m ;
										var test_TPShort = 1.001m ;
										var test_SLShort = 0.95m ;
										
								
										if (BidPrice[0]>AskPrice[1])
										{
										if (BidPrice[2]>AskPrice[1])
										{
										if ((BidPrice[0]-AskPrice[1]) > test_minSize)
										{

    									this.OnOrderFilledEvent = (Testalgo, Symbol, FillPrice) =>
   	            						{
   	            							return new OneCancelsOtherTicketSet(
	                    					Testalgo.LimitOrder(contract.Symbol, -1, FillPrice * test_TPLong, "Profit Long test_Target"),
	                    					Testalgo.StopMarketOrder(contract.Symbol, -1, FillPrice * test_SLLong, "Stop Long test_Loss"));
	            						};
	            							this.EntryOrder = MarketOrder(contract.Symbol, 1, false, "Entry");
        								}}}
        								
        								
        								if (AskPrice[0]<BidPrice[1])
										{
										if (AskPrice[2]<BidPrice[1])
										{
										if ((BidPrice[1]-AskPrice[0]) > test_minSize)
										{

    									this.OnOrderFilledEvent = (Testalgo, Symbol, FillPrice) =>
   	            						{
   	            							return new OneCancelsOtherTicketSet(
	                    					Testalgo.LimitOrder(contract.Symbol, -1, FillPrice * test_TPLong, "Profit Short test_Target"),
	                    					Testalgo.StopMarketOrder(contract.Symbol, -1, FillPrice * test_SLLong, "Stop Short test_Loss"));
	            						};
	            							this.EntryOrder = MarketOrder(contract.Symbol, 1, 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 override void OnMarginCall(List<SubmitOrderRequest> requests)
        {
            // this code gets called BEFORE the orders are placed, so we can try to liquidate some of our positions
            // before we get the margin call orders executed. We could also modify these orders by changing their
            // quantities
            foreach (var order in requests.ToList())
            {
                // liquidate an extra 10% each time we get a margin call to give us more padding
                var newQuantity = (int)(Math.Sign(order.Quantity) * order.Quantity * 1.1m);
                requests.Remove(order);
                requests.Add(new SubmitOrderRequest(order.OrderType, order.SecurityType, order.Symbol, newQuantity, order.StopPrice, order.LimitPrice, Time, "OnMarginCall"));
            }
        }

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

}