user@elrise.io:~/market-data-emulator-in-trading-bots
· 5 min

Synthetic market in the trading bots workflow

A trading bot runs in a workflow where synthetic data comes first, real market data comes second. Not instead, but for different phases.

My trading bots run in a workflow where synthetic data comes first, real market data comes second. Not "either/or", but in that exact order. Earlier I did it the other way: backtest on history, deploy, catch edge cases in production. Then I realised that half of those edge cases are not "something that will happen on the market" but "something my algorithm misinterprets". The second category cannot be caught on real data — there is no repeatability there. Synthetic data closes exactly that gap.

market-data-emulator (project page) takes on three tasks that real market data cannot cover.

Market regimes

Real market data gives me one current regime — whatever it happens to be. I cannot test how my risk engine behaves in a liquidation cascade if there is no cascade on the market right now. I cannot check how my orderbook strategy handles a flash crash if no flash crash has happened in the last six months. The emulator generates the regime I need on demand: meta.regimes_summary returns {"trend_up": 5, "range": 235} for 240 bars, and I know the trend indicator should fire only on the trend phase and stay silent on the range. This is not "realistic data", it is a controlled environment. I pick the parameters, fix the seed, verify the behaviour.

Analyzer nodes

In the program's pipeline, separate blocks — change_point_detector, regime_hmm, spring_detector, wyckoff_detector. Each one needs isolated testing: what it catches, what it misses, what it catches falsely. On real market data, that is a composition of test snapshots from real days, and for each test case I have to find a day that fits. On synthetic data, that is a scenario with a known oracle. change_point_injection itself says "level shift @ bar 100, mean +5σ", and my detector must catch it. In wyckoff_spring there is an oracle spring, and my detector must not miss it. The test is written once, the oracle lives in the scenario registry.

Local models

When I train an ML filter on a specific pattern (e.g. distinguishing dead_cat_bounce from a trend continuation), I need a dataset with many examples of that pattern in different variations. On real market data — 3-5 cases per year, each in a unique context, leaf-level labels are set manually. On synthetic data — 50 examples of each pattern with different drift parameters, different σ, different regimes. The model learns the structure, not specific historical coincidences. This is not "fake data for training", it is dataset augmentation with a controlled label.

The boundary

Synthetic data does not replace real market data. A bot that has only passed synthetic tests is not ready for deployment — it has not seen a live orderbook, microstructure, dislocations. Synthetic data covers the phase where real market data is either excessive (I know what I want to test) or harmful (training on every real example is overfitting on history). Real market data covers the phase where I need a plausible picture without the ability to control variables.

So the order is: synthetic data → unit tests on nodes and the risk engine → backtest on real market data → paper trading → production. The emulator is not a replacement for real market data. It is the tool for the phase where real market data either does not catch the issue or does not teach the model.

Where the emulator is not a substitute

If you want more on the project — see the project page at /projects/market-data-emulator/ or the repository at github.com/elriseio/market-data-emulator.