RealTest User Guide
RealTest User Guide

 

 

Navigation: <Root level>

Backtest Engine Details

 

 

 

 

The RealTest Backtest Engine is written to support multi-strategy portfolio-level backtesting as effectively and efficiently as possible.

In most other software, portfolio-based backtesting is implemented by first generating all the entry and exit signals for each symbol for the entire date range, and then running a second pass that models the portfolio for each date using the generated signals.

In contrast to this, RealTest loops through the data by date first, then loops through each strategy, then finally each symbol for that strategy.

Use of this loop hierarchy models a daily trading process in the most realistic way.

 

Here is a simplified overview of what goes on "under the hood" when you run a test:

1.Apply the Settings (if present and applicable) to the Settings Panel (where they will persist until next changed)

2.Load the specified Data File if not already in memory

3.Determine the current Parameter values (the defaults for a single test or the next optimization values for multiple tests)

4.Adjust the test date range to match the data date range and/or the next optimization interval

5.Recalculate Data Section items (arrays) as needed

6.Loop through the dates in the test's date range and do the following:

a.initialize daily stats

b.do at-open exits then entries for each strategy (exits first to free capital for positions being entered)

c.do intraday entries then exits for each strategy (entries first to avoid assuming capital can be freed when intraday fill sequence is unknown)

d.do at-close exits then entries for each strategy (exits first to free capital for positions being entered)

e.update daily stats for each strategy

f.recalculate allocation for each strategy

 

The exits in steps b-d above are processed as follows:

1.Loop through all strategy positions and exit each if any of the following are true:

a.ExitRule evaluates to TRUE and ExitTime matches time of day (exit at open or close)

b.ExitLimit or ExitStop price was touched without ambiguity (exit at that price)

c.ExitLimit and/or ExitStop price were touched with ambiguity and Ambiguity setting permits exit anyway

d.this is the last bar of data or last date of the test (exit at close)

 

In the default "top-down" mode, the entries in steps b-d above are processed as follows:

 

1.For each strategy:

a.Loop through all stocks and evaluate EntrySetup, making a list of stocks for which it returns TRUE (setups)

b.Sort this list of setups by SetupScore and truncate the list at MaxSetups (if specified)

2.For each setup selection turn number (loop from 1 to the most setups in any strategy):

a.For each strategy in StrategyScore sequence (highest score first):

i.Loop doing the following steps:

1)select the next unprocessed setup for this strategy (ranked by SetupScore)

2)see if adding that setup would exceed any applicable Max... constraint for the strategy, any StatsGroups it belongs to, or Combined

3)if no constraints are exceeded then add this setup and update the strategy, group, and combined constraint values to account for this setup, else skip the setup

4)if MaxPerTurn setups have been added on this turn, break from the loop and yield to the next strategy

3.For each strategy (now that we have the complete setup list for all strategies with constraints accounted for):

a.Sort setups by EntryScore if provided (not necessary in this mode except in rare cases)

b.Evaluate  QtyFinal for each setup to optionally adjust the order quantity now that total setup counts are known

c.Evaluate EntrySkip if provided and skip the entry if true (ditto)

d.Enter the position if EntryLimit and/or EntryStop have been touched or were not specified

 

Key points about top-down mode:

position sizes for constraint-checking purposes are always based on OrderPrice, not on FillPrice (which can't be known yet at setup-processing time)

all constraints are applied to the setup list prior to processing any entries

setups for strategies that enter with limit or stop orders count towards all constraints whether or not they are filled

this model assumes that all orders are placed in advance of the market open each day with no realtime order management (e.g. live cancellation when a capacity is reached)

 

In legacy mode, the entries in steps b-d above are processed as follows:

For each Strategy in script order:

1.Loop through all stocks and evaluate EntrySetup, making a list of the stocks for which it returned TRUE (setups)

2.Sort this list of setups by SetupScore and truncate the list at MaxSetups (if specified)

3.Sort the setup list by EntryScore and loop through the sorted list, adding new positions when ALL of the following are true:

a.date matches strategy BarSize and time of day matches the strategy EntryTime

b.EntryLimit and/or EntryStop price have been touched or were not specified

c.there's not already a position in this stock for this strategy (unless MaxSameSym is greater than one)

d.MaxPositions or MaxInvested or MaxExposure or MaxEntries has not been reached

e.EntrySkip does not evaluate to TRUE

 

Key points about legacy mode:

all constraints other than MaxSetups are applied at entry time, not at setup selection time

constraints are applied based filled orders rather than setups

this model assumes that execution software would manage the constraints in live trading

 

 

 

 

Copyright © 2020-2024 Systematic Solutions, LLC