Simulating fills

Simulating order fills is a crucial part of any backtesting process. This is also a reasonably complex process - at least if the results are to be accurate.

As such, the AWTS data protocol APIs include a specific endpoint (SimFill()); to put the onus on fill simulation on the data module itself. This is for three main reasons:

  1. Performance. Simulating a fill usually means lots of extra data lookups, at the smallest resolution possible; the data modules already have this data and can scan through it quickly
  2. Accuracy. Data modules are broker/vendor/market specific already, and therefore are already aware (or as aware as it is possible to be) of spreads, fees, slippage, etc.
  3. Do It Once. Simulating fills is always important, so whether or not you choose to use the full execution engine you can still benefit from not having to reimplement this logic.

For example, the dataoanda data module provides data from Oanda, an FX/CFD broker. Oanda market data includes spreads, and the API reports down to S5 (five second) candles. Therefore the dataoanda module can accurately and rapidly determine whether and when a given order would fill.

Conversely, Polygon.io are a data vendor and do not act as a broker. The datapolygon module can rapidly simulate fills, but should be fed spread/slippage information with the request to improve accuracy.

How to do it

If you use the AWTS execution engine, this all happens automatically and you don't need to do anything yourself; the act of your strategy placing an order will result in a best effort simulated fill that the engine will take care of for you.

To use it manually, you can use the CLI tool or the AWTS APIs - see the examples below.

Note a positive quantity signifies a Buy, a negative quantity for a sell. Zero quantity is invalid.

The order type can be market, limit, stoploss or takeprofit. Other order types (e.g. multi-legged/complex orders, "market if touched" orders, OCO/bracketed orders, etc) are not supported yet, but will be added in a future iteration for modules where the upstream broker supports such functionality in actual trading.

::tip In practise, when using SimFill() you may not always wish to use the result; your strategy can can subsequently decide to just ignore it; e.g. to 'cancel' the order. The point of simulating in one call is to avoid having to make multiple re-checks to the data on every tick asking "have you filled yet?"; just do it once and keep hold of the result. ::

Examples

CLI

The AWTS CLI tool provides a simple command-line mechanism for testing fills, in a fashion that can be included in shell scripts or other automations. This is also the quickest/simplest way to explore the functionality.

Here is an example of simulating a fill on the instrument with symbol OANDA:NATGAS_USD (a Natural Gas CFD), for a limit order placed at 2023-06-14T17:13:03Z for 1 unit at a limit price of 2.15:

❯ awts data simfill OANDA:NATGAS_USD 2023-06-14T17:13:03Z limit 1 2.15
Symbol:  OANDA:NATGAS_USD
Filled
At 2023-12-13T06:51:12Z after 4357h38m9s
At price 2.153

The result showed that such an order would fill at 2023-12-13T06:51:12Z - i.e. after ~181 days! And it would fill at a price of 2.153.

APIs

For making SimFill() requests via the APIs please see the API documentation.

Limitations

Complex order rules (e.g. OCO, Market-if-touched, etc) and broker-specific feature extensions to order behavior are not currently supported.