/**
 * # The IBKR PAPER **DRY-RUN ORDER TICKET** (kestrel-7o2.8) — env-gated, TRANSMITS NOTHING
 *
 * Not a test (it is not a `*.test.ts` and never runs under `bun test`): a hand-run script that drives
 * the whole paper order face against a LIVE, client-launched IB Gateway and **prints the order ticket
 * a human then reviews** — the contract identity, the side/qty, the `@fair`-anchored limit price WITH
 * ITS RECEIPT, the observed bid/ask (a HEALTH SIGNAL, never a price), the max loss, the budget, and
 * the L0 clamp verdict.
 *
 * ## THE HARD RULE: THE DEFAULT PATH TRANSMITS NOTHING
 * It resolves the contract, pulls the quotes, computes the price, runs the L0 clamp, prints the
 * ticket — and STOPS. `IbkrBroker.preflight` is what it calls: the full guard chain WITHOUT the
 * `placeOrder`. Transmission happens ONLY if `KESTREL_IBKR_TRANSMIT=1` is explicitly set, which is a
 * separate, deliberate, HUMAN act. The dry run is the default and says so loudly.
 *
 * ## What it is (and is not) allowed to be
 * - The instrument is **SPY** — a generic, publication-safe ticker. Nothing here reveals an
 *   application or a strategy (ARCHITECTURE §7).
 * - The action is a **DEFINED-RISK LONG**: BUY 1 option contract. Max loss = the premium, so
 *   never-naked holds trivially and the ticket can be checked by eye.
 * - `mode` is **paper**. The order face refuses `live` at construction.
 *
 * ## The quote source is INJECTED
 * kestrel-7o2.7 (the `ibkrFeed` FeedSource) is a parallel bead and does not exist on this branch, so
 * this script pulls its two-sided quotes directly through the transport's shared socket
 * ({@link reqMktDataQuotes}). That path is behind an injected {@link QuoteSource}, so the real feed
 * drops in later without touching this script.
 *
 * ## Run it
 * ```bash
 * KESTREL_IBKR_PAPER_E2E=1 KESTREL_IBKR_CLIENT_ID=14 bun run src/adapters/broker/ibkr/order-dryrun.ts
 * ```
 */
import { EventName } from "@stoqey/ib";
import type { Contract } from "@stoqey/ib";
import { IbkrTransport } from "./transport.ts";
import type { PriceAnchor, QuoteFreshness } from "./broker.ts";
/**
 * A two-sided quote for one contract, WITH ITS PROVENANCE.
 *
 * `bid`/`ask` are a HEALTH SIGNAL (is this thing tradeable?) — never a value, and never a price on
 * their own. But they are not decoration either: they BOUND `@fair`, which is the only thing that
 * prices an order. And `@fair` may only be computed from LIVE input, so `freshness` travels WITH the
 * numbers — a quote that cannot say where it came from cannot anchor anything (kestrel-7o2.8).
 */
export interface TwoSidedQuote {
    readonly bid: number | null;
    readonly ask: number | null;
    readonly last: number | null;
    /** What the VENUE served. Only `live` may ANCHOR a price; the rest are health signals only. */
    readonly freshness: QuoteFreshness;
}
/**
 * Where the dry run gets its quotes (kestrel-7o2.8). INJECTED so the real `ibkrFeed` FeedSource
 * (kestrel-7o2.7, a parallel bead) substitutes for {@link reqMktDataQuotes} later without this script
 * changing at all.
 */
export interface QuoteSource {
    quote(contract: Contract): Promise<TwoSidedQuote>;
}
/**
 * The default {@link QuoteSource}: `reqMktData` over the transport's ONE shared socket. It collects
 * `tickPrice` until BOTH sides are present or the deadline lapses, then cancels the subscription.
 *
 * ## It asks for LIVE, and it REPORTS what it actually got (kestrel-7o2.8, blocker 4a)
 * The shipped version asked for `DELAYED_FROZEN` and fed the result to `@fair` as a PRICE ANCHOR. That
 * is the defect: a price anchor must never accept delayed/frozen input. So we request **LIVE** (type
 * 1) — and because IB SUBSTITUTES rather than refusing when the account lacks a live subscription, we
 * also LISTEN: the venue's own `marketDataType` callback, and the arrival of the DELAYED tick ids
 * (66/67/68), each stamp the quote's {@link TwoSidedQuote.freshness}. A delayed quote is still returned
 * — it is an honest health signal, and a MISSING one would look like a dark book — but it is returned
 * WEARING ITS LABEL, and everything that PRICES an order refuses it (the broker's price-anchor wall).
 */
export declare function reqMktDataQuotes(transport: IbkrTransport, timeoutMs?: number): QuoteSource;
/**
 * Build the broker's {@link PriceAnchor} from an OBSERVED quote and the `@fair` derived from it —
 * fail-closed: a quote that is not LIVE and two-sided yields NO anchor at all, and the broker's
 * price-anchor wall then refuses the order. This is the ONE place a script turns a quote into
 * something that may price an order, and it is deliberately unable to launder a stale one.
 */
export declare function priceAnchorFrom(quote: TwoSidedQuote, fair: number): PriceAnchor | undefined;
/**
 * The order-id minter. The sequence is the GATEWAY's (`nextValidId`) — never ours to invent, and never
 * an RNG. It is drawn ONLY on the transmit path; the dry run never reaches it. If the gateway never
 * issued a seed, a transmit FAILS CLOSED rather than guessing an id that might collide with a live one.
 *
 * EXPORTED (kestrel-7o2.12) so the paper session driver's venue composition draws its order ids from
 * this ONE rule rather than a second copy of it — a rule that exists twice is a rule that diverges.
 */
export declare function mintOrderId(client: {
    on(event: EventName, listener: (...args: never[]) => void): unknown;
    reqIds(n?: number): unknown;
}): () => number;
//# sourceMappingURL=order-dryrun.d.ts.map