/** * Pure decision function: given the exchange's truth (open positions) and the runtime's DSL state, * returns the list of reconcile actions required to bring runtime state in sync. * * No I/O, no imports of SenpiClient, no disk access, no Date.now, no side effects. */ import type { OpenPosition } from "../senpi/types.js"; import type { DslState } from "../types/dsl/index.js"; /** * SIZE_EPS — absolute threshold below which a position size is treated as "flat" (no position). * Mirrors position-tracker.ts `DEFAULT_SIZE_CHANGE_EPSILON = 1e-9`: * sub-unit IEEE-754 drift on perp venues is typically < 1e-12; any real sub-unit trade * is ≥ 0.001 on the smallest venues, so 1e-9 cleanly separates float noise from real size. * Boundary: |szi| <= SIZE_EPS → flat (ignored); |size diff| > SIZE_EPS → resize trigger. */ export declare const SIZE_EPS = 1e-9; /** * ENTRY_EPS — relative tolerance for entry-price comparison. * Entry prices can be large (BTC ~60 000, ETH ~3 000) so an absolute epsilon * would need per-asset tuning. A relative tolerance of 1e-6 (0.0001%) is * large enough to suppress harmless floating-point serialisation drift * (e.g. 60000.000000001 vs 60000.0) while small enough to catch any real * re-entry/average-down event. Formula: |a - b| / max(|b|, 1) > ENTRY_EPS → drift. */ export declare const ENTRY_EPS = 0.000001; export interface ReconcileInputs { /** Strategy wallet address — used only for context in returned actions (not for filtering). */ address: string; /** All positions from the exchange for this wallet (both DEXes; may include zero-size rows). */ exchangePositions: OpenPosition[]; /** All DSL states for this wallet — function filters to active ones internally. */ runtimeDslStates: DslState[]; } export type ReconcileAction = { kind: "adopt"; coin: string; dex: string; position: OpenPosition; } | { kind: "gone"; coin: string; dex: string; state: DslState; } | { kind: "resize"; coin: string; dex: string; position: OpenPosition; state: DslState; }; export interface ReconcileResult { actions: ReconcileAction[]; counts: { toAdopt: number; toArchive: number; toResize: number; }; } /** * Pure, idempotent reconcile decision function. * * Exchange is the source of truth. Running this on a converged state * (after all returned actions have been applied) yields an empty action list. * * Duplicate exchange rows for the same (coin, dex) key: last-wins (later index in the * array wins). This matches typical clearing-house payloads where the last row is freshest. * * Malformed rows (missing coin, NaN/Infinity size or entry, negative coin string) are * silently skipped without throwing. This prevents a single bad row from blocking all * reconciliation. */ export declare function decideReconcile(inputs: ReconcileInputs): ReconcileResult; //# sourceMappingURL=reconcile-decide.d.ts.map