From 160b100f9c9121ce030817ce031e15a9be1061d0 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Fri, 18 Sep 2026 04:21:28 +0800 Subject: [PATCH] fix(ibkr): probe write access with safe-haven what-if symbol SOXL one-share what-if exceeds small-account initial margin and emits Error 201; use BIL/safe haven so permission checks do not look like failed live orders. Co-authored-by: Cursor --- main.py | 13 +++++++++---- tests/test_request_handling.py | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 1616607..a5a1e42 100644 --- a/main.py +++ b/main.py @@ -576,14 +576,19 @@ def submit_market_order_intent(ib, order_intent, **kwargs): def probe_market_order_write_access(ib): - managed_symbols = resolve_reporting_managed_symbols() - if len(ACCOUNT_IDS) != 1 or not managed_symbols: + """Probe order-write access with a low-notional safe-haven what-if buy. + + Do not use the first managed growth symbol (e.g. SOXL): one share can exceed + small-account initial margin and emit Error 201 even though write access is OK. + """ + if len(ACCOUNT_IDS) != 1: raise RuntimeError( - "IBKR what-if permission probe requires one account_id and one managed symbol" + "IBKR what-if permission probe requires exactly one account_id" ) + probe_symbol = str(SAFE_HAVEN or "BIL").strip().upper() or "BIL" return probe_order_write_access( ib, - symbol=managed_symbols[0], + symbol=probe_symbol, account_id=ACCOUNT_IDS[0], stock_exchange=MARKET_EXCHANGE, stock_currency=MARKET_CURRENCY, diff --git a/tests/test_request_handling.py b/tests/test_request_handling.py index 9213010..68879b1 100644 --- a/tests/test_request_handling.py +++ b/tests/test_request_handling.py @@ -409,6 +409,30 @@ def fake_build_broker_adapters(*, dry_run_only_override=None): assert observed["dry_run_only_override"] is True +def test_probe_market_order_write_access_uses_safe_haven_not_growth_symbol( + strategy_module, monkeypatch +): + observed = {} + + def fake_probe(_ib, *, symbol, account_id, **_kwargs): + observed["symbol"] = symbol + observed["account_id"] = account_id + return types.SimpleNamespace(warningText="") + + monkeypatch.setattr(strategy_module, "probe_order_write_access", fake_probe) + monkeypatch.setattr(strategy_module, "SAFE_HAVEN", "BIL") + monkeypatch.setattr(strategy_module, "ACCOUNT_IDS", ["U1234567"]) + monkeypatch.setattr( + strategy_module, + "resolve_reporting_managed_symbols", + lambda: ("SOXL", "SOXX", "BIL"), + ) + + strategy_module.probe_market_order_write_access(object()) + + assert observed == {"symbol": "BIL", "account_id": "U1234567"} + + def test_handle_dry_run_ignores_paper_liquidate_only(strategy_module, monkeypatch): observed = {"called": False}