Skip to content

Execution Modeling

The difference between a profitable backtest and a profitable live strategy often comes down to execution. In the real world, you do not get magically filled at the exact price you want, for the exact quantity you want, at the exact moment you want. Prices slip, volume is limited, and fills can be partial.

Stratifyre’s execution modeling is designed to simulate these realities so your backtest results are as close to live trading as possible. This page explains every aspect of how the engine handles order fills.

Consider a simple example: your strategy generates a buy signal on a stock trading at $100. In a naive backtest, you would get filled at exactly $100. But in real life:

  • The price might move to $100.05 by the time your order reaches the exchange (slippage).
  • If you are buying 10,000 shares and only 2,000 traded in that bar, you cannot realistically fill the entire order.
  • If it is an illiquid small-cap stock, your order itself might move the price.

These effects are small on any single trade but compound across hundreds of trades. A strategy that looks great with perfect fills might be marginal — or outright unprofitable — with realistic execution.

Stratifyre lets you control exactly how strict or lenient the execution simulation is, so you can test under a range of assumptions.

The execution mode determines when your strategy’s rules are evaluated and when orders are eligible for filling. This is a fundamental setting that affects every aspect of how your backtest behaves.

In On-Open mode, the engine only evaluates your strategy’s rules after a bar has completely formed. Your strategy sees the final open, high, low, close, and volume for each bar — never partial data.

When your rules generate an order, the fill occurs at the open of the next bar.

Timeline:

  1. Bar N completes (OHLCV is final).
  2. The engine evaluates your rules using Bar N’s complete data.
  3. If rules trigger, an order is placed.
  4. The order is filled at the open of Bar N+1.

Advantages:

  • No risk of look-ahead bias within a bar — your strategy only sees data that is definitively in the past.
  • Simpler to reason about — you always know exactly what data your strategy had available.
  • Fills at the open are a realistic assumption for many strategies (especially daily bar strategies).

Best for: Most strategies, especially those on daily or longer timeframes. This is the recommended default.

In On-Close mode, the engine evaluates your strategy’s rules while the current bar is still forming. Your strategy sees the bar’s open and the price action up to the current point — essentially partial bar data.

When your rules generate an order, the fill occurs on the next incoming tick (or effectively at the close, depending on order type).

Timeline:

  1. Bar N begins forming.
  2. As price updates within the bar, the engine evaluates your rules.
  3. If rules trigger, an order is placed.
  4. The order is filled on the next tick within or after the bar.

Advantages:

  • Allows your strategy to react to intrabar price movements.
  • Supports strategies that use stop orders or limit orders that should trigger within a bar.
  • More realistic for intraday strategies where you would be watching price action in real time.

Best for: Intraday strategies and strategies that use intrabar stop or limit orders.

When a market order is placed, a single price bar contains a range of prices: open, high, low, and close. The fill simulation mode determines which price within that range your order receives.

Your order is filled at the worst price in the bar for your order direction:

  • Buy orders are filled at the bar’s high — the most expensive price you could have paid.
  • Sell orders are filled at the bar’s low — the cheapest price you could have received.

When to use it: This is the stress-test mode. If your strategy is still profitable under pessimistic fills, you can have high confidence that real-world execution will not destroy the edge.

Your order is filled at the best price in the bar for your order direction:

  • Buy orders are filled at the bar’s low — the cheapest price available.
  • Sell orders are filled at the bar’s high — the best price available.

When to use it: To understand the best-case scenario. Useful for bounding the range of possible outcomes when compared against pessimistic results. If a strategy is unprofitable even with optimistic fills, it has no viable edge.

Your order is filled at the bar’s closing price, regardless of direction.

When to use it: This is the most commonly used fill mode in other backtesting platforms, so it is useful for comparison. It is a reasonable middle ground for daily-bar strategies where you might place orders at or near the close.

Your order is filled at the average of the open, high, low, and close — the OHLC midpoint.

When to use it: A balanced estimate that accounts for the full range of prices within the bar. Many practitioners consider this a more realistic default than close fills, since real-world fills could happen at any point in the bar.

Running the same strategy across all four fill modes gives you a sense of how sensitive your results are to execution quality:

Scenario Implication
Profitable across all four modes Strong edge that survives execution uncertainty
Profitable on optimistic and close, unprofitable on pessimistic Edge exists but is sensitive to fill quality — proceed with caution
Only profitable on optimistic No reliable edge — fill quality is masking the problem
Unprofitable across all modes Strategy does not work regardless of fill assumptions

Slippage is the difference between the intended price and the actual fill price. It occurs because:

  • Prices move between when you decide to trade and when your order is executed (latency).
  • The bid-ask spread means you pay more to buy and receive less to sell.
  • Large orders consume available liquidity at the best price and fill at progressively worse levels (market impact).

Stratifyre supports two slippage models:

Per-share (or per-contract) amount: A fixed dollar amount added to buy fills and subtracted from sell fills. For example, $0.01 per share means a buy order intended at $50.00 fills at $50.01.

Best for equities and other instruments with relatively stable per-unit costs.

Percentage of price: A percentage of the order price. For example, 0.05% slippage on a $50.00 order adds $0.025 to a buy fill.

Best for futures, forex, and crypto where notional values vary widely and a fixed per-unit amount would be inappropriate.

The right slippage setting depends on what you are trading:

Market Typical Slippage
Large-cap US equities (AAPL, MSFT) $0.01 per share or 0.01-0.02%
Mid-cap equities $0.02-0.05 per share or 0.03-0.05%
Small-cap / illiquid stocks $0.05-0.20 per share or 0.1-0.5%
E-mini futures (ES, NQ) 1 tick ($12.50 for ES)
Crypto (BTC, ETH on major exchanges) 0.02-0.10%
Forex (major pairs) 0.5-2 pips

In real markets, you cannot buy or sell more than the available volume without severely impacting the price. Stratifyre enforces volume constraints to prevent unrealistic fills.

By default, the engine will not fill your order for more than 10% of the bar’s total volume. This means if a bar had 100,000 shares traded, your order can fill at most 10,000 shares.

You can adjust this percentage in the backtest settings. Lower percentages are more conservative (more realistic for large accounts). Higher percentages are more lenient.

Volume constraints have a dramatic effect on strategies that:

  • Trade illiquid instruments (small-cap stocks, exotic futures).
  • Use large position sizes relative to market volume.
  • Trade at low-volume times (overnight, pre-market).

Without volume constraints, a backtest might happily fill a 50,000-share order on a stock that only trades 20,000 shares per day. That is not a realistic scenario.

When volume constraints prevent a full fill, the engine processes a partial fill — executing only the portion of the order that fits within the volume limit. The remainder may fill on subsequent bars (depending on your order type and duration) or be cancelled.

Partial fills affect:

  • Position sizing — You may end up with a smaller position than intended.
  • Average fill price — If the order fills across multiple bars, each partial fill may be at a different price.
  • Strategy logic — Your exit rules apply to the actual position size, not the intended size.

For strategies that use leverage (futures, margin accounts), the engine validates that you have sufficient margin to support your positions. If a trade would exceed your available margin, the order is rejected.

This prevents backtests from taking on unrealistic amounts of leverage. In live trading, a margin call would force liquidation — the engine models this constraint.

While fill simulation modes apply primarily to market orders, Stratifyre also handles limit and stop orders with realistic logic:

  • Limit orders are filled only when the bar’s price range includes your limit price. The fill price is at your limit price or better.
  • Stop orders are triggered when the bar’s price range crosses your stop level. The fill price accounts for slippage beyond the stop.
  • Stop-limit orders combine both behaviors — triggered at the stop level, filled at the limit or better.
  • OCO (One-Cancels-Other) orders — when one side fills, the other is automatically cancelled.

Bracket Orders: When Both Legs Trigger on the Same Bar

Section titled “Bracket Orders: When Both Legs Trigger on the Same Bar”

A common challenge in bar-based backtesting is what happens when a single bar’s price range is wide enough to cover both the take-profit and the stop-loss of a bracket order. For example, if you enter long at $100 with a take-profit at $103 and a stop-loss at $97, and the next bar has a low of $95 and a high of $105, both exit orders could theoretically have triggered.

In reality, only one can fill. But with bar data alone, there is no way to know which price was hit first — the bar only tells you the range, not the sequence of ticks within it.

How Stratifyre handles this: The engine uses a deterministic priority based on order type. Stop orders (execution rank 1) are always processed before limit orders (execution rank 3). Since the stop-loss is a stop order and the take-profit is a limit order, the stop-loss always fills first when both legs trigger on the same bar. The take-profit is then automatically cancelled as the OCO sibling.

This is a pessimistic assumption — the engine assumes the worst-case exit happened first. This applies symmetrically to both long and short positions:

Position Take-Profit Stop-Loss Same-bar winner
Long (buy entry) Limit sell (rank 3) Stop sell (rank 1) Stop-loss fills first
Short (sell entry) Limit buy (rank 3) Stop buy (rank 1) Stop-loss fills first

This behavior is intentional and conservative. A backtest that assumes the favorable exit happened first would overstate performance in exactly the scenarios where your strategy is most vulnerable — wide-range bars during volatile conditions.

Using Smaller Time Resolutions for Better Accuracy

Section titled “Using Smaller Time Resolutions for Better Accuracy”

If you find that both bracket legs frequently trigger on the same bar, that is a signal that your time resolution is too coarse for your strategy’s price targets. When bars are large relative to your take-profit and stop-loss distances, the engine cannot distinguish which was hit first, and the pessimistic assumption kicks in more often.

The solution is to run your backtest at a finer time resolution:

Current resolution Consider switching to When
Daily 60-minute or 15-minute TP/SL within 3-5% of entry on volatile instruments
60-minute 5-minute or 1-minute TP/SL within 1-2% of entry
5-minute 1-minute or 1-second Tight TP/SL on fast-moving instruments
1-minute Tick (TBBO) Scalping strategies with very tight brackets

With finer bars, the bar ranges become narrower and it becomes far less likely that both your take-profit and stop-loss fall within a single bar. When they do not overlap, the engine fills whichever leg is actually reached — giving you a more accurate picture of your strategy’s real-world behavior.

For instruments that trade in extended hours (pre-market and after-hours for US equities), the engine can include this data if your strategy and data settings support it. Extended hours typically have lower volume and wider spreads, so slippage and volume constraints are particularly important during these sessions.

The most reliable backtests use a combination of these settings:

  1. On-Open execution mode to avoid intrabar look-ahead bias.
  2. Pessimistic or Average fill mode for realistic fill pricing.
  3. Moderate slippage appropriate to your instrument.
  4. Volume constraints at 10% or lower for realistic position fills.
  5. Margin validation enabled for leveraged strategies.

Then, as an additional check, run the same backtest with Optimistic fills and zero slippage to see the absolute best case, and Pessimistic fills with high slippage to see the worst case. If the strategy is profitable across the full range, you have strong evidence of a real edge.

For detailed guidance on interpreting these results, see Understanding Results and Performance Metrics.