The first live UCITS paper run on bizworx reported EXECUTED/exit-0 but was
degraded: the IEF->CBU0 leg got 0 fills and DBMF hung Submitted.
- Error 478 (contract conflict): the ISIN-qualified UCITS contract kept a
localSymbol/secId conflicting with the pinned conId (requested CBU0 vs
canonical CSBGU0). Strip secId/secIdType/localSymbol after resolve and route
by conId + SMART.
- Error 10349 (TIF preset): the bare MarketOrder had no TIF so the account
preset forced DAY + cancel/reconfirm. Set explicit tif="DAY".
- False-success (the dangerous one): plan.executed counted Cancelled/Submitted
legs as placed, and exec-record booked on any non-blocked run. Now executed
requires EVERY leg filled; a degraded run prints DEGRADED, exits 1, and
skips exec-track booking so the reconciliation gate stays WAIT (never books a
phantom rebalance) — real money errs false-WAIT.
Tests: new test_ucits_exec_fill_status.py + degraded cases in test_execution.py
and test_execute_multistrat_b2a.py (TDD failing-first). 523 exec/forward/gate
tests green, mypy clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The IEF->CBU0 UCITS remap (515117d, 2026-07-16 12:28) left the paper account
holding IDTM (the old thin Dist line, bought on the 07-15/16 09:00 runs under the
prior IEF->IDTM config). The rebalancer only ever traded its TARGET symbols
(_plan iterates targets.items()), so it never sold the orphaned IDTM — it lingered
in the account NLV and (correctly) tripped the stray-holdings warning.
Fix — scoped, safe self-cleaning:
- superseded_holdings(): the symbols multistrat ITSELF previously traded (per its
own exec_fills) that are still held but no longer a target — priced at the last
fill. Scoped to multistrat's own fills, so a position ANOTHER strategy holds on
the SHARED IBKR account is never touched.
- plan_and_record: adds them at target weight 0 (+ LSEETF/USD spec so a UCITS line
resolves by symbol to SELL) before the rebalance. Best-effort: a scan failure
never blocks a real rebalance.
- _plan: a full EXIT (weight 0 on a held line) ALWAYS trades — hysteresis damps
churn, it must not strand a position we're deliberately closing.
Next UCITS rebalance (09:00) closes IDTM and buys CBU0; the warning clears. Also
prevents future mapping-change legacy from silently accreting in the NLV.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The IGLN gold-sleeve 'priced but no order' bug. scaled_weights sizes orders to
the paper envelope (envelope*within_weight), but _plan's entry-floor/hysteresis
threshold used entry_floor*nlv (the full $1M account NLV) — so the effective
floor was ~entry_floor*(nlv/envelope) of the envelope (~5%), silently dropping
every sleeve below it. A 3% gold sleeve at a $100k envelope on a $1M account
skipped. FIX: rebalance_weights takes sizing_capital (the envelope); the floor
is entry_floor*min(sizing_capital,nlv). Sizing + recording unchanged. Regression
test: a 3% sleeve survives WITH the envelope basis, drops without it. 2005 green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
execute-multistrat --venue ucits was unrunnable and mis-sized:
- place_order hardcoded Stock(symbol, SMART, USD) so LSE-listed UCITS ETFs
(CSPX/IBTM/SGLN/ICOM/DBMF) failed IBKR resolution (Error 200);
- apply_ucits_map reused the US ticker's Yahoo price for the UCITS ticker, so
shares = weight*envelope/price was wrong;
- any single unmapped sleeve refused the whole (PRIIPs-legal) rebalance.
Fix:
- Order carries optional exchange/currency/sec_id_type/sec_id (US path keeps
SMART/USD defaults, byte-unchanged). IbkrBroker resolves UCITS orders via
Contract(secIdType=ISIN, secId, currency=USD) + qualifyContracts; an
unresolved contract logs loudly and is SKIPPED (no crash, no wrong order).
- IbkrBroker.market_price fetches the REAL UCITS USD price via delayed market
data (reqMarketDataType(3) + reqMktData snapshot); the UCITS route sizes from
it, not the US Yahoo price. Modeled US weights unchanged.
- route_ucits routes sleeves that map+resolve+price and loudly logs+skips the
rest; survivors keep their own weight (book NOT rescaled), skipped $ reported.
- UcitsSettings.map now carries verified ISINs (CSPX IE00B5BMR087, IBTM
IE00B1FZS798, SGLN IE00B4ND3602, ICOM IE00BDFL4P12) and DBMF is mapped to the
real iMGP DBi Managed Futures UCITS ETF (LU2951555585, USD line) with a
liquidity caveat comment.
TDD mocks the IB client (no live broker). Full suite: 1986 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Puts the adaptive multi-strat ETF book on the clean execution port:
- multistrat.target_weights(closes): exposes the final-day per-instrument weights
(L*tw*volnorm_scale) that book_series applies but only collapses into a return.
Refactored _volnorm via a shared _volnorm_scale so book_series stays byte-identical.
Tested: sum(w*R[last]) reconstructs book_series's last booked return exactly.
- ExecutionService.rebalance_weights(weights, prices): a direct pre-computed-weights
entry beside rebalance(book), sharing one _plan engine (gates + fractional sizing).
Caller owns data<->broker symbol mapping.
- AlpacaBroker crypto-aware: a slash symbol (BTC/USD) -> time_in_force gtc; equities
stay day. So the book's BTC-USD leg trades on Alpaca crypto alongside the 5 ETFs.
- CLI fxhnt execute-multistrat (maps BTC-USD -> BTC/USD); the alpaca-rebalancer
CronJob now runs it (suspended until paper keys).
Full suite green (1832); +5 tests. Alpaca-crypto position-symbol form validated on
first paper run.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Foundation for a 2nd, uncorrelated execution venue alongside the Bybit crypto book:
- AlpacaBroker (httpx REST, Broker port): account_state + place_order, FRACTIONAL
market+day orders, is_paper from base_url, supports_fractional=True. httpx test
seam (MockTransport) — no network.
- ExecutionService fractional-aware: sizes float shares when broker.supports_fractional
(Alpaca) — precise weights at small capital — else whole shares (IBKR, unchanged).
- AlpacaSettings (paper base_url default; live gated by allow_live). CLI
.
- Suspended CronJob + credentials scaffold (arm after paper keys, like the Bybit
testnet leg). Runs the survivor book end-to-end.
The multi-strat ETF book on Alpaca is a documented follow-up (its position logic
isn't on the clean port yet). Full suite green (1827); 6 new tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>