Overall Statistics
Total Trades
2107
Average Win
0.35%
Average Loss
-0.22%
Compounding Annual Return
-1.097%
Drawdown
24.000%
Expectancy
-0.040
Net Profit
-5.393%
Sharpe Ratio
-0.068
Loss Rate
63%
Win Rate
37%
Profit-Loss Ratio
1.56
Alpha
-0.005
Beta
0.001
Annual Standard Deviation
0.073
Annual Variance
0.005
Information Ratio
-0.668
Tracking Error
0.137
Treynor Ratio
-4.065
Total Fees
$3370.40
namespace QuantConnect 
{   
    public class FXCMBollengerBands : QCAlgorithm
    {
        private BollingerBands bollingerBands;
        private decimal _price;
        
        private string security = "EURUSD"; 
        //private string security = "USDJPY";
        
        decimal buyBBLinePct = 0.9m;
        decimal sellBBLinePct = 0.9m;
        
        private int consolidateMinutes = 30;
        private int cash = 25000;
        
        private int backtestYears = 5;
        
        private bool wentLow = false;
        private bool wentHigh = false;
        
        int orderSize = 20000;
        
        public override void Initialize() 
        {
			
            //Start and End Date range for the backtest:

            SetStartDate(DateTime.Now.Date.AddDays(-365*backtestYears));
            SetEndDate(DateTime.Now.Date.AddDays(-1));
            
            //Cash allocation
            SetCash(cash);
            
            
            // FXCM Brokerage
            SetBrokerageModel(BrokerageName.FxcmBrokerage);
         
         
            AddSecurity(SecurityType.Forex, security, Resolution.Minute);
            Securities[security].SetLeverage(50.0m);
            
            // Setup BB Indicator
            bollingerBands = new BollingerBands(20, 2, MovingAverageType.Simple);
            
            // 15 min Trade bars
            var fifteenConsolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(consolidateMinutes));
            fifteenConsolidator.DataConsolidated += OnDataFifteen;
            SubscriptionManager.AddConsolidator(security,fifteenConsolidator);
            
            // Put it all together
            RegisterIndicator(security, bollingerBands, fifteenConsolidator, x => x.Value);
            
            SetWarmup(new TimeSpan(10, 0, 0, 0, 0));  // 10 Days
          
        }
            
      
        public void OnData(TradeBars data) 
        {   if (IsWarmingUp) return; 
        	if (!data.ContainsKey(security)) { return; }
        	// Placeholder
        }
        
        private void OnDataFifteen(object sender,TradeBar consolidated)
        {
        	if (IsWarmingUp) return; 
            _price = consolidated.Close;
            if (!bollingerBands.IsReady) return;
            
            var _buyBBLine = bollingerBands.LowerBand;
            var _sellBBLine = bollingerBands.UpperBand;
            
            Plot("BB", "Price", _price);
            Plot("BB", bollingerBands.UpperBand, bollingerBands.MiddleBand, bollingerBands.LowerBand);
            
            var adjustedBuyLine = ((bollingerBands.MiddleBand - bollingerBands.LowerBand) * 0.25m) + bollingerBands.LowerBand;
            var adjustedSellLine = ((bollingerBands.UpperBand - bollingerBands.MiddleBand) * 0.85m) + bollingerBands.MiddleBand;
            Plot("BB", "BBSell",adjustedSellLine);
            Plot("BB", "BBBuy",adjustedBuyLine);
            
            decimal buy_signal = 0;
            decimal sell_signal = 0;
            // (CalculateOrderQuantity(security,1.0m) / 1000) * 1000; // FXCM Required ordering in multiples of 1000 for standard and mini accounts https://www.fxcm.com/accounts/account-types/
            bool _buySignal = consolidated.Close < adjustedBuyLine;
            bool _sellSignal = consolidated.Close >  adjustedSellLine;
            
            /*if(!Portfolio[security].Invested)
	        {
	        	if (_buySignal) { 
                    	Order(security, orderSize);
	        	}
	        	
	        	if (_sellSignal){
	        		Order(security, orderSize * -1);
	        	}
	        	
	        }else{
	        	
	        	if ((_buySignal) && (Portfolio[security].IsShort)) { 
	        		Log("Was Short Go Long Sz"+orderSize.ToString()+" + "+(Securities[security].Holdings.Quantity * -1).ToString());
                    	Order(security, orderSize + (Securities[security].Holdings.Quantity * -1));
	        	}
	        	
	        	if ((_sellSignal) && Portfolio[security].IsLong){
	        	//	Order(security, orderSize * -1);
	        	Log("Was Long Go Short Sz"+(orderSize * -1).ToString()+" + "+(Securities[security].Holdings.Quantity * -1).ToString());
	        		Order(security, (orderSize * -1) + (Securities[security].Holdings.Quantity * -1));
	        	}
	        }*/
	        
	        if (Portfolio[security].IsLong && (consolidated.Close > (bollingerBands.MiddleBand * 1.1m)))
	        {
	        	// Bail
	        	Log("BAIL!");
	        	Liquidate();
	        }
	        
	        if (Portfolio[security].IsShort && (consolidated.Close < (bollingerBands.MiddleBand * 0.90m)))
	        {
	        	// Bail
	        	Log("BAIL!");
	        	Liquidate();
	        }
	        
	        if (wentLow || wentHigh)
	        {
		        if (wentLow && (consolidated.Close >=bollingerBands.MiddleBand ))
		        {
		        	// Go Long
		        	wentLow = false;
		        	GoLong();
		        }
		        
		        if (wentHigh && (consolidated.Close <=bollingerBands.MiddleBand ))
		        {
		        	// Go Short
		        	wentHigh = false;
		        	GoShort();
		        }
	        
	        }else{
		        if (!wentLow && consolidated.Close < bollingerBands.LowerBand)
		        {
		        	Log ("Price Breached Lower BB");
		        	wentLow = true;
		        }
		        
		        if (!wentHigh && consolidated.Close > bollingerBands.LowerBand)
		        {
		        	Log ("Price Breached Higher BB");
		        	wentHigh = true;
		        }
	        }
            
           
        }
        
        private void GoLong()
        {
        	if (Portfolio[security].IsLong) { return; }
        	Log("Go Long");
        	if (Portfolio[security].IsShort)
        	{
        		Order(security, orderSize + (Securities[security].Holdings.Quantity * -1));
        	}else{
        		Order(security,orderSize);
        	}
        }
        
        private void GoShort()
        {
        	if (Portfolio[security].IsShort) { return; }
        	Log("Go Short");
        	if (Portfolio[security].IsLong)
        	{
        		Order(security, (orderSize * -1) + (Securities[security].Holdings.Quantity * -1));
        	}else{
        		Order(security,orderSize * -1);
        	}
        }
    }
}