| 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.FillPricefrom 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()