Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
namespace QuantConnect 
{   
    /*
    *   QuantConnect University: Full Basic Template:
    *
    *   The underlying QCAlgorithm class is full of helper methods which enable you to use QuantConnect.
    *   We have explained some of these here, but the full algorithm can be found at:
    *   https://github.com/QuantConnect/QCAlgorithm/blob/master/QuantConnect.Algorithm/QCAlgorithm.cs
    */
    public class BasicTemplateAlgorithm : QCAlgorithm
    {
        //Initialize the data and resolution you require for your strategy:
        
        string symbol = "EURUSD";
        int quantity = 100000;
        
        List<decimal> xBuffer = new List<decimal>();
        List<decimal> yBuffer = new List<decimal>();
        
        List<DateTime> yBufferTime = new List<DateTime>();
    	
    	DateTime prevTickTime = new DateTime();
    	
    	private OrderTicket CurrentOrder;
    	private OrderTicket StopLoss;
    	private OrderTicket ProfitTarget;
    	
    	public string regPeriod = "M15";
    	public int fastRegPeriods = 20;
    	public int slowRegPeriods = 80;
    	
    	public decimal noOfStandardDeviations = 2;
    	
    	//previous states of security and indicators (to be campared with current state)
    	decimal prevTickAvgPrice = 0m;
    	decimal prevRegFastL0 = 0m;
    	decimal prevRegFastU0 = 0m;
    	
    	
    	//Minimum Slope needed for entries. Emperical for now.
    	decimal minSlowSlope = .000003m; //.5 adj pip per 15 min candle
    	decimal minFastSlope = .000003m; //.5 adj pip per 15 min candle
    	
