DocumentationOperate

Protection and risk reduction

Updated: 2026-08-13

Nothing here submits an order for you. The daemon can propose a close or a reduce and can price one against the broker. Placing it stays an explicit instruction from you, for that exact order, in that moment.

A blocked proposal row is normally the system refusing to act on evidence it cannot trust, not a fault to work around. Canary exposes only constrained close/reduce actions here; use TWS for an unmodeled emergency exit.

What each command does

Command Reaches the broker Use it for
canary proposals list no the current proposal set, blockers included
canary proposals refresh no rebuild the set against fresh positions and quotes
canary proposals preview KEY REVISION no mint a preview token and read the broker WhatIf verdict
canary proposals submit KEY REVISION yes place that one protective order
canary proposals reduce SYMBOL --percent N only with --submit a discretionary partial close
canary proposals request-stop SYMBOL no stage a trailing-stop proposal for one uncovered stock/ETF holding now

canary proposals with no subcommand runs list. In a standard build the submit path fails closed anyway: the daemon's write handler is compiled out behind the trading build tag and returns ErrTradingDisabled. See Constrained orders and the trading build.

Proposals are advisory, and close or reduce only

The daemon owns generation. It rebuilds the set from current positions, the protection policy, and market-event context, and every row it emits closes or reduces. The submit path checks that twice, once against the proposal's own position effect and once against the preview's, and blocks on either. A protection proposal cannot open, increase, or flip exposure. authority.auto_submit must be false; the policy file fails validation otherwise.

Four buckets generate rows, each enabled separately in the protection policy:

The option-exit policy uses the explicitly approved absolute 0.05 quote-currency TRAIL LIMIT offset. An inherited or omitted offset still fails activation, and an empty exact-contract intent list produces no candidates.

canary proposals reduce is separate: a discretionary partial close you size yourself. It previews unless you pass --submit. Under --portfolio the percentage is the share of net delta-adjusted portfolio risk to remove rather than a flat per-position cut, and hedges are never selected, so --include-hedges is a hard error there instead of a silent no-op.

canary proposals request-stop answers the coverage ledger directly: name an uncovered stock/ETF holding (symbol, or --con-id when ambiguous) and the daemon rebuilds the proposal set and returns that position's trailing-stop proposal with the key and revision to preview. It generates only — placing the stop still goes through preview and submit with every gate intact. An earlier ignore for that stop is cleared by the explicit request, and the result says so. The paired app offers the same action from the Protection panel's uncovered-positions list.

Option exits do not enter the protection coverage ledger. That ledger remains stock/ETF stop coverage; calling a directional option exit portfolio protection would overstate what the broker is actually covering. Option proposals still use the same preview, WhatIf, full position-effect, duplicate-order, account, mode, freeze, origin and explicit submit gates as every other broker-adjacent proposal.

A blocked row is the system working

Every blocker carries a code, a message, and an action line. Under stress the action is the part to read, because it names the next command.

An active regulatory or news halt blocks the row. So does an active LULD pause. That is deliberate: a protective order priced against a symbol that is not trading is a guess about the reopening print. Recent flags that are no longer active stay visible as context and do not block.

Other rows block because the evidence is not good enough. A stale option-exit quote raises fresh_option_quote_required. A revision older than the current snapshot raises stale_revision. A time-in-force that drifted between the proposal and its preview raises tif_drift, and a quantity beyond the position raises quantity_outside_position. The row stays visible with its reason attached rather than quietly disappearing.

An explicitly declared option whose exact quote, cost, role, or session evidence is unavailable appears as a blocked Option exit review row. It is not silently dropped and it cannot be previewed as an order.

When a stop no longer matches its position

If a position shrinks or goes flat while a close-only protective order is still working, the daemon marks that order position_mismatch and grades it critical. Triggering it would open an opposite-direction position rather than close anything.

Kind What it means Fix
short_entry_full no coverage left cancel the order
short_entry_excess partial coverage reduce to reduce_to_quantity

reduce_to_quantity is the position magnitude available in the order's closing direction: the long share count for a SELL, the short magnitude for a BUY. It is the exact quantity a reduce-modify has to target, and it appears with short_risk_quantity in canary orders open --json. The same holdings show up in canary positions as reconcile_required under protection coverage, where a stale protective order is deliberately not counted as protection.