A compass resting on a map — steering a portfolio by a set heading rather than by hand
Open-source

Sovereign — an autonomous IBKR fund that trades through bezant, with guardrails because it's real money

4 min read Isaac Rowntree

Zack Design has published Sovereign — an open-source, multi-agent portfolio fund for Interactive Brokers. It’s the companion to bezant: bezant mints the access, Sovereign spends it. Nine deterministic TypeScript agents hold a model portfolio, detect drift, size trades with real risk controls, and execute through bezant — standalone, or under whatever scheduler you already run.

Source → github.com/isaacrowntree/sovereign-ibkr-fund (Apache-2.0 OR MIT) · Built on bezant

Why it exists

I had a portfolio problem that a lot of people quietly have: one winner had run so hard it became 40%+ of the book. Great on the way up, a single point of failure on the way down. Fixing that by hand — trimming the concentration, funding a diversified target, doing it without fat-fingering a real order — is exactly the kind of repetitive, high-stakes, easy-to-get-wrong work you should not be doing manually at 11pm.

So the fund isn’t a get-rich bot. It’s a discipline engine: hold a target allocation, notice when reality drifts from it, and make the smallest correct trades to close the gap — with enough guardrails that a bad market-data tick or a logic bug can’t do real damage.

bezant already gave every language typed access to IBKR’s Client Portal API. Sovereign is what happens when you build an actual fund on that foundation and take the “it’s real money” part seriously.

Nine agents, no LLM calls

The agents are plain TypeScript --once processes — deterministic, no model calls in the loop. That’s deliberate: I want a trade decision to be a pure function of the inputs, reproducible and auditable, not a sample from a distribution.

Agent Job
Managing Partner Orchestrates the fund, snapshots NAV and positions
Portfolio Strategist HRP / Black-Litterman weights, drift detection, sizes rebalance orders
Quant Analyst Regime detection, factor regression
Risk Manager VaR / CVaR, drawdown control, volatility targeting
Execution Bot Places orders through bezant — window-gated, capped, reconciled
Tax Optimizer FIFO lots, tax-loss harvesting, wash-sale tracking
Hedger Options overlay (covered calls, protective puts)
Research Scout Price monitoring and alerts
Observer Ingests the WebSocket fill/event stream

Under the hood there’s a real quant toolbox: Hierarchical Risk Parity, Black-Litterman, risk-parity, Ledoit-Wolf shrinkage covariance, a regime overlay, and vol targeting — all backtestable.

The guardrails are the point

Anyone can write a loop that places market orders. The interesting engineering is everything that stops it from doing something stupid with real money:

  • Validation-first execution. Before it will batch a rebalance, the executor proves a live fill on the single smallest order and confirms it against IBKR’s own execution records. No confirmed fill, no batch.
  • Executions are authoritative. Fills are reconciled against IBKR’s execution log, and the trade ledger is idempotent — the same fill can never be recorded twice, even if a confirmation arrives by two paths.
  • Hard caps. Absolute backstops on per-order notional, per-order % of NAV, and per-run notional — independent of the sizing math. A garbled input can’t size a monster order.
  • Data-sanity gates. If NAV or a price tick looks impossible (zeroed, or a 100× move with no cash flow), the strategist refuses to generate orders that cycle rather than trade against garbage.
  • Drawdown control. De-risk and hard-stop thresholds that pull exposure down when the book is bleeding.
  • State lives outside the checkout. Positions and ledger sit in STATE_DIR, never entangled with the code — so a deploy can never clobber your holdings.

Most of these exist because the honest way to build this is to assume your own code will misbehave and make sure the blast radius is bounded when it does.

Standalone, or under whatever you run

Every agent is just node dist/agents/<name>.js --once. That one contract means Sovereign doesn’t care how it’s scheduled:

  • Built-in schedulernpm start runs the whole fund on a cadence, zero dependencies.
  • cron / systemd — point timers at the --once scripts; examples in deploy/.
  • Any orchestrator — set ENABLE_SCHEDULER=false and let your platform drive the same scripts.

The core never imports the scheduler, so it genuinely runs both ways.

Your book stays yours

The public repo ships a generic sample portfolio (a diversified ETF template) and runs against paper out of the box. Your real allocation goes in a gitignored src/portfolios/local.ts that takes precedence automatically and never leaves your machine. Everything else — caps, thresholds, cadences, optimizer choice — is environment-driven. Nothing about your positions lives in the source.

Backtesting

There’s a full backtest engine (HRP, risk-parity, Black-Litterman, regime overlay, vol targeting). The historical dataset is gitignored — you generate it yourself from Yahoo Finance with npm run fetch-data, and the backtest suites skip cleanly until it exists, so a fresh clone is green on the first npm test.

Status and licensing

  • v0.1 — runs end-to-end against IBKR paper accounts; the API and agent set will evolve.
  • Dual-licensed Apache-2.0 OR MIT.
  • Requires a running bezant gateway — that’s how it talks to IBKR.
  • Not affiliated with Interactive Brokers. This is not financial advice. It places real trades — start on paper, and understand every guardrail before you flip TRADING_MODE=live.

If bezant was about making IBKR programmable, Sovereign is about making a portfolio governable — trading on rules you can read, with brakes you can trust. If you’re running money through IBKR and you’d rather it followed a written policy than your 11pm instincts, clone it and point it at your own bezant. Contributions welcome — especially on the optimizers and the risk engine.