You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: wire JSON risk namespace through to Config (close PR #148 gap) (#149)
The previous JSON config layer (#148) flattened ``{"risk": {...}}`` into
flat keys correctly, but those values only flowed into ``strategy_config``
— the strategy-level merged dict — not into the ``Config`` class that
``RiskManager`` actually reads from. Operators putting
``"daily_loss_limit": 200`` in their JSON would see no effect on the
risk guardrails.
This change closes that gap:
* Promote ``_RISK_PARAMS`` from ``main()`` to module level so the JSON
helper and the CLI override loop share the list.
* Add ``_apply_json_risk_overrides(json_overrides, args)``: for each
risk param present in JSON and *not* already supplied via CLI args,
write the value to ``Config.{KEY.upper()}``. Pop the key from
``json_overrides`` so it does not leak into ``strategy_config``
(which the strategy would not know what to do with) or trigger the
typo detector.
* Call the helper right after ``load_json_configs`` and before the
existing CLI risk loop. CLI > JSON precedence is preserved because
the CLI loop runs last and unconditionally writes ``args.{param}``
when present.
* ``known_market_making_keys()`` now includes ``_RISK_PARAMS`` so the
JSON loader's typo detector treats risk keys as known when they
appear at flat-top-level (e.g., a user mixing flat + nested forms).
* README clarifies that the ``risk`` namespace targets ``Config``,
not ``strategy_config``, and that CLI flags still beat JSON.
5 new test cases pin the behaviour: JSON sets Config when CLI is
unset; CLI beats JSON; multiple risk params apply together; empty /
None inputs are no-ops; unknown risk-shaped keys pass through
untouched. Tests snapshot and restore the relevant ``Config`` class
attributes so they stay isolated from each other and from the wider
suite.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -336,6 +336,8 @@ becomes:
336
336
337
337
Unknown keys produce a warning (typo detection) but are still passed through to the validator, which decides whether to abort. Missing files are warned and skipped (so a typo in `--config /missing.json` does not block startup); malformed JSON aborts with exit code 2. See `examples/config.example.json` for a full template.
338
338
339
+
The `risk` namespace flows to the bot's `Config` class (the same path the existing `--max-position-pct` / `--daily-loss-limit` / etc. CLI flags target), not to `strategy_config`. CLI flags still beat JSON for any individual risk parameter, so an operator can leave defaults in JSON and override per-run from the command line.
340
+
339
341
The `market_making` strategy uses **progressive close pricing**: as a position ages, the take-profit price is tightened from full spread → breakeven (at 50% of max age) → small loss (at 75%), reducing costly taker force-closes. The loss tolerance is configurable via `--aggressive-loss-bps` (default: 1 bps). During the force-close phase, `--force-close-max-loss-bps` enables progressive loss acceptance that scales from `aggressive-loss-bps` to the configured maximum as the position approaches the taker deadline. **Unrealized loss early close** (`--unrealized-loss-close-bps`): When a position's unrealized loss exceeds this threshold (in bps), it is immediately closed via taker order regardless of position age. This caps large adverse moves before the age-based close triggers. Default: 0 (disabled).
340
342
341
343
**BBO mode** (`--bbo-mode`): Places orders at the best bid/ask instead of `mid ± spread_bps`. On Hyperliquid, market spreads are typically 0.1–2 bps, so even `SPREAD_BPS=5` places orders 4–5 bps away from BBO, resulting in low fill rates. BBO mode improves fill rates by tracking the current best prices. Use `--bbo-offset-bps N` to place orders N bps behind BBO (default: 0 = at BBO). Falls back to `mid ± spread_bps` when BBO is unavailable.
0 commit comments