/** * Paper-trading Portfolio. * * Tracks cash, positions, and P&L as the agent executes trades. Pure in-memory * math — an Exchange (mock or real) produces Fill events; Portfolio applies * them. Persistence is handled separately in store.ts so tests don't touch disk. * * This is the execution substrate for Franklin's Trading Agent vertical — * the first place where "the AI agent with a wallet" actually makes autonomous * economic decisions and carries real P&L. No live-exchange integration here * yet; MockExchange (mock-exchange.ts) gives deterministic fills for testing, * and a real ExchangeClient adapter can be dropped in later against the same * Fill contract. */ export type Side = 'buy' | 'sell'; export interface Fill { symbol: string; side: Side; qty: number; priceUsd: number; feeUsd?: number; } export interface Position { symbol: string; qty: number; avgPriceUsd: number; } export interface PortfolioOptions { startingCashUsd: number; } export interface MarketSnapshot { equityUsd: number; cashUsd: number; unrealizedPnlUsd: number; realizedPnlUsd: number; positions: Array; } export declare class Portfolio { cashUsd: number; realizedPnlUsd: number; private positions; constructor(opts: PortfolioOptions); getPosition(symbol: string): Position | undefined; listPositions(): Position[]; /** Serializable snapshot for persistence; paired with `restore()`. */ snapshot(): { cashUsd: number; realizedPnlUsd: number; positions: Position[]; }; /** Rehydrate state from a prior snapshot; overwrites all current fields. */ restore(snap: { cashUsd: number; realizedPnlUsd: number; positions: Position[]; }): void; applyFill(fill: Fill): void; /** * Value the portfolio against a live price table. Callers supply the marks * (e.g. from TradingSignal or a live feed) so this stays pure and testable. * Symbols with no mark are valued at avgPriceUsd (zero unrealized P&L). */ markToMarket(priceTable: Record): MarketSnapshot; }