UNPKG

kestrel.markets

Version:

A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.

147 lines (145 loc) 3.97 kB
import"./bin-q0g6xvsw.js"; import"./bin-pcxsrxfy.js"; import"./bin-8gxcgtzn.js"; import"./bin-5t125gvh.js"; import"./bin-xx1qrxe3.js"; import"./bin-t58k60v9.js"; import"./bin-p5jfg5b0.js"; import"./bin-29be75ss.js"; import"./bin-n77kea5n.js"; import"./bin-mn7wcxhv.js"; import"./bin-8pchjxn2.js"; import"./bin-am3351y2.js"; import"./bin-73jr945c.js"; import"./bin-df1tn094.js"; import"./bin-3ft0k1jq.js"; import"./bin-2ywrx58g.js"; import { require_dist } from "./bin-ah4h5nq5.js"; import"./bin-ff04wpv3.js"; import { __toESM } from "./bin-wckvcay0.js"; // src/adapters/broker/ibkr/order-dryrun.ts var import_ib = __toESM(require_dist(), 1); var IB_TICK_BID = 1; var IB_TICK_ASK = 2; var IB_TICK_LAST = 4; var IB_TICK_DELAYED_BID = 66; var IB_TICK_DELAYED_ASK = 67; var IB_TICK_DELAYED_LAST = 68; var IB_MARKET_DATA_LIVE = 1; function freshnessOf(marketDataType) { switch (marketDataType) { case 1: return "live"; case 2: return "frozen"; case 3: return "delayed"; case 4: return "delayed-frozen"; default: return "unknown"; } } function reqMktDataQuotes(transport, timeoutMs = 6000) { const client = transport.client(); let reqId = 9000; client.reqMarketDataType(IB_MARKET_DATA_LIVE); return { quote(contract) { const id = ++reqId; return new Promise((resolve) => { let bid = null; let ask = null; let last = null; let freshness = "unknown"; let done = false; const finish = () => { if (done) return; done = true; clearTimeout(deadline); client.removeListener(import_ib.EventName.tickPrice, onTick); client.removeListener(import_ib.EventName.marketDataType, onType); try { client.cancelMktData(id); } catch {} resolve({ bid, ask, last, freshness }); }; const onType = (rid, marketDataType) => { if (rid !== id) return; freshness = freshnessOf(marketDataType); }; const onTick = (rid, field, value) => { if (rid !== id) return; const v = value > 0 ? value : null; switch (field) { case IB_TICK_BID: bid = v; break; case IB_TICK_ASK: ask = v; break; case IB_TICK_LAST: last = v; break; case IB_TICK_DELAYED_BID: bid = v; freshness = "delayed"; break; case IB_TICK_DELAYED_ASK: ask = v; freshness = "delayed"; break; case IB_TICK_DELAYED_LAST: last = v; freshness = "delayed"; break; default: return; } if (bid !== null && ask !== null) finish(); }; const deadline = setTimeout(finish, timeoutMs); client.on(import_ib.EventName.tickPrice, onTick); client.on(import_ib.EventName.marketDataType, onType); client.reqMktData(id, contract, null, false, false); }); } }; } function priceAnchorFrom(quote, fair) { if (quote.bid === null || quote.ask === null) return; if (quote.freshness !== "live") return; return { bid: quote.bid, ask: quote.ask, fair, fairTrusted: true, freshness: quote.freshness }; } function mintOrderId(client) { let next; client.on(import_ib.EventName.nextValidId, (id) => { if (next === undefined || id > next) next = id; }); client.reqIds(1); return () => { if (next === undefined) { throw new Error("the IB Gateway has issued no nextValidId — refusing to invent an order id (it could collide with a live order). Fail-closed."); } const id = next; next += 1; return id; }; } if (false) {} export { reqMktDataQuotes, priceAnchorFrom, mintOrderId };