Overall Statistics |
Total Trades 606 Average Win 0.48% Average Loss -0.38% Compounding Annual Return -13.101% Drawdown 16.300% Expectancy -0.122 Net Profit -13.301% Sharpe Ratio -1.312 Probabilistic Sharpe Ratio 0.195% Loss Rate 61% Win Rate 39% Profit-Loss Ratio 1.27 Alpha -0.111 Beta 0.067 Annual Standard Deviation 0.077 Annual Variance 0.006 Information Ratio -0.941 Tracking Error 0.28 Treynor Ratio -1.489 Total Fees $106275.10 Estimated Strategy Capacity $34000000.00 Lowest Capacity Asset NQ XHYQYCUDLM9T |
from typing import Dict, List # CONFIGS RSI_period = 14 RSI_upper = 30 RSI_lower = 27 bar_size = timedelta(minutes=5) portfolio_pct = .1 stoploss_dist = 20 # distance below high for stop loss takeprofit_dist = 20 # distance above high for take profit stoplimit_dist = 5 # distance b/w the stop and limit prices of a stop limit order max_losses = 2 # max number of losses in a day debug = True # turn off to reduce logging # END CONFIGS f = False if f: from AlgorithmImports import * class Consulting(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 8, 1) self.SetEndDate(2020, 8, 5) self.SetCash(10000000) future = self.AddFuture(Futures.Indices.NASDAQ100EMini, Resolution.Minute) future.SetFilter(0, 90) self.rsi = RelativeStrengthIndex(RSI_period) self.consolidators: Dict[Symbol, QuoteBarConsolidator] = {} self.just_bought = False self.market_ticket = None # Market order ticket self.stoploss_ticket = None # StopMarket stop loss ticket self.takeprofit = None # take profit price self.high = -1 self.last_rsi = None self.loss_count = 0 self.curr_day = -1 self.quoteBar = None self.prev_contract = None self.stoploss_cumulative = 0 self.takeprofit_cumulative = 0 def OnData(self, data:Slice): # new day if self.curr_day != self.Time.day: self.curr_day = self.Time.day self.NewDay(data) return if not self.Securities[self.GetSymbol()].IsTradable: return def GetSymbol(self) -> Symbol: ''' get current front month contract ''' return list(self.consolidators.keys())[0] def NewDay(self, data:Slice): self.Plot('Stoploss count', 'count', self.stoploss_cumulative) self.Plot('Take profit count', 'count', self.takeprofit_cumulative) self.Reset() self.PruneContracts() self.ChooseContract(data) def Reset(self): self.Liquidate() self.last_rsi = None self.loss_count = 0 self.rsi.Reset() self.ResetOrders() def ChooseContract(self, data:Slice): for chain in data.FutureChains: contracts = [contract for contract in chain.Value] if len(contracts) == 0: self.Print('No contracts found') return contract = sorted(contracts, key=lambda k : k.OpenInterest, reverse=True)[0] self.SetUpContract(contract.Symbol) continue def SetUpContract(self, symbol:Symbol): # consolidate the contract data consolidator = QuoteBarConsolidator(bar_size) consolidator.DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(symbol, consolidator) self.consolidators[symbol] = consolidator def PruneContracts(self): # unconsolidate untradeable symbols for symbol in self.consolidators: consolidator = self.consolidators[symbol] self.SubscriptionManager.RemoveConsolidator(symbol, consolidator) consolidator.DataConsolidated -= self.OnDataConsolidated self.consolidators = {} def ResetOrders(self): self.market_ticket = None self.stoploss_ticket = None self.takeprofit = None def Print(self, msg): if debug: self.Log(msg) def OnDataConsolidated(self, sender, quoteBar:QuoteBar): ''' 5 minute consolidator Update RSI, SetHoldings ''' self.rsi.Update(self.Time, quoteBar.Close) self.quoteBar = quoteBar if not self.rsi.IsReady: return curr_rsi = self.rsi.Current.Value if self.loss_count > max_losses: return # self.Plot('RSI', 'Value', curr_rsi) if (not self.Portfolio.Invested and self.last_rsi and self.last_rsi < RSI_lower and curr_rsi > RSI_upper): if quoteBar.High - stoploss_dist < quoteBar.Close: symbol = self.GetSymbol() quantity = self.CalculateOrderQuantity(symbol, portfolio_pct) self.just_bought = True self.market_ticket = self.MarketOrder(symbol, quantity) if quoteBar.High > self.high: self.high = quoteBar.High if self.stoploss_ticket: updateFields = UpdateOrderFields() updateFields.StopPrice = self.high - stoploss_dist updateFields.LimitPrice = self.high - stoploss_dist - stoplimit_dist self.stoploss_ticket.Update(updateFields) if self.takeprofit and quoteBar.Close > self.takeprofit: self.takeprofit_cumulative += 1 self.Liquidate() self.ResetOrders() self.last_rsi = curr_rsi def OnOrderEvent(self, orderEvent: OrderEvent): if self.just_bought: self.just_bought = False self.stoploss_ticket = self.StopLimitOrder(orderEvent.Symbol, -orderEvent.Quantity, self.quoteBar.High - stoploss_dist, self.quoteBar.High - stoploss_dist - stoplimit_dist) self.takeprofit = self.quoteBar.High + stoploss_dist elif self.stoploss_ticket and orderEvent.OrderId == self.stoploss_ticket.OrderId: self.ResetOrders() self.loss_count += 1 self.stoploss_cumulative += 1