feat(exec): execute-multistrat --broker ibkr (whole-share) alongside alpaca

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-07-10 22:53:20 +02:00
parent 2b02942ef9
commit 3488c69ff2

View File

@@ -277,6 +277,8 @@ def execute_multistrat(
do_execute: bool = typer.Option(False, "--execute", help="place orders (default: dry-run plan only)"),
live: bool = typer.Option(False, "--live", help="allow a non-paper account"),
max_gross: float = typer.Option(2.0, help="gross budget (risk-parity multistrat can sit modestly above 1)"),
broker_name: str = typer.Option("alpaca", "--broker",
help="execution venue: 'alpaca' (fractional) or 'ibkr' (whole-share)"),
) -> None:
"""Compute the adaptive multi-strat book's CURRENT target weights and rebalance them on ALPACA — the 5
pure-equity streams (SPY/IEF/GLD/PDBC/DBMF) as fractional shares. BTC-USD is DROPPED from the fund book
@@ -284,7 +286,6 @@ def execute_multistrat(
no crypto order. Dry-run by default. Same ExecutionService safety gates + fractional sizing as `execute`."""
import datetime as _dt
from fxhnt.adapters.broker.alpaca import AlpacaBroker
from fxhnt.adapters.persistence.forward_nav import ForwardNavRepo
from fxhnt.application.multistrat_exec_record import plan_and_record
from fxhnt.domain.strategies import multistrat
@@ -314,8 +315,18 @@ def execute_multistrat(
today = _dt.datetime.now(_dt.UTC).strftime("%Y-%m-%d")
at = _dt.datetime.now(_dt.UTC).replace(tzinfo=None)
broker = AlpacaBroker(settings.alpaca.api_key, settings.alpaca.api_secret,
settings.alpaca.base_url, settings.alpaca.timeout)
# execution venue: IBKR (whole-share, via ib-gateway) or Alpaca (fractional). Both are the Broker port —
# ExecutionService + plan_and_record are broker-agnostic (fractional handling keys off supports_fractional).
if broker_name == "ibkr":
from fxhnt.adapters.broker.ibkr import IbkrBroker
broker: Any = IbkrBroker(settings.ibkr.host, settings.ibkr.port,
settings.ibkr.client_id, settings.ibkr.timeout)
where = f"IBKR ({settings.ibkr.host}:{settings.ibkr.port})"
else:
from fxhnt.adapters.broker.alpaca import AlpacaBroker
broker = AlpacaBroker(settings.alpaca.api_key, settings.alpaca.api_secret,
settings.alpaca.base_url, settings.alpaca.timeout)
where = f"Alpaca ({settings.alpaca.base_url})"
try:
with broker as brk:
svc = ExecutionService(data, brk, settings)
@@ -325,7 +336,7 @@ def execute_multistrat(
today=today, at=at, max_gross=max_gross, execute=do_execute)
except Exception as e: # connection / runtime
typer.echo(f"broker error: {type(e).__name__}: {str(e)[:100]}")
typer.echo(f" reachable? Alpaca ({settings.alpaca.base_url}) — creds set?")
typer.echo(f" reachable? {where} — creds/gateway set?")
raise typer.Exit(1) from e
typer.echo(f"NLV ${plan.nlv:,.0f} | envelope ${envelope:,.0f} (B2a) | orders {len(plan.orders)}")
for n in plan.notes: