Overall Statistics
Total Trades
47
Average Win
7.11%
Average Loss
-14.04%
Compounding Annual Return
-51.169%
Drawdown
70.800%
Expectancy
-0.149
Net Profit
-51.265%
Sharpe Ratio
-0.545
Probabilistic Sharpe Ratio
3.066%
Loss Rate
43%
Win Rate
57%
Profit-Loss Ratio
0.51
Alpha
-0.285
Beta
-0.214
Annual Standard Deviation
0.598
Annual Variance
0.358
Information Ratio
-0.745
Tracking Error
0.697
Treynor Ratio
1.522
Total Fees
$0.00
class AdvancedBB(QCAlgorithm):
    
    # Order ticket for our stop order, Datetime when stop order was last hit
    stopMarketTicket = None
    stopMarketOrderFillTime = datetime.min
    fill_price = 0
    highestPrice = 0
    lowestPrice = 0
    stoplosspctlong = 0.97
    stoplosspctshort = 1.01
    
    def Initialize(self):
        
        self.SetStartDate(2020, 1, 1)  #Set Start Date
        self.SetEndDate(2020, 12, 31)    #Set End Date
        self.SetCash(2000)             #Set Strategy Cash
        self.SetBrokerageModel(BrokerageName.OandaBrokerage)

        # define Cfd we want to trade on
        # for example NATGAS
        self.symbol = "NATGASUSD"
        self.AddCfd(self.symbol, Resolution.Minute, Market.Oanda)
        
        
        # Set window
        self.window = RollingWindow[QuoteBar](3)
        
        
        # create a bollinger band
        self.Bolband = self.BB(self.symbol, 20,2, MovingAverageType.Simple, Resolution.Minute)
        self.Bolband.Updated += self.BolbandUpdated
        self.BolbandWin = RollingWindow[IndicatorDataPoint](5)
        
        # set warmup period
        self.SetWarmUp(20)
        
        
    def BolbandUpdated(self, sender, updated):
        '''Adds updated values to rolling window'''
        self.BolbandWin.Add(updated)


    def OnData(self, data):
        
        if (self.Time - self.stopMarketOrderFillTime).days < 15:
            return
        
        self.window.Add(data[self.symbol])
        if not (self.window.IsReady and self.BolbandWin.IsReady): return
    
    
        currentprice = self.window[0].Close
        previousprice = self.window[1].Close
        currentlowerband = self.Bolband.LowerBand.Current.Value
        currentmiddleband = self.Bolband.MiddleBand.Current.Value
        currentupperband = self.Bolband.UpperBand.Current.Value
        available = (self.Portfolio.Cash/currentprice)*1
        

        
 #       # LONG TRANSACTIONS
  #      ##############################################
 
 #       # open LONG position
        
  #      if not self.Portfolio.Invested:
            
   #         if self.IsMarketOpen(self.symbol):
                
    #            if currentprice < currentlowerband:
                
   #                 self.stopMarketTicket = self.StopMarketOrder(self.symbol, available, self.stoplosspctlong * currentprice)
        
   #     else:
            
            # Check if the price is higher that highestPrice.
    #        if currentprice > self.highestPrice:
                
                # Save the new high to highestPrice; then update the stop price to % of highestPrice 
     #           self.highestPrice = currentprice
     #           updateFields = UpdateOrderFields()
      #          updateFields.StopPrice = self.highestPrice * self.stoplosspctlong
     #          self.stopMarketTicket.Update(updateFields)
                
                # Print the new stop price with Debug()
      #          self.Debug(str(self.symbol) + str(self.highestPrice) + " Stop (long): " + str(updateFields.StopPrice))
        
        # close LONG position
        
      #  if self.Portfolio[self.symbol].Invested and self.IsMarketOpen(self.symbol):   
                
       #     if currentprice < self.Bolband.UpperBand.Current.Value and self.fill_price > currentprice:
      #          self.Liquidate()
        
        
        # SHORT TRANSACTIONS
        ##############################################
        # open SHORT position
        
        if not self.Portfolio[self.symbol].Invested:
            
            if self.IsMarketOpen(self.symbol):
                
                if currentprice < currentupperband and previousprice >= currentupperband:
                
                    self.stopMarketTicket = self.StopMarketOrder(self.symbol, round(-available), self.stoplosspctshort * currentprice)
        
        
        else:
            
            #1. Check if the price is lower that lowestPrice.
            if currentprice < self.lowestPrice:
                
                # Save the new low to lowestPrice; then update the stop price to % of lowestPrice 
                self.lowestPrice = currentprice
                updateFields = UpdateOrderFields()
                updateFields.StopPrice = self.lowestPrice * self.stoplosspctshort
                self.stopMarketTicket.Update(updateFields)
                
                # Print the new stop price with Debug()
                self.Debug(str(self.symbol) + str(self.lowestPrice) + " Stop (short): " + str(updateFields.StopPrice))
                
                
        # close SHORT position
        
        if self.Portfolio[self.symbol].Invested and self.IsMarketOpen(self.symbol):
            if currentprice <= currentlowerband and currentprice >= previousprice:
                    self.Liquidate()
            
                
         
    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status != OrderStatus.Filled:
            return
        if self.stopMarketTicket is not None and self.stopMarketTicket.OrderId == orderEvent.OrderId: 
            self.stopMarketOrderFillTime = self.Time
            self.fill_price = orderEvent.FillPrice
