How strategies trade real money: dollar amounts, automatic reconciliation, close-all, and the kill switch.
The trading portfolio is the set of strategies allowed to place real orders. Each strategy in it gets a fixed dollar amount; the reconciler daemon then keeps the positions the strategies themselves opened converged to the combined target — you never place these orders yourself. It only manages its own orders: a position you opened by hand is invisible to it and never touched.
strategy.py ──► state.json ──────────────┐
(cron) ├──► reconciler.py ──► exchange
amounts ──► portfolio_config.json ───┘
Each strategy in the portfolio is assigned an amount in account currency (e.g. USD) — what the strategy trades with when its signal is at full size. The target position per symbol is the sum across strategies:
target[symbol] = Σ ( amount × position )
position is the strategy's signal and can be fractional (a vol-scaled strategy may emit 0.5 or 1.8). The amount you set is exactly what sizes positions — it does not drift with account equity. Exception: for Capital (群益) Taiwan futures strategies the amount is a lot count (number of contracts), not a dollar figure.
manager/portfolio_config.json by hand. Set amounts from the workspace Trading setup page or ask the agent; optimizer weights are applied only through manager.py, which is dry-run by default and writes the config only with --apply after you confirm.
The reconciler is a daemon that polls every 5 seconds and reconciles whenever:
state.json changes)Each pass compares the target against the bot's own book — the reconciler keeps its own ledger, a running total of every order it has placed (manager/orders.jsonl), rather than reading the account's raw exchange positions, so a position you opened by hand is never read as "already held" and never added to or closed. Orders are then placed to close the gap — market orders by default; each strategy can be set to market, TWAP, chase limit, or a custom execution style in Trading setup (Capital (群益) TW futures support market only). Differences under $10 are ignored (TW futures reconcile in whole lots instead). A position flip (long → short) is split into a reduce-only close plus a fresh open, so hedge-mode accounts never hold both sides at once.
When positions cannot be read from the exchange: a temporary exchange fault (timeout, busy, maintenance) only skips those rounds, and trading resumes by itself once reads succeed; after 30 minutes in a row you are notified. The reconciler trips the kill switch only for an invalid key, missing permissions, an IP not on the whitelist, 3 unrecognized errors in a row, or an account mismatch found at startup, on reconnect, or after a key change — and that switch never clears itself; you decide when to resume.
Press Pause trading in the workspace and the dialog offers two choices: Pause new positions only trips the kill switch; Pause and close positions (or python3 manager/flatten.py) market-closes the positions the strategies opened — only what is on the bot's own book, so a position you opened by hand is left alone, and spot sells only the coins under strategy management, never your other holdings. It is a panic button, not portfolio management:
While the kill switch is on, any order that would add exposure is refused at the code level. Closing positions, stop-loss / take-profit, and cancels still go through — a halt never traps a position you are trying to reduce.
It is set by Pause trading in the workspace (including Pause and close positions), by telling the agent to stop trading, or automatically on a key or permission error, 3 unrecognized errors in a row, or an account mismatch found at startup, on reconnect, or after a key change (a temporary exchange fault does not trip it — trading resumes by itself once the exchange is back). It is never cleared automatically — trading resumes only when you press Start trading or explicitly ask the agent to resume. Start trading offers two choices as well: Start and catch up positions places market orders immediately to match each strategy's current signal; Start, wait for new signals places no orders now — each strategy starts trading only at its next entry, exit, or flip. Every order attempt and denial is written to an audit log.
Every executed order is appended to manager/orders.jsonl with its legs — the exchange-confirmed fill price and executed quantity of each individual leg. A position flip records two legs: the closing leg carries the exit price, the opening leg the entry price.
Partial failures are recorded too: if a flip's closing leg filled but the opening leg failed, the entry is kept and marked failed — the history never hides an order that moved real money. The workspace Order History tab renders this file.