    	//Minimum and Maximum SD for entries. Emperical for now. Maximum can be increased if algo can be switched off during high vol events.
    	decimal minFastSD = .0005m; //5 adj pips
    	decimal maxFastSD = .0030m; //30 adj pips
    	
    	
    	//time for strategy ()..in hours for now
    	int strategyStartHour = 5; //30 min after LSE open
    	int strategyEndHour = 8; //30 min before US open
    	
    	
        public override void Initialize() 
        {
			
            //Start and End Date range for the backtest:
            SetStartDate(2016, 4, 10);         
            SetEndDate(DateTime.Now.Date.AddDays(-1));
            
            //Cash allocation
            SetCash(50000);
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            AddSecurity(SecurityType.Forex, symbol, Resolution.Second);
            
            //MinuteIdentity = Identity(Symbol, Resolution.Minute);
			//MinuteIdentity.Updated += MinuteIdentity_Updated;
        }

        
         //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
        public void OnData(TradeBars data) 
        {   
           
            
            if (!Portfolio.HoldStock) 
            {
                
                //get last tick values in a second
                decimal lastTickAvgPrice = data[symbol].Close;
                
                //get time of tick data
                DateTime lastTickTime = data[symbol].Time;
                
                
                int tickMinute = lastTickTime.Minute;
                int tickSecond = lastTickTime.Second;
                
                if(lastTickTime.Minute % 15 == 0 && lastTickTime.Second == 0)
                {
                	Debug(lastTickTime + " " + lastTickAvgPrice);
                }
                //Debug("tickMinute: " + tickMinute.ToString());
                //Debug("tickSecond: " + tickSecond.ToString());
                
                
                if(xBuffer.Count == 0)
                {
                	//first tick data
                	yBuffer.Add(lastTickAvgPrice);
                	yBufferTime.Add(lastTickTime);
                	xBuffer.Add(1);
                	prevTickTime = lastTickTime;
                		
                }
                	
                	//Debug("PrevTickTime: " + prevTickTime.ToString());
                	//Debug("lastTickTime: " + lastTickTime.ToString());
                	
                if(xBuffer.Count < slowRegPeriods)
                {
                	//Create first data points
                	
                	
                		if(lastTickTime > prevTickTime && ((lastTickTime.Minute % 15) < (prevTickTime.Minute % 15)))
                		{
                			// new candle
                			yBuffer.Add(lastTickAvgPrice);
                			yBufferTime.Add(lastTickTime);
                			xBuffer.Add(xBuffer.Count + 1);
                			
                			//Debug(yBufferTime[yBufferTime.Count - 1] + " " + yBuffer[yBuffer.Count - 1]);
                		}
                		else
                		{
                			//Update price list for new data within candle
                			yBuffer.RemoveAt(yBuffer.Count - 1);
                			yBuffer.Add(lastTickAvgPrice);
                			
                			yBufferTime.RemoveAt(yBufferTime.Count - 1);
                			yBufferTime.Add(lastTickTime);
                			
                		}
                	
                	
                }
                
                for(int i=0;i<yBuffer.Count;i++)
                {
                	//Debug(yBufferTime[i] + " " + yBuffer[i] + " ");
                }
                
                /*
                else
                //update price list for new data
                {
                	if((lastTickTime.Minute % 15) < (prevTickTime.Minute % 15) && lastTickTime > prevTickTime)
                	{
                		//Debug("tickMinute % 15" + (tickMinute % 15));
                		//update for new candle
                		yBuffer.RemoveAt(0);
                		yBuffer.Add(lastTickAvgPrice);
                		
                		yBufferTime.RemoveAt(0);
                		yBufferTime.Add(lastTickTime);
                	}
                	
                	else
                	{
                		//update closing on existing candle
                		yBuffer.RemoveAt(yBuffer.Count - 1);
                		yBuffer.Add(lastTickAvgPrice);
                		
                		yBufferTime.RemoveAt(yBufferTime.Count - 1);
                		yBufferTime.Add(lastTickTime);
                	}
                	
                	for(int i=0;i<yBuffer.Count;i++)
                	{
                		
                		Debug(yBufferTime[i] + " " + yBuffer[i] + " ");
                	}
                	//calculate new channels
                	decimal standardError = 0;
                	decimal lastRegPrice = 0;
                	decimal regSlope = 0;
                	
                	//Slow Channel
                	//CalculateRegressionChannel(xBuffer,yBuffer,out standardError, out lastRegPrice, out regSlope);
                	
                	decimal regSlowSlope = regSlope;
                	
                	//Fast Channel
                	List<decimal> xBufferFast = xBuffer.GetRange(0,fastRegPeriods);
                	List<decimal> yBufferFast = yBuffer.GetRange(xBuffer.Count - fastRegPeriods, fastRegPeriods);
                	
                	//CalculateRegressionChannel(xBufferFast,yBufferFast,out standardError, out lastRegPrice, out regSlope);
                	
                	decimal regFastSlope = regSlope;
                	decimal regFastM0 = lastRegPrice;
                	decimal regFastL0 = lastRegPrice - noOfStandardDeviations * standardError;
                	decimal regFastU0 = lastRegPrice + noOfStandardDeviations * standardError;
                	decimal sDFast = standardError;
                	
                	decimal holdings = Portfolio[symbol].Quantity;
                	
                	//Debug("holdings: " + holdings.ToString());
		            //Debug("LineRegFast Lower Channel: " + regFastL0.ToString());
					//Debug("Slope Slow: " + regSlowSlope.ToString());
					//Debug("Time: " + Time.Date.ToString() + Time.Hour.ToString());
					//Debug("Price: " + lastTickAvgPrice.ToString());
				//	Debug("Standard Deviation: " + sDFast.ToString());
                	
                	//entry conditions
                	if(Time.Hour >= strategyStartHour && Time.Hour <= strategyEndHour)
		            {
		            	
		            	if(holdings == 0 && sDFast > minFastSD && sDFast < maxFastSD)
		            	{
		            		
		            		if(regSlowSlope > minSlowSlope && regFastSlope > minFastSlope && lastTickAvgPrice < regFastL0 && prevTickAvgPrice > prevRegFastL0)
		            		{
		            			//buy signal
		            			//Debug("holdings: " + holdings.ToString());
		            			//Debug("LineRegFast Lower Channel: " + hRegFastL0.ToString());
					            //Debug("Slope Slow: " + slopeSlow.ToString());
					            //Debug("Time: " + Time.Date.ToString() + Time.Hour.ToString());
					            //Debug("Price: " + close.ToString());
					            //Debug("Standard Deviation: " + sDFast.ToString());
					            //Debug("noOfDeviations: " + linRegFast.noOfDeviations.ToString());
					            //Debug("noOfSamples: " + linRegFast.noOfSamples.ToString());
					            //Debug("noOfPeriods: " + linRegFast.noOfPeriods.ToString());
					            //Debug("xBuffer Count: " + linRegFast.xBuffer.Count.ToString());
					            //Debug("yBuffer Count: " + linRegFast.yBuffer.Count.ToString());
					            //Debug("xBuffer Last: " + linRegFast.xBuffer[linRegFast.xBuffer.Count - 1].ToString());
					            //Debug("yBuffer Last: " + linRegFast.yBuffer[linRegFast.xBuffer.Count - 1].ToString());
		            			CurrentOrder = Order(symbol, quantity);
		            			StopLoss = StopMarketOrder(symbol,-quantity, 2 * regFastL0 - regFastM0);
		            			ProfitTarget = LimitOrder(symbol, -quantity, regFastM0);
		            		}
		            		
		            		else if(regSlowSlope < -minSlowSlope && regFastSlope < -minFastSlope && lastTickAvgPrice > regFastU0 && prevTickAvgPrice < regFastU0)
		            		{
		            			//sell signal
		            			CurrentOrder = Order(symbol, -quantity);
		            			StopLoss = StopMarketOrder(symbol,quantity,2 * regFastU0 - regFastM0);
		            			ProfitTarget = LimitOrder(symbol, quantity,regFastM0);
		            		}
		            	}
		            }
                	prevRegFastL0 = regFastL0;
                	prevRegFastU0 = regFastU0;
                }*/
                //previous state = present state
                prevTickAvgPrice = lastTickAvgPrice;
                	
                prevTickTime = lastTickTime;
            }
        }
        
        
        // If the StopLoss or ProfitTarget is filled, cancel the other
        // If you don't do this, then  the ProfitTarget or StopLoss order will remain outstanding
        // indefinitely, which will cause very bad behaviors in your algorithm
        public override void OnOrderEvent(OrderEvent orderEvent)
		{
			// Ignore OrderEvents that are not closed
			if (!orderEvent.Status.IsClosed())
			{
				return;
			}
			
			// Defensive check
			if (ProfitTarget == null || StopLoss == null)
			{
				return;
			}
			
			var filledOrderId = orderEvent.OrderId;

			// If the ProfitTarget order was filled, close the StopLoss order
			if (ProfitTarget.OrderId == filledOrderId)
			{
				StopLoss.Cancel();
			}

			// If the StopLoss order was filled, close the ProfitTarget
			if (StopLoss.OrderId == filledOrderId)
			{
				ProfitTarget.Cancel();
			}
			
		}
    