from QuantConnect.Indicators import *
import numpy as np
from decimal import *
import decimal as d

### <summary>
### In this example we are looking for price to breakout above the bollinger bands
### and look to buy when we see that. We hold our position until price touches the 
### middle band of the bollinger bands.
###

class BollingerBreakoutAlgorithm(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2020, 1, 1)  #Set Start Date
        self.SetEndDate(2021, 1, 11)    #Set End Date
        self.SetCash(1000)             #Set Strategy Cash
        self.SetBrokerageModel(BrokerageName.OandaBrokerage)
        
        # define Cfd we want to trade on
        # for example NATGAS
        self.target_cfd = "NATGASUSD"
        self.AddCfd(self.target_cfd, Resolution.Hour, Market.Oanda)
        
        # Set window
        self.window = RollingWindow[QuoteBar](3)

        
        # create a bollinger band
        self.Bolband = self.BB(self.target_cfd, 20, 2, MovingAverageType.Simple, Resolution.Hour)
        self.Bolband.Updated += self.BolbandUpdated
        self.BolbandWin = RollingWindow[IndicatorDataPoint](5)
        
        # set warmup period
        self.SetWarmUp(20)

    def BolbandUpdated(self, sender, updated):
        '''Adds updated values to rolling window'''
        self.BolbandWin.Add(updated)

    
    def OnData(self, data):
        
        self.window.Add(data[self.target_cfd])
        if not (self.window.IsReady and self.BolbandWin.IsReady): return
        
        holdings = self.Portfolio[self.target_cfd].Quantity
        currentprice = self.window[0].Close
        previousprice = self.window[1].Close
        previouspreviousprice = self.window[2].Close
        currentlowerband = self.Bolband.LowerBand.Current.Value
        currentmiddleband = self.Bolband.MiddleBand.Current.Value
        lowerpctline = self.Bolband.MiddleBand.Current.Value - ((self.Bolband.MiddleBand.Current.Value - self.Bolband.LowerBand.Current.Value)* 0.30)
        selltrigger1 = self.Bolband.UpperBand.Current.Value - ((self.Bolband.UpperBand.Current.Value - self.Bolband.MiddleBand.Current.Value) * (0.30))
    

        buy_below_lowerband = (previousprice <= self.Bolband.LowerBand.Current.Value) and (currentprice > self.Bolband.LowerBand.Current.Value)
        
        
        if holdings <= 1:
            # if the previous price is lower or the same as the current lower band and the price before the previousprice is smaller and the current price is more than the current lower band then buy
            if previousprice <= currentlowerband and currentprice > currentlowerband and currentprice < currentmiddleband:
                self.SetHoldings(self.target_cfd, 1)
                
            elif previousprice <= lowerpctline and currentprice > lowerpctline and currentprice < currentmiddleband:
                self.SetHoldings(self.target_cfd, 1)
        
        if holdings > 0:
            
            # sell when the previous price is above the upper band and the current price is below the upperband - triggered after steep rise in price
            if previousprice >= self.Bolband.UpperBand.Current.Value and currentprice < self.Bolband.UpperBand.Current.Value:
                self.Liquidate()
            
            #sell when the previous price is a 25 % below the upper band and the current price is below that point - triggered after small increase in price
            elif previouspreviousprice >= previousprice and previousprice > selltrigger1 and currentprice <= selltrigger1:
                self.Liquidate()
            

            elif buy_below_lowerband:
                if currentprice == self.Bolband.MiddleBand.Current.Value:
                    self.Liquidate()