Hello, I am implementing intra-day trading algorithm and facing a slow backtest.

I wonder if you guys have a better idea than I currently have now.

The basic strategy is that we track all equities (no ETF), filter them based on cumulative intra-day dolllar volume for each one at 3pm, and buy 20 among them based on some algorithm that I have. 

Here are two ways that I came up with, which both are really slow on backtesting.

<First Way>

Universe Resolution: Hour (Minute would be idea, but it is too slow)

Basic idea: Within OnData, calculate dollar volume (volume * close) and add it to dictionary.

import pandas as pd

class MyAlgo(QCAlgorithm):
def Initialize(self):
# Set start date and end date
self.SetStartDate(2020, 1, 1)

# Set strategy cash
self.SetCash(10000)

# Set benchmark
self.benchmark = Symbol.Create('SPY', SecurityType.Equity, Market.USA)

# Parameters
self.dollar_volume_limit = 1000000
self.price_limit = 20

# Set requested data resolution
self.UniverseSettings.Resolution = Resolution.Hour
self.SetUniverseSelection(CoarseFundamentalUniverseSelectionModel(self.CoarseSelectionFunction))
self.AddEquity("SPY", Resolution.Minute)

# Exit position
self.Schedule.On(
self.DateRules.EveryDay("SPY"),
self.TimeRules.At(9, 30),
self.ExitPosition
)

# Enter position
self.Schedule.On(
self.DateRules.EveryDay("SPY"),
self.TimeRules.At(15, 00),
self.EnterPosition
)

self.my_universe = []
self.dollar_volume_by_symbol = {}

def CoarseSelectionFunction(self, coarse):
# Exclude ETF and Price filter
filtered = [c for c in coarse if c.HasFundamentalData and c.Volume > 0 and c.Price > 1 and c.Price < self.price_limit]
self.dollar_volume_by_symbol = {c: 0 for c in filtered}
self.my_universe = filtered

return self.my_universe

def OnData(self, data):
for symbol in self.dollar_volume_by_symbol.keys():
if symbol in data.Bars:
value = data.Bars[symbol]
self.dollar_volume_by_symbol[symbol] += (value.Volume * value.Price)

def EnterPosition(self):
# dollar volume threshold
temp = []
for s in self.my_universe:
if s in self.dollar_volume_by_symbol.keys():
if self.dollar_volume_by_symbol[s] > self.dollar_volume_limit:
temp.append(s)
self.dollar_volume_by_symbol.clear()
self.my_universe = temp

########################
# Buy some number of stocks from filtered self.my_universe
########################


def ExitPosition(self):
self.Liquidate()

<Second Way>

Within EnterPosition function, use History for every my_universe equities, and use dataframe to calculate dollar volume.

----------------------------------------------- Code is similar to the First one-------------------------------------------

First way is a bit faster on backtest than the second one, but they are both extremely slow.

Is there a way to increase backtest speed for such strategies that require intra-day cumulative data to order, but you can't filter out many securities within universe selection?

 

Thanks!

Author