ALLOW, CUT and BLOCK

Every order gets one of three answers, in the same request. What each one means, and what your code does with it.

In development. Not released yet; names and formats may change.View as Markdown

The three answers

reTrade’s three answers, and what happens to the order
AnswerWhat it meansWhat the SDK doesWhat your code does
ALLOWThe order fits every rule.Places it as sent, once.Keep the decision id with your order record.
CUTIt fits only at a smaller quantity.Places the smaller quantity reTrade approved.Treat quantity as what was placed. Don’t send the rest another way.
BLOCKIt breaks a rule, or no room is left.Places nothing.Don’t send it another way. Resize to fits when it’s set, re-plan or ask your user.

Nothing waits for a person. There are no holds and no approval step. An order that once would have waited for someone comes straight back to your agent as a BLOCK, with a reason code, and the agent decides what to do next.

The rule that decided

A CUT or BLOCK names the rule that decided it in deciding, exactly as reTrade sent it: {"code": "order_size_cap"}, for example, or {"code": "approval_line", "reason": "per_order"} for a dollar line. An ALLOW has none. Reason codes lists every code and what the agent can do.

Resizing to fits

Over a dollar line or in an agent conflict, a BLOCK also carries fits: the largest quantity that would pass, or 0 when none would. Your agent can send the order again at fits. That’s a new decision, checked in full, and it counts toward the agent’s orders-per-minute limit (runaway_throttle), as the BLOCK before it did. Resend once; don’t loop.

Python
from dataclasses import replace

from retrade import Outcome, Placement

if (result.outcome is Outcome.BLOCK and result.fits
        and result.placement is Placement.NOT_PLACED):
    result = rt.place(replace(order, quantity=result.fits),
                      account="A1", agent="agt_momentum", via=broker)
TypeScript
const resizable = result.outcome === "BLOCK" && result.placement === "not_placed"
  && result.fits !== null && result.fits !== "0";
if (resizable) {
  result = await rt.place({ ...order, quantity: Number(result.fits) }, {
    account: "A1", agent: "agt_momentum", via: broker,
  });
}

Check placement first, as here: in shadow mode the original order was already placed.

When the SDK decides itself

Sometimes the SDK has no answer it can trust: reTrade didn’t answer within 2.5 seconds (unreachable), or the answer failed a check (unverified). Then the SDK decides on its own: local is true, reason says why, and deciding is empty. In enforce and test mode that’s a BLOCK, and nothing is placed. A local result is never evidence for an insurer.

The SDK also says why in reason when it doesn’t place an approved order, such as expired or broker-rejected. Reason codes lists them all.

How long an answer lasts

An ALLOW or CUT lives 30 seconds by default (an admin can set 5 to 60), counted from when the SDK sent the request. The SDK places it only while time is left and no known stop covers the account and agent, and it places each decision at most once. Otherwise the result’s reason is expired or stopped, and nothing is placed. A BLOCK has no lifetime.

Modes

An account runs in one mode, and your key’s mode must match it
ModeWhat happensEvidence for an insurer
enforcereTrade’s answer decides what reaches the broker.Yes, for placed orders.
shadowYour agent’s orders are placed unchanged, whatever the answer. reTrade only records what it would have done.No.
testLike enforce, for testing.No.

The mode is part of your bot key id, such as exk_test_…. A result’s claimable is true only for an enforce decision whose order was placed. It marks evidence and promises no payment.