Skip to content

Commit 6d5fc05

Browse files
committed
Validate all MM numeric settings up front
1 parent b9a07c8 commit 6d5fc05

2 files changed

Lines changed: 31 additions & 6 deletions

File tree

examples/write/market_maker_bot.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -530,10 +530,24 @@ def _env_default_numeric(name: str, default: float | int, caster: type[float] |
530530

531531

532532
def _validate_settings(settings: MMSettings) -> None:
533-
if not math.isfinite(settings.max_inventory) or settings.max_inventory <= 0:
534-
raise ValueError("max_inventory must be a finite value > 0; adjust --max-inventory")
535-
if not math.isfinite(settings.max_margin_usage) or settings.max_margin_usage <= 0:
536-
raise ValueError("max_margin_usage must be a finite value > 0; adjust --max-margin-usage")
533+
errors: list[str] = []
534+
finite_positive_fields = (
535+
("spread", settings.spread, "--spread"),
536+
("order_size", settings.order_size, "--order-size"),
537+
("max_inventory", settings.max_inventory, "--max-inventory"),
538+
("skew_per_unit", settings.skew_per_unit, "--skew-per-unit"),
539+
("max_margin_usage", settings.max_margin_usage, "--max-margin-usage"),
540+
("refresh_interval_s", settings.refresh_interval_s, "--refresh-interval"),
541+
("cooldown_s", settings.cooldown_s, "--cooldown"),
542+
("cancel_resync_s", settings.cancel_resync_s, "--cancel-resync"),
543+
)
544+
for field_name, value, flag in finite_positive_fields:
545+
if not math.isfinite(value) or value <= 0:
546+
errors.append(f"{field_name} must be a finite value > 0; adjust {flag}")
547+
if settings.max_cycles < 0:
548+
errors.append("max_cycles must be >= 0; adjust --max-cycles")
549+
if errors:
550+
raise ValueError("; ".join(errors))
537551

538552

539553
async def main() -> int:

tests/test_market_maker_bot.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ def test_validate_settings_rejects_non_finite_limits() -> None:
178178
mm._validate_settings(mm.MMSettings(max_margin_usage=float("nan")))
179179

180180

181+
def test_validate_settings_reports_multiple_invalid_fields() -> None:
182+
mm = _load_market_maker_module()
183+
bad = mm.MMSettings(spread=float("nan"), max_margin_usage=0.0, max_cycles=-1)
184+
with pytest.raises(ValueError) as excinfo:
185+
mm._validate_settings(bad)
186+
msg = str(excinfo.value)
187+
assert "spread must be a finite value > 0; adjust --spread" in msg
188+
assert "max_margin_usage must be a finite value > 0; adjust --max-margin-usage" in msg
189+
assert "max_cycles must be >= 0; adjust --max-cycles" in msg
190+
191+
181192
def test_decimal_rounding_helpers_stable_for_tiny_values() -> None:
182193
mm = _load_market_maker_module()
183194
down = mm._round_to_tick_size_decimal(
@@ -284,8 +295,8 @@ async def _fake_run_cycle(*args, **kwargs):
284295
skew_per_unit=0.0001,
285296
max_margin_usage=0.5,
286297
refresh_interval=0.01,
287-
cooldown=0.0,
288-
cancel_resync=0.0,
298+
cooldown=0.01,
299+
cancel_resync=0.01,
289300
max_cycles=1,
290301
dry_run=True,
291302
),

0 commit comments

Comments
 (0)