| Overall Statistics |
|
Total Trades 250 Average Win 0.43% Average Loss -0.12% Compounding Annual Return 42.904% Drawdown 4.700% Expectancy 2.597 Net Profit 47.305% Sharpe Ratio 1.383 Loss Rate 21% Win Rate 79% Profit-Loss Ratio 3.54 Alpha 43.952 Beta -3174.121 Annual Standard Deviation 0.19 Annual Variance 0.036 Information Ratio 1.31 Tracking Error 0.19 Treynor Ratio 0 Total Fees $0.00 |
from QuantConnect.Indicators 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):
#####################
# Backtest Settings #
#####################
self.SetStartDate(2016, 6, 1) # Set Start Date
self.SetEndDate(2017, 7, 1) # Set End Date
self.SetCash(10000) # Set Strategy Cash
self.SetBrokerageModel(BrokerageName.GDAX)
###########################
# Configurable parameters #
###########################
self.target_crypto = "BTCUSD" # Can be ETHUSD, LTCUSD, BTCUSD, or BCCUSD
self.indicator_name = "bollinger" # bollinger or momentum
self.warmup_lookback = 20 # Number of time resolution to load
self.time_resolution = Resolution.Minute # Resolution of periods/data to use
# For bollinger
self.moving_average_type = MovingAverageType.Exponential # See https://github.com/QuantConnect/Lean/blob/bc9af8784b02715000a2030e9757ef63b484378e/Indicators/MovingAverageType.cs
self.bollinger_period = 20
self.k = 2
# For momentum
self.momentum_period = 5
############################
# Indicators and processes #
############################
# Add Symbol
self.AddCrypto(self.target_crypto, self.time_resolution)
if self.indicator_name == "bollinger":
# Create bollinger band
self.Bolband = self.BB(self.target_crypto, self.bollinger_period, self.k, self.moving_average_type, self.time_resolution)
# Plot Bollinger Band
self.PlotIndicator(
"Indicators",
self.Bolband.LowerBand,
self.Bolband.MiddleBand,
self.Bolband.UpperBand,
)
elif self.indicator_name == "momentum":
# Create a momentum indicator over 3 days
self.mom = self.MOM(self.target_crypto, self.momentum_period)
# Plot Momentum
self.PlotIndicator(
"Indicators",
self.mom
)
# Pump historical data into the indicators before algo start
self.SetWarmUp(self.warmup_lookback,self.time_resolution)
def OnData(self, data):
holdings = self.Portfolio[self.target_crypto].Quantity
last_price = self.Securities[self.target_crypto].Close
ask_price = self.Securities[self.target_crypto].AskPrice
bid_price = self.Securities[self.target_crypto].BidPrice
amount = self.Portfolio.TotalPortfolioValue / last_price
# Check to see if there is an open order and if it is taking too long to fill. Check to see if the ask moved
# If the ask moved by > 1%, then adjust the price to the new bid/ask price. Don't make another order while there are open orders
if len(self.Transactions.GetOpenOrders(self.target_crypto)) > 0:
open_order = self.Transactions.GetOpenOrders(self.target_crypto)[0]
self.Debug("Updating order price")
if float(open_order.Price - last_price) > abs(float(open_order.Price)*.01):
updateOrderFields = UpdateOrderFields()
updateOrderFields.LimitPrice = last_price
print("ask_price: %s bid_price: %s " % (ask_price,bid_price))
updateOrderFields.LimitPrice = ask_price if open_order.Direction > 0 else bid_price
self.Transactions.GetOrderTicket(open_order.Id).Update(updateOrderFields)
return
if self.indicator_name == "bollinger":
# buy if price closes above upper bollinger band
if holdings == 0 and last_price > self.Bolband.LowerBand.Current.Value:
limitOrderTicket = self.LimitOrder(self.target_crypto, amount, ask_price)
# sell if price closes below middle bollinger band
elif holdings > 0 and last_price < self.Bolband.MiddleBand.Current.Value:
limitOrderTicket = self.LimitOrder(self.target_crypto, -holdings, bid_price)
elif self.indicator_name == "momentum":
mom = self.mom.Current.Value
return
def OnOrderEvent(self, orderEvent):
order = self.Transactions.GetOrderById(orderEvent.OrderId)
self.Debug("{0}: {1}: {2}".format(self.Time, order.Type, orderEvent))