Files
mt-data-mcp/docs/TRADING_RISK.md
T

183 lines
9.7 KiB
Markdown
Raw Normal View History

2026-07-13 17:15:01 -05:00
# Trading risk analytics
2026-06-12 22:17:00 -05:00
2026-07-13 17:15:01 -05:00
**Read-only** tools for sizing, tail risk, and stress tests. They inspect the account and open positions — they **never** place, modify, or close orders. Pair them with [TRADING_SAFETY.md](TRADING_SAFETY.md) when you move from analysis to execution.
2026-06-12 22:17:00 -05:00
| Tool | Answers |
|------|---------|
2026-07-13 17:15:01 -05:00
| `trade_risk_analyze` | “How big can this trade be?” and “How much am I risking right now?” |
| `trade_var_cvar_calculate` | “What is my statistical worst-case loss over one bar?” |
| `trade_stress_test` | “What happens to open positions under these price shocks?” |
2026-06-12 22:17:00 -05:00
2026-07-13 17:15:01 -05:00
**Dense terms:** [Fixed-fraction sizing](GLOSSARY.md#fixed-fraction-sizing) · [Kelly](GLOSSARY.md#kelly-criterion) · [VaR](GLOSSARY.md#var-value-at-risk) · [CVaR / ES](GLOSSARY.md#cvar-conditional-var--expected-shortfall) · [Drawdown](GLOSSARY.md#drawdown)
**Related:** [Sample trade](SAMPLE-TRADE.md) · [Advanced playbook](SAMPLE-TRADE-ADVANCED.md) · [Guardrails](ENV_VARS.md#trade-guardrails) · [Barriers](BARRIER_FUNCTIONS.md)
2026-06-12 22:17:00 -05:00
---
## `trade_risk_analyze`
Analyzes current open/pending risk and, when given a proposed entry and stop, sizes a
new trade. Supports two sizing methods: fixed-fraction and Kelly.
```bash
# Current portfolio risk only
mtdata-cli trade_risk_analyze --json
# Size a new long: risk-based volume from entry + stop
2026-08-01 17:11:00 -05:00
mtdata-cli trade_risk_analyze EURUSD --direction long \
--entry 1.0850 --stop-loss 1.0800 --sizing '{"method":"fixed_fraction","risk_pct":1.0}' --json
2026-06-12 22:17:00 -05:00
```
| Parameter | Default | Description |
|-----------|---------|-------------|
| `symbol` | — | Symbol for new-trade sizing; omit for portfolio-only risk. |
| `sizing` | — | JSON object selecting `fixed_fraction` with `risk_pct`, or `kelly` with its edge inputs and cap. |
| `strict_risk` | `true` | Return `suggested_volume=0.0` if the broker minimum lot would exceed the requested sizing risk. |
2026-06-12 22:17:00 -05:00
| `include_pending` | `true` | Include contingent stop-loss risk from pending orders in portfolio totals. |
| `direction` | — | `long`/`short` (aliases accepted) for the proposed trade. |
| `entry` | — | Proposed entry price. With `symbol`+`stop_loss` but no entry, it is resolved from the latest tick (ask for long, bid for short, mid otherwise). A closed/stale quote is labeled `last_available_tick_*` and `sizing_reference_only`; refresh it before submission. |
2026-06-12 22:17:00 -05:00
| `stop_loss` | — | Proposed stop (alias `sl`). Required to compute risk-based volume. |
| `take_profit` | — | Optional target (alias `tp`) for reward/risk context. |
New-trade sizing uses an incremental candidate-risk policy: `sizing.risk_pct`
limits the proposed trade's stop risk as a percentage of account equity, and
account-wide margin stress remains a hard safety gate. Existing positions on other
symbols do not prevent sizing, but the returned `sizing_risk_policy` states that the
suggestion is not an aggregate portfolio stop-risk cap.
2026-08-06 18:13:27 -05:00
Candidate validation is independent of portfolio observation. A valid proposed
trade returns `candidate_valid: true`. If its direction, stop, or target is
invalid, the response retains the account and portfolio snapshot but returns
`success: false`, `candidate_valid: false`, a structured `error_code`, and
`portfolio_snapshot_status: available`; CLI callers receive a nonzero exit status.
2026-06-12 22:17:00 -05:00
### Kelly sizing
Set `sizing.method=kelly` and supply edge statistics in the same JSON object:
2026-06-12 22:17:00 -05:00
```bash
2026-08-01 17:11:00 -05:00
mtdata-cli trade_risk_analyze EURUSD --direction long \
--entry 1.0850 --stop-loss 1.0800 \
--sizing '{"method":"kelly","win_rate":0.55,"avg_win":0.012,"avg_loss":0.010,"fraction_multiplier":0.5,"max_risk_pct":2.0}' --json
2026-06-12 22:17:00 -05:00
```
| Parameter | Default | Description |
|-----------|---------|-------------|
| `sizing.win_rate` | — | Win probability as a fraction in `[0, 1]`. |
| `sizing.avg_win` | — | Average winning return normalized to a consistent stake or unit of risk (for example, an R-multiple). |
| `sizing.avg_loss` | — | Average losing return magnitude on the same normalized basis. |
| `sizing.fraction_multiplier` | `0.5` | Multiplier on the raw Kelly fraction (half-Kelly = `0.5`). |
| `sizing.max_risk_pct` | `2.0` | Hard cap on account risk (%) for Kelly sizing. |
2026-06-12 22:17:00 -05:00
The Kelly fraction is `win_rate − (1 − win_rate) / (avg_win / |avg_loss|)`, then scaled
by `sizing.fraction_multiplier` and capped by `sizing.max_risk_pct`. On a non-positive edge the tool reports
2026-06-12 22:17:00 -05:00
`status="kelly_no_edge"` and a suggested volume of `0.0`.
`trade_journal_analyze` reports `avg_win` and `avg_loss` in account currency. Those
raw PnL averages are not Kelly inputs because deal sizes and capital at risk can vary.
Normalize each historical outcome to a consistent stake or initial risk before
computing the average return metrics supplied here.
Portfolio stop risk is the gross sum of each ticket's remaining loss from its
current MT5 mark to its stop. This measures equity at risk now; it does not reuse
the original entry-to-stop loss after unrealized P&L has changed. It is a
conservative path-risk measure, not a same-symbol net-exposure estimate; a path
can trigger both sides of a hedge sequentially. Pending-order stop risk is
reported separately as contingent and is included in the total only when
`include_pending=true`.
`notional_value` and portfolio notional fields are linearized account-currency
exposures derived from the broker's tick value and tick size. The per-position
`contract_price_product` diagnostic preserves raw `volume × contract_size × price`
with the explicit unit `contract_size_times_price`; it must not be compared with
account equity or summed across unlike instruments.
2026-06-12 22:17:00 -05:00
---
## `trade_var_cvar_calculate`
Estimates one-bar Value at Risk (VaR) and Conditional VaR (CVaR, a.k.a. Expected
Shortfall) for the current open positions — either the whole portfolio or a single
symbol.
```bash
# Portfolio VaR/CVaR at 95% over one H1 bar
mtdata-cli trade_var_cvar_calculate --timeframe H1 --lookback 500 --confidence 0.95 --json
2026-06-12 22:17:00 -05:00
# Symbol-scoped, parametric/Gaussian, percentage returns
mtdata-cli trade_var_cvar_calculate EURUSD --method parametric \
2026-06-12 22:17:00 -05:00
--transform pct --lookback 300 --json
```
| Parameter | Default | Description |
|-----------|---------|-------------|
| `symbol` | — | Restrict to one symbol's exposure; omit for the full portfolio. |
| `timeframe` | `H1` | Return interval and the one-bar holding period. |
| `lookback` | `500` | Historical bars used to build the return distribution. |
| `confidence` | `0.95` | Confidence fraction (`0.95`, `0.99`); must satisfy `0 < confidence < 1`. |
| `method` | `historical` | `historical` (empirical tail) or `parametric` (Gaussian model). |
2026-06-12 22:17:00 -05:00
| `transform` | `log_return` | Return transform: `log_return` or `pct`. |
| `min_observations` | `50` | Minimum aligned observations before estimating risk. |
**Output** includes `var` and `cvar`, position/exposure counts, and — by detail level —
per-position and per-symbol exposure breakdowns. With no open positions, `--detail full`
returns the legacy zero-filled arrays.
2026-07-11 21:12:58 -05:00
VaR/CVaR converts percentage price shocks to account-currency P&L with each
symbol's broker-provided tick value and tick size (`pnl_model` is
`tick_value_linear_sensitivity`). Positions without usable tick economics are rejected
rather than mixed into a portfolio in incompatible quote-currency units. The model is
linearized and does not include gaps, spread changes, swaps, or nonlinear payoff effects.
2026-08-06 20:39:50 -05:00
Every open position must have usable account-currency valuation and every
included symbol must have usable history. The tool returns
`portfolio_var_incomplete` instead of silently calculating a smaller portfolio
2026-08-06 20:39:50 -05:00
when any position lacks valuation inputs or any symbol history is unavailable.
2026-07-11 21:12:58 -05:00
2026-06-12 22:17:00 -05:00
---
## `trade_stress_test`
Applies deterministic percentage price shocks to open positions and reports the P&L
impact. Useful for "what if EURUSD drops 2% and everything else 3%?" scenarios.
```bash
# Per-symbol shocks
mtdata-cli trade_stress_test '{"EURUSD":-2.0,"GBPUSD":-1.5}' --json
# Wildcard shock applied to every position without an explicit entry
mtdata-cli trade_stress_test '{"*":-3.0}' --detail full --json
```
| Parameter | Default | Description |
|-----------|---------|-------------|
| `shocks` | (required) | Per-symbol percentage shocks, e.g. `{"EURUSD": -2.0}`. Use `"*"` as a fallback for symbols without an explicit entry. |
| `include_unshocked` | `false` | Include positions that received no shock (no exact match and no `"*"` fallback). |
| `detail` | `compact` | `full` adds per-position diagnostics. |
**Output** is a list of `items` (one per evaluated position) with `ticket`, `symbol`,
`side`, `volume`, `shock_pct`, `current_price`, `shocked_price`, and `pnl_impact`, plus
totals: `total_pnl_impact`, `positions_total`/`evaluated`/`shocked`, and — when account
metadata is available — `equity_before`/`equity_after`/`impact_pct`.
---
## Caveats
- All three tools read live MT5 state; results change as positions and quotes move.
- A `None` position/order response from MT5 is a failed snapshot, not an empty
book. Snapshot-dependent analytics return a `*_snapshot_unavailable` error;
empty tuples/lists remain valid empty books.
2026-06-12 22:17:00 -05:00
- VaR/CVaR assume the recent return distribution persists and use a single-bar holding
period; they are not a guarantee of maximum loss.
- Stress shocks are deterministic and linear in price; they do not model spread
widening, gaps, swaps, or correlation breaks.
- Kelly sizing is only as good as its inputs — estimate `win_rate` and normalized
average win/loss returns from a sufficient out-of-sample track record.
2026-06-12 22:17:00 -05:00
2026-07-13 17:15:01 -05:00
## See also
2026-06-12 22:17:00 -05:00
- [BARRIER_FUNCTIONS.md](BARRIER_FUNCTIONS.md) — TP/SL hit probabilities
2026-07-13 17:15:01 -05:00
- [TRADING_SAFETY.md](TRADING_SAFETY.md) — Execution preview and guardrails
- [GLOSSARY.md](GLOSSARY.md) — VaR, CVaR, Kelly
- [SAMPLE-TRADE-ADVANCED.md](SAMPLE-TRADE-ADVANCED.md) — Risk gates in a full workflow