Risk Management
The risk management layer is the final gate before a signal is stored or alerted. It enforces hard limits on daily volume, AI acceptance, reward-to-risk, and stop distance — then suggests position size for manual review.
Risk management runs after AI scoring and before a signal is saved. It does not place trades or move capital — it decides whether a setup is within your configured bounds and attaches a sizing suggestion.
Approval Checks
Each check is evaluated in sequence. A signal must pass all four to receive approved status. Related settings live under Risk And Scheduling.
Daily Signal Cap
Limits how many signals can be approved in a single UTC calendar day. This prevents alert fatigue and caps exposure when many markets fire at once.
- The counter uses signals already approved today (status approved, created_at date in UTC).
- Rejected signals do not count toward the cap.
- When the cap is reached, every remaining signal in that scan is rejected with a daily-limit reason — even if it would otherwise pass.
- Controlled by MAX_DAILY_SIGNALS (default 100).
Example rejection reason: Daily signal limit reached: 100/100
AI Rejection
If the AI or rule engine rejects the setup, the risk mangement layer rejects the signal regardless of price levels.
- This runs after scoring — the risk manager does not re-score the signal, it enforces the AI decision.
- A signal can show a strong setup in the strategy reasons but still be rejected here if the scorer flagged conflicts or a low score.
- With an OpenAI key configured, the model decides pass or reject. Without one, the built-in rule engine applies the same threshold.
Example rejection reason: AI evaluation rejected the signal
Minimum Reward-to-Risk
Every signal must target at least as much profit as it risks. Signals below 1.0 R:R are rejected.
- R:R is set by the strategy from entry, stop loss, and take profit distances.
- Example: entry 100, stop 98, target 104 → reward 4, risk 2 → R:R 2.0 (passes).
- Example: entry 100, stop 95, target 102 → reward 2, risk 5 → R:R 0.4 (rejected).
- The minimum threshold is fixed at 1.0 — it is not configurable.
Example rejection reason: Risk/reward below minimum: 0.50 < 1.00
Stop Distance Limit
Rejects signals whose stop is too far from entry relative to your configured risk budget.
- Stop distance % = |entry − stop loss| ÷ entry.
- Maximum allowed = MAX_RISK_PER_TRADE × 5.
- With the default 2% risk per trade, stops wider than 10% of entry are rejected.
- This filters setups where the strategy placed a stop so wide that sizing would imply an outsized position or unrealistic risk profile.
Example rejection reason: Stop distance too wide: 12.00% > 10.00%
Approved vs Rejected
Both results are stored in the database and can appear in scan output and alerts. Rejected signals are not hidden — they include risk_reasons explaining which check failed.
- Approved — passed all checks; counts toward the daily cap; eligible for outcome tracking.
- Rejected — failed one or more checks; still saved with full AI evaluation and sizing; does not count toward the daily cap.
A signal can show AI pass in an alert but still be REJECTED if a risk check fails — for example, R:R below 1.0 or the daily cap already reached. Always read the Risk section at the bottom of an alert alongside the header status.
Position Sizing
Sizing answers one question: if you risk a fixed fraction of your account and the stop is hit, how large should the position be? The result is a suggestion only — adjust it to your own account, leverage, and risk rules.
Formula
risk amount = account equity × max risk per trade
stop distance = |entry − stop loss|
suggested qty = risk amount ÷ stop distance
suggested notional = suggested qty × entryWorked Example
With ACCOUNT_EQUITY=10000 and MAX_RISK_PER_TRADE=0.02, a long at entry 64250 and stop 63810.5:
risk amount = 10,000 × 0.02 = 200.00
stop distance = |64250 − 63810.5| = 439.5
suggested quantity = 200 ÷ 439.5 ≈ 0.455 units
suggested notional = 0.455 × 64250 ≈ 29,237.84If price reaches the stop, you lose roughly $200 — 2% of the configured equity. The notional can exceed equity because spot sizing is based on stop distance, not full collateral requirements.
position_size is omitted when account equity, risk percentage, entry, or stop distance are zero or invalid.
| Field | Description |
|---|---|
account_equity | Account size from ACCOUNT_EQUITY — the notional baseline for sizing math. |
risk_pct | Risk fraction from MAX_RISK_PER_TRADE (e.g. 0.02 = 2% of equity at risk if the stop is hit). |
risk_amount | Dollar amount at risk: account_equity × risk_pct. This is what you stand to lose if price reaches the stop. |
stop_distance | Absolute price gap between entry and stop loss in quote-currency terms. |
stop_pct | Stop distance as a fraction of entry — used by the stop-distance approval check. |
suggested_quantity | Base-asset units sized so a move to the stop loses risk_amount: risk_amount ÷ stop_distance. |
suggested_notional | Total position value in quote currency: suggested_quantity × entry. |
Signal Strength
strength on the final signal is set directly from the AI or rule-engine score (0–1). It reflects setup quality from the scorer, not a separate risk calculation. A high-strength signal can still be rejected if a hard risk limit fails.