		public void CalculateRegressionChannel(List<decimal> xBuffer, List<decimal> yBuffer, out decimal standardError, out decimal lastRegPrice, out decimal regSlope)
        {
        	int count = xBuffer.Count;
        	decimal xAvg = xBuffer.Average();
        	decimal yAvg = yBuffer.Average();
        	
        	//Debug("xAvg: " + xAvg.ToString());
        	//Debug("yAvg: " + yAvg.ToString());
        	
        	List<decimal> regLine = new List<decimal>();
        	
        	decimal xSD = (decimal)Math.Sqrt(xBuffer.Sum(v => Math.Pow((double)(v - xAvg),2))/(count - 1));
        	
        	decimal coVariance = 0;
        	for(int i = 0; i < count; i++)
        	{
        		coVariance += xBuffer[i] * yBuffer[i];
        		
        	}
        	coVariance = coVariance - count * xAvg * yAvg;
        	coVariance = coVariance / count;
        	
        	decimal slope = coVariance / (decimal) Math.Pow((double) xSD,2);
        	
        	decimal intercept = yAvg - slope * xAvg;
        	
        	standardError = 0;
        	lastRegPrice = 0;
        	regSlope = 0;
        	for(int i = 0; i < count; i ++)
        	{
        		regLine.Add(slope * xBuffer[i] + intercept);
        		standardError += (decimal) Math.Pow((double) (yBuffer[i] - regLine[i]),2);
        		
        	}
        	standardError = (decimal) Math.Sqrt((double) standardError/(count - 1));
        	lastRegPrice = regLine[regLine.Count - 1];
        	regSlope = regLine[regLine.Count - 1] - regLine[regLine.Count - 2];
        	
        	for(int i = 0;i<count;i++)
        	{
        		//Debug(" " + yBuffer[i].ToString());
        	}
        	//Debug("regLine[last]:  " + regLine[regLine.Count - 1]);
        	//Debug("slope: " + slope.ToString());
        	//Debug("intercept: " + intercept.ToString());
        	//Debug("x count: " + count.ToString());
        	//Debug("y count: " + yBuffer.Count.ToString());
        	//Debug("Standard Error: " + standardError.ToString());
        	
        	
        }
        
       
    }
}