Overall Statistics
Total Trades
41
Average Win
7.15%
Average Loss
-5.82%
Compounding Annual Return
-12.323%
Drawdown
69.100%
Expectancy
-0.220
Net Profit
-25.687%
Sharpe Ratio
0.158
Loss Rate
65%
Win Rate
35%
Profit-Loss Ratio
1.23
Alpha
0.12
Beta
-0.428
Annual Standard Deviation
0.626
Annual Variance
0.392
Information Ratio
0.078
Tracking Error
0.645
Treynor Ratio
-0.231
Total Fees
$0.00
namespace QuantConnect 
{
    /*
    */
    public class BollingerBandsAlgorithm : QCAlgorithm 
    { 
        //Define required variables:
        int quantity = 0;
        decimal price = 0;
        decimal high = 0;
        decimal low = 0;
        decimal tolerance = 0m; //0.1% safety margin in prices to avoid bouncing.
        string symbol = "EURUSD";
        int profitTargetPercent = 1;
        DateTime sampledToday = DateTime.Now;
        
        //Set up the BB
        private AverageDirectionalIndex adx;
        private BollingerBands bb;
        private RelativeStrengthIndex rsi;
        
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {          
            SetStartDate(2015, 01, 01);
            SetEndDate(DateTime.Now);  
            SetCash(1000);
            
            //Specify the Oanda Brokerage.
            SetBrokerageModel(BrokerageName.OandaBrokerage);
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            AddSecurity(SecurityType.Forex, symbol, Resolution.Minute); //Forex
            
            adx = ADX(symbol, 14, Resolution.Daily);
            bb = BB(symbol, 20, 2, MovingAverageType.Simple, Resolution.Daily);
            rsi = RSI(symbol, 14, MovingAverageType.Simple, Resolution.Daily);
        }
        
        //Handle TradeBar Events: a TradeBar occurs on every time-interval
        public void OnData(TradeBars data) {
            
            //One data point per day:
            if (sampledToday.Date == data[symbol].Time.Date) return;
            
            //Only take one data point per day (opening price)
            price = Securities[symbol].Close;
            high = Securities[symbol].High;
            low = Securities[symbol].Low;
            sampledToday = data[symbol].Time;
            
            //Wait until SMA's are ready:
            if (!bb.IsReady || !rsi.IsReady) return;
            
            //Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio.
            decimal cash = Portfolio.Cash;
            int holdings = Portfolio[symbol].Quantity;
            quantity = Convert.ToInt32((cash * 0.5m) / price);
            
            
            //exit: short
            if (Portfolio[symbol].IsShort) {
            	if (price > (bb.UpperBand * (1+tolerance))  && rsi > 70) {
            		Liquidate(symbol);
            		//Buy(symbol, (holdings + quantity));
            		//Log(Time.ToShortDateString() + " > Liquidate Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString());
            	}
            }
            
            //exit: long
            if (Portfolio[symbol].IsLong) {
            	if (price < (bb.LowerBand * (1+tolerance))  && rsi < 30) {
            		Liquidate(symbol);
            		//Buy(symbol, (holdings + quantity));
            		//Log(Time.ToShortDateString() + " > Liquidate Long > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString());
            	}
            }
            
            //long
            if (!Portfolio.HoldStock) {
				if (price < (bb.LowerBand * (1+tolerance)) && rsi < 30)
                {
                    LimitOrder(symbol, Math.Abs(holdings) + quantity, high);
                    //Log(Time.ToShortDateString() + "> Go Long >  Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString());
                }
            }
            
            //short
            if (!Portfolio.HoldStock) {
                if (price > (bb.UpperBand * (1+tolerance)) && rsi > 70)
                {
                    LimitOrder(symbol, -(Math.Abs(holdings) + quantity), low);
                    //Log(Time.ToShortDateString() + " > Go Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString());
                }
            }
            
            
            /*
            if (holdings > 0 || holdings == 0) {
                //If we're long, or flat: check if EMA crossed negative: and crossed outside our safety margin:
                if (price > (bb.UpperBand * (1+tolerance)) && rsi > 70 )
                {
                    //Now go short: Short-EMA signals a negative turn: reverse holdings
                    LimitOrder(symbol, -(holdings + quantity), low);
                    //Log("compare: " + price.ToString() + " == " + low.ToString());
                    //Order(symbol, -(holdings + quantity));
                    Log(Time.ToShortDateString() + " > Go Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString());
                }
                
            } else if (holdings < 0 || holdings == 0) {
                //If we're short, or flat: check if EMA crossed positive: and crossed outside our safety margin:
                if (price < (bb.LowerBand * (1+tolerance)) && rsi < 30)
                {
                    //Now go long: Short-EMA crossed above long-EMA by sufficient margin
                    LimitOrder(symbol, Math.Abs(holdings) + quantity, high);
                    //Order(symbol, Math.Abs(holdings) + quantity);
                    Log(Time.ToShortDateString() + "> Go Long >  Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString());
                }
            }
            */

            Plot(symbol, "BB", bb);
            Plot(symbol, "RSI", rsi);
            Plot(symbol, "Close", price);
            Plot(symbol, "High", high);
        }
    }
}