import type { CloseOrderType, CreatePositionRequest, CreatePositionResult, EditPositionResult, OrderStatus, FeeOptimizedLimitOptions, RatchetStopEvent, RatchetStopPosition } from "../senpi/types.js"; export type TradingRisk = 'conservative' | 'moderate' | 'aggressive'; /** Strategy configuration. Address is the strategy identifier (platform id). */ export interface StrategyConfig { address: string; /** Initial strategy budget (USD); used for guard-rail resolution (e.g. daily_loss_limit_pct). */ budget?: number; slots: number; tradingRisk: TradingRisk; marginPerSlot?: number; marginPct?: number; defaultLeverage?: number; leverageMultipliers?: Partial>; dailyLossLimit?: number; dsl?: Record; guardRails?: Record; dataRetentionHours?: number; enabled?: boolean; } /** Account-level + position data from strategy_get_clearinghouse_state (single MCP call). */ export interface ClearinghouseState { accountValue: number; totalMarginUsed: number; totalUnrealizedPnl: number; totalNtlPos: number; withdrawable: number; positions: OpenPosition[]; /** Minimum `time` (ms epoch) across all dex entries in the API response. Indicates data freshness. */ time: number; } export interface OpenPosition { coin: string; dex: string; szi: number; entryPx: number; leverage: number; leverageType: "cross" | "isolated"; unrealizedPnl: number; marginUsed: number; liquidationPx: number | null; returnOnEquity: number; } export interface PastTrade { coin: string; /** HIP-3 / xyz book when present (matches DSL dex normalization). */ dex?: string; direction: 'LONG' | 'SHORT'; entryPx: number; closePx: number; szi: number; realizedPnl: number; closedTime: number; openTime: number; totalFees: number; } export interface OpenOrder { orderId: number; coin: string; side: 'BUY' | 'SELL'; size: number; price: number; orderType: string; status: string; timestamp: number; } export interface StrategyDetails { strategyId: string; name: string; status: string; traderAddress: string; /** * Total USDC funded into the strategy — `undefined` when the backend reported no readable figure. * * The distinction survives all the way to the reader: this object is what the `strategy: details` * context slice hands an LLM decision prompt, and `JSON.stringify` drops an `undefined` key, so an * unreadable amount reaches the prompt as ABSENT rather than as `0`. A zero here would say the * wallet is empty, which is the opposite next step from "nobody read this figure". */ initialBudget: number | undefined; totalPnl: number; pnlPercentage: number; createdAt: string; } /** Runtime strategy state. Address is the strategy identifier and equals config.address. */ export interface StrategyState { readonly address: string; readonly config: StrategyConfig; getClearinghouseState(): ClearinghouseState | undefined; getOpenPositions(): OpenPosition[] | undefined; getPastTrades(): PastTrade[] | undefined; getOpenOrders(): OpenOrder[] | undefined; /** * Free slots per the last fetched clearinghouse view, or **0 when no view has been * fetched** — an unread book is unknown, not empty, and this getter fails closed rather * than reporting the full cap. Read `config.slots` for the configured cap; fetch first if * you need the live count. */ getAvailableSlots(): number; getDetails(): StrategyDetails | undefined; hasOpenPosition(coin: string, dex?: string): boolean; fetchClearinghouseState(opts?: { retryUnreadable?: boolean; signal?: AbortSignal; }): Promise; fetchPastTrades(opts?: { limit?: number; offset?: number; sort_by?: string; sort_direction?: string; }): Promise; fetchOpenOrders(): Promise; fetchDetails(): Promise; refresh(): Promise; cancelOrder(orderId: number): Promise; closePosition(coin: string, reason: string, dex?: string, orderOptions?: { orderType?: CloseOrderType; feeOptimizedLimitOptions?: FeeOptimizedLimitOptions; /** Structured close-reason context (notifications 2.3): the configured time limit in minutes (hard_timeout cuts). */ closeLimitMinutes?: number; /** Structured close-reason context (notifications 2.3): the peak ROE percent the cut decision used (weak_peak_cut). */ closePeakRoe?: number; }): Promise; createPosition(params: CreatePositionRequest): Promise; editPosition(payload: { coin: string; dex?: string; stopLoss?: { triggerPx: number; }; }): Promise; /** `opts.timeoutMs` overrides the default read timeout for callers that must bound the wait. */ getOrderStatus(orderId: number, opts?: { timeoutMs?: number; }): Promise; addRatchetStop(params: { asset: string; dex?: string; direction?: "LONG" | "SHORT"; entryPrice?: number; size?: number; leverage?: number; ratchetStopConfig: { tiered: { tiers: Array<{ triggerRoe: number; lockRoe: number; }>; }; }; }): Promise<{ success: boolean; position?: RatchetStopPosition; }>; deleteRatchetStop(params: { asset: string; dex?: string; }): Promise<{ success: boolean; }>; queryRatchetStops(params?: { asset?: string; dex?: string; status?: "ACTIVE" | "PAUSED" | "DELETED" | "ALL"; }): Promise; queryRatchetStopEvents(params?: { positionId?: string; since?: string; sortOrder?: "ASC" | "DESC"; }): Promise; } //# sourceMappingURL=strategy.d.ts.map