Overall Statistics
using System.Net; 

namespace QuantConnect.Algorithm.CSharp
{
    public class ParticleTransdimensionalCoreWave : QCAlgorithm
    {
		private QuantConnect.Securities.Future.Future future; 
		private List<ContractData> contractDataList; 
		private int lookback = 60; 
		private double takeProfit = 0.001; 
		private double stopLoss = 0.001; 
		
        public override void Initialize()
        {
            SetStartDate(2019, 8, 1);  //Set Start Date     
            SetEndDate(2019, 10, 1);  //Set Start Date
            SetCash(100000);             //Set Strategy Cash
            

            future = AddFuture(Futures.Energies.CrudeOilWTI, Resolution.Minute); //or https://www.quantconnect.com/lean/documentation/topic26533.html
        	future.SetFilter(TimeSpan.FromDays(0), TimeSpan.FromDays(182)); 
			
			contractDataList = new List<ContractData>(); 
        }
        
        public override void OnOrderEvent(OrderEvent orderEvent)
		{
			var order = Transactions.GetOrderById(orderEvent.OrderId);
		    if (orderEvent.Status == OrderStatus.Filled)
		    {
		        var symbol = orderEvent.Symbol;
		        var fillQuantity = orderEvent.FillQuantity;
		        var fillPrice = orderEvent.FillPrice;
		        Debug(string.Format("Open {0} Position on {1}", symbol, fillPrice)); 
		        
		        //order.Update(new UpdateOrderFields
                //{
                    // we could change the quantity, but need to specify it
                    //Quantity = 
                //    StopPrice = fillPrice * (decimal)(1 + takeProfit),
                //    LimitPrice = fillPrice * (decimal)(1 - stopLoss)
                //});
                if (order.Type == OrderType.Limit || order.Type == OrderType.StopLimit) 
                {
        			Transactions.CancelOpenOrders(symbol);
                }
	        	if (order.Type == OrderType.Market)
	        	{
	        		Debug($"{order}");
	        		return;
	        	}
		    }
		  
		}

        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// Slice object keyed by symbol containing the stock data
        public override void OnData(Slice data)
        {
            if (!Portfolio.Invested)
            {
				// In OnData(Slice slice)
				FuturesChain chain;
				// Explore the future contract chain
				if (data.FuturesChains.TryGetValue(future.Symbol, out chain))
				{
					var underlying = chain.Underlying;
					
					foreach (var contract in chain.Contracts)
					{
					    var sym = contract.Value.Symbol;
					    
						if (contractDataList.Count() < 1 || !contractDataList.Any(d => d.Symbol == sym))
						{
					    	contractDataList.Add(new ContractData(contract.Value.Symbol, lookback, this)); 
						}
					}
				}
					
				foreach (ContractData contract in contractDataList)
				{
					if (contract.IsReady)
					{
						decimal wilrValue = contract.GetWilliamsRange(); 
						Debug(string.Format("williams range: {0}", wilrValue)); 
						
						decimal fastSto = contract.GetFastStochastic(); 
						Debug(string.Format("fast STO: {0}", fastSto)); 
						
						if (contract.IsBuySignal())
						{
							double close = (double)Securities[contract.Symbol].Close;
							var stopPrice = close * 0.099; // Trigger stop limit when price falls 1%.
							var limitPrice = close * 1.001; // Sell equal or better than 1% > close.
							var stopLimitTicket = StopLimitOrder(contract.Symbol, 10, (decimal)stopPrice, (decimal)limitPrice);
						}
						else if (contract.IsSellSignal())
						{
							
						}
					}
	
				}
				
	        }
        }
        
        public decimal GetFutureStorageData(string url)
        {
			var json = new WebClient().DownloadString(url);
			
			return 0; 
        }
    }
    
    public class ContractData 
    {		
    	private WilliamsPercentR wilr; 
		private Stochastic sto;
		public string Symbol; 
    	public ContractData(string symbol, int lookback, QCAlgorithm algo) 
    	{
    		this.Symbol = symbol; 
    		this.wilr = algo.WILR(symbol, lookback, Resolution.Minute); 
			this.sto = algo.STO(symbol, lookback, Resolution.Minute); 
    	}
    	
    	public bool IsReady { get { return wilr.IsReady && sto.IsReady; } }
    	
    	public decimal GetWilliamsRange()
    	{
    		if (!wilr.IsReady) 
    			return decimal.MaxValue;
    		
    		return wilr.Current.Value; 
    	}
    	
    	public decimal GetFastStochastic()
    	{
    		if (!sto.IsReady)
    			return decimal.MaxValue; 
    		return sto.FastStoch; 
    	}
    	
    	public bool IsBuySignal()
    	{
    		if (!this.IsReady)
    			return false; 
    		
    		decimal wpr = GetWilliamsRange(); 
    		decimal sto = GetFastStochastic(); 
    		
    		return wpr < -80 && sto < 20; 
    	}
    	
    	public bool IsSellSignal()
    	{
    		if (!this.IsReady)
    			return false; 
    		
    		decimal wpr = GetWilliamsRange(); 
    		decimal sto = GetFastStochastic(); 
    		
    		return wpr > -20 && sto > 80; 
    	}
    }
}