Hello,

I’m still new to QuantConnect and I used the recent time to read a lot in the community in order to get my head around the main concepts. In parallel I tried to practice with code.

I would like to code a basic framework that can handle the most common parts like:

  • defining the main parameters (account size, backtesting timeframe, symbol, market, resolution, brokerage, leverage, etc.)
  • defining the criteria/rules for the trading setup (including indicators if required)
  • defining the risk and order management (position size, trade entry, stop loss, take profit)
  • using Debug function 
  • using RollingWindow function
  • using Schedule function

 

Please find below my example code.

This example strategy is NOT designed to be profitable, but for learning purposes only! :-)

In this example the strategy is long-only and consists of 3 simple criteria:

  • if fast EMA > slow EMA then long
  • only enter position between 9-10am UTC
  • only have one position at a time

 

The RollingWindow function is used to derive the entry, stop loss and take profit levels from the previous candle:

  • stop buy at previous candle high
  • stop loss at previous candle low
  • take profit at previous candle high plus 10%

The Schedule function is used to handle the required trading time slot (9-10am UTC).

The Risk Management is determined by 2 requirements:

  • max risk per trade = 0.5% from portfolio value
  • max equity per trade = portfolio value * max leverage * 25%

 

I would like to use this first example code to identify and solve the main issues and potential misconceptions that I (probably) have and then take it further from there.

Your feedback and comments are highly appreciated!

Cheers, 

Thom

 

class SessionTrend(QCAlgorithm): def Initialize(self): # input self.SetTimeZone('Europe/London') self.SetCash(100000) self.SetStartDate(2019,4,1) self.SetEndDate(2019,4,30) self._max_risk_per_trade_factor = 0.005 self._max_equity_per_trade_factor = 0.25 self._maxLeverage_factor = 20.0 self._symbol = 'EURUSD' self._pricePrecision = 4 self._resolution = Resolution.Hour self._market = Market.Oanda self._brokerage = BrokerageName.OandaBrokerage self.SetBrokerageModel(self._brokerage, AccountType.Margin) # add Price Data to data self._eurusd = self.AddForex(self._symbol, self._resolution, self._market, leverage=10.0) # RollingWindow self._window = RollingWindow[QuoteBar](2) # indicators self._ema_fast = self.EMA(self._symbol, 8, self._resolution) self._ema_slow = self.EMA(self._symbol, 21, self._resolution) # schedule self._session = False self.Schedule.On(self.DateRules.EveryDay(self._symbol), self.TimeRules.At(9, 0), Action(self._sessionOn)) self.Schedule.On(self.DateRules.EveryDay(self._symbol), self.TimeRules.At(10, 0), Action(self._sessionOff)) def _sessionOn(self): self._session = True def _sessionOff(self): self._session = False def OnData(self, data): # retrieve current price data self._currentPrice = self.Securities[self._symbol].Close # add price data to RollingWindow self._window.Add(data[self._symbol]) # wait for indicator to be ready. if not self._ema_slow.IsReady: return # Setup criteria _invested = self.Portfolio[self._symbol].Invested _ema_bullish = (self._ema_fast.Current.Value > self._ema_slow.Current.Value) _condition = not _invested and self._session and _ema_bullish # long orders if _condition: # trade setup self._stopBuy = round(self._window[1].High, self._pricePrecision) self._stopLoss = round(self._window[1].Low, self._pricePrecision) self._takeProfit = round(self._window[1].High * 1.1, self._pricePrecision) # risk management self._max_equity_per_trade = self.Portfolio.TotalPortfolioValue * self._maxLeverage_factor * self._max_equity_per_trade_factor # max allowed equity per trade [currency] self._max_risk_per_trade = round(self.Portfolio.TotalPortfolioValue * self._max_risk_per_trade_factor, 0) # max allowed risk per trade [currency] self._risk_per_unit = round(self._stopBuy - self._stopLoss, self._pricePrecision) # risk per unit [currency] self._max_quantity_equity = round(self._max_equity_per_trade / self._stopBuy, 0) # max quantity per trade [nr. of contracts] based on max equity self._max_quantity_risk = round(self._max_risk_per_trade / self._risk_per_unit, 0) # max quantity per trade [nr. of contracts] based on max risk self._quantity = round(min(self._max_quantity_equity, self._max_quantity_risk), 0) # number of contracts to be ordered # order management self._marketBuyTicket = self.MarketOrder(self._symbol, self._quantity, False, 'market buy') self._limitSellTicket = self.LimitOrder(self._symbol, -self._quantity, self._takeProfit, 'target limit sell') self._stopMarketSellTicket = self.StopMarketOrder(self._symbol, -self._quantity, self._stopLoss, 'stop market sell') self.Debug(f'order time: {self.Time}, tag: {self._marketBuyTicket.Tag}, quantity: {self._marketBuyTicket.Quantity}, fill price: {self._marketBuyTicket.AverageFillPrice}, status: {self._marketBuyTicket.Status}') def OnOrderEvent(self, orderEvent): _orderFromEvent = self.Transactions.GetOrderById(orderEvent.OrderId) _orderTicketFromEvent = self.Transactions.GetOrderTicket(orderEvent.OrderId) _openOrderTickets = self.Transactions.GetOrderTickets() # OCO if _orderTicketFromEvent.Status == OrderStatus.Filled: # cancel stop loss order if _orderTicketFromEvent.Tag == 'target limit sell': for _ticket in _openOrderTickets: if _ticket.Tag == 'stop market sell': self.Debug(f'event time: {orderEvent.UtcTime}, event: {_orderTicketFromEvent.Tag}, cancelled order: {_ticket.Tag}') self.Transactions.CancelOrder(_ticket.OrderId) # cancel take profit order elif _orderTicketFromEvent.Tag == 'stop market sell': for _ticket in _openOrderTickets: if _ticket.Tag == 'target limit sell': self.Debug(f'event time: {orderEvent.UtcTime}, event: {_orderTicketFromEvent.Tag}, cancelled order: {_ticket.Tag}') self.Transactions.CancelOrder(_ticket.OrderId)