Risk management in Backtest Kit operates at the portfolio level — validation runs across all active strategies and symbols before any signal is accepted into the lifecycle. Rather than embedding risk rules inside individual strategies (where they can be forgotten, duplicated, or inconsistently applied), the framework provides a dedicated risk schema layer that intercepts every pending signal before position entry. Rejection is logged automatically, strategies continue without crashing, and rejection statistics are available for analysis.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-docs/llms.txt
Use this file to discover all available pages before exploring further.
Define a Risk Profile
A risk profile is a named collection of validation functions registered withaddRiskSchema. Each validation receives the pending signal alongside current market state and throws an error to reject the signal.
Attach a Risk Profile to a Strategy
TheriskName field on addStrategySchema connects the strategy to a registered risk profile. Every signal produced by this strategy must pass all validations in the named profile before being accepted.
What Each Validation Receives
Each validation function is called with a context object containing everything needed to evaluate the pending signal against portfolio state:| Field | Type | Description |
|---|---|---|
pendingSignal | ISignalRow | The proposed signal: entry price, TP, SL, direction, estimated time |
currentPrice | number | VWAP at the time of validation (last 5 one-minute candles) |
symbol | string | The trading pair the signal was generated for |
backtest | boolean | Whether validation is running inside a backtest |
priceOpen in pendingSignal may be undefined if the strategy did not specify a limit entry, in which case currentPrice is the correct fallback (as shown in the examples above).
Common Validation Patterns
Minimum R/R Ratio
Reject any signal where the potential reward does not justify the risk taken. A 2:1 minimum is a common baseline for trend-following strategies.
Maximum Position Count
Cap the number of simultaneously open positions to limit portfolio drawdown during adverse market conditions.
Time-of-Day Restrictions
Avoid entering trades during low-liquidity hours, news events, or exchange maintenance windows by checking the
when timestamp from the execution context.Volatility Filters
Gate entries on ATR or candle-range metrics to avoid entering during choppy, low-momentum conditions where TP and SL levels are likely to be hit randomly.
Risk Rejection Handling
When a validation throws, the signal is rejected and the strategy continues running normally. No exception propagates to user code. The rejection is:- Logged with the validation error message and the signal parameters
- Counted in the per-strategy rejection statistics
- Emitted to any
listenRisksubscribers for real-time monitoring or alerting
Monitoring Rejections with listenRisk
Subscribe to the listenRisk event emitter to receive a callback every time a signal is rejected by risk validation. This is useful for building dashboards, sending alerts, or logging rejection reasons to an external system.
rejectionNote field contains a human-readable explanation of why the trade was rejected. The currentSignal field carries the full pending signal that was blocked, making it straightforward to log signal parameters alongside the rejection reason.
Risk validation uses atomic check-and-reserve semantics in parallel multi-symbol execution. When multiple symbols are backtested concurrently and a validation checks a shared resource like total open position count, the framework serializes the check-and-commit operation. This prevents race conditions where two parallel backtests each read
count = 2, both pass a max 3 check, and both open a position — leaving the portfolio with 4 open trades instead of the allowed 3.