Skip to main content

What BacktestConstraintsSpec Controls

Real exchanges enforce multiple layers of execution constraints: order size minimums, margin requirements, liquidation thresholds, and funding rate settlements. In a backtest, you may want to selectively enable or disable these layers depending on the stage of your research. BacktestConstraintsSpec gives you fine-grained control over five constraint toggles: When no BacktestConstraintsSpec is provided to TradingExecutionSpec, all constraints are active (equivalent to the realistic() preset).

Three Presets

Rather than configuring each toggle individually, use the class method presets for common scenarios:

research()

Disables every constraint. Pair with zero-cost CostModelSpec for a completely frictionless backtest:

cost_only()

Keeps funding enabled (a real cost for perpetual futures) but disables order validation, margin checks, and liquidation. Useful for isolating the P&L impact of fees and funding without orders being rejected:

realistic()

All constraints active. This is the default behavior and matches what happens in live trading:

Individual Toggles

You can mix and match any combination of toggles by passing them directly to the constructor.

Scenario 1: Funding Analysis Without Liquidation Risk

Test how funding rates erode returns on a carry trade, without positions being liquidated during drawdowns:

Scenario 2: Order Validation Only

Check how many of your orders would be rejected by exchange minimums, without margin or liquidation interference:

Scenario 3: High Leverage Stress Test

Override exchange max leverage to test how a strategy behaves under extreme leverage:

Scenario 4: Margin-Aware Without Liquidation

Validate that your strategy stays within margin limits, but do not force-close positions. Useful for understanding how close you get to liquidation without actually triggering it:

Scenario 5: Conservative Leverage Cap

Run a realistic backtest but cap leverage below the exchange maximum to match your risk policy:

Scenario 6: Frictionless With Funding

Like research() but with funding enabled. Useful when your signal is funding-rate-dependent (e.g., carry or basis trades) and you need funding P&L in your signal but not other constraints:

Scenario 7: Full Realistic With Reduced Leverage

The most common production configuration. All constraints active, but leverage capped to a conservative level:
Progress through three stages when developing a strategy:
Stage 1 — Signal Validation. Use research() with zero-cost CostModelSpec to isolate pure signal quality. If the strategy does not show alpha here, no amount of execution tuning will save it.
Stage 2 — Cost Impact. Switch to cost_only() and remove the zero-cost override. This reveals how much of your alpha is consumed by fees and funding.
Stage 3 — Production Readiness. Use realistic() (or omit constraints entirely, since it is the default). This is the final validation before going live.
If your strategy shows strong returns in Stage 1 but collapses in Stage 2, it is likely cost-dominated. Reduce trade frequency or improve signal quality before proceeding to Stage 3.

Integration with TradingExecutionSpec

BacktestConstraintsSpec is passed to TradingExecutionSpec via the constraints field:
When constraints is None (the default), all constraints are active — this preserves backward compatibility with existing specs that do not use BacktestConstraintsSpec. The constraints field is only meaningful in backtest mode. In live mode, real exchange rules always apply regardless of this setting.

Cost Models

CostModelSpec, VenueFeeResolver, and slippage modeling

Liquidation Logic

Exchange-specific margin calculations and liquidation simulation

Funding Rates

8-hour funding settlement and its impact on perpetual futures P&L

Backtesting Accuracy

The five layers of accuracy that make ClyptQ backtests realistic