Skip to main content
Position management handles the lifecycle of open positions, from creation through exit plan updates to automated closures via stop-loss and take-profit triggers.

Orders Table: Single Source of Truth

All position and trade data is stored in the Orders table with a status-based state model:

OPEN Status

Active positions shown in the Positions tab. Unrealized P&L calculated live from current market prices.

CLOSED Status

Completed trades shown in the Trades tab. Realized P&L and exit price recorded at close time.
Location: src/db/schema.ts:125

Exit Plans

Exit plans define the conditions under which a position should be closed. They are stored in the exitPlan JSONB column and used for both manual reference and automated execution.

Exit Plan Structure

Confidence represents the AI’s confidence in the exit plan, not the trade itself. A high confidence exit plan means the AI is certain about where to place stops and targets.

Creating Exit Plans

Exit plans are specified when creating positions and can be updated later via the updateExitPlanTool.

Updating Exit Plans

AI agents can update exit plans for open positions using the updateExitPlanTool.
Location: src/server/features/trading/agent/tools/updateExitPlanTool.ts
Updating the exit plan in live mode cancels existing SL/TP orders and places new ones with the updated prices.

Stop-Loss and Take-Profit Automation

Live Trading: Exchange Orders

In live trading mode, SL/TP are real orders placed on the Lighter exchange that execute automatically when price triggers are hit.
Location: src/server/features/trading/slTpOrderManager.ts:35 Order Types:
  • STOP_LOSS: Triggers when price moves against position (Mark price ≤ trigger for LONG)
  • TAKE_PROFIT: Triggers when price moves in favor (Mark price ≥ trigger for LONG)
  • Both use reduceOnly: 1 to ensure they only close positions, never open new ones
  • Expiry set to 28 days (longest allowed by Lighter exchange)
Database Tracking: The slOrderIndex and tpOrderIndex are stored in the Orders table to enable cancellation when:
  • Position is manually closed
  • Exit plan is updated
  • Position is scaled into (new quantity requires new orders)

Simulation: In-Memory Triggers

In simulation mode, SL/TP are checked in-memory during the market refresh polling cycle.
Location: src/server/features/simulator/exchangeSimulator.ts:261 Trigger Detection (in AccountState):
Auto-Close Flow:
  1. Every 5 seconds: Refresh market prices for all symbols
  2. Update mark prices: Apply new prices to all open positions
  3. Collect triggers: Check if any position’s SL or TP has been hit
  4. Queue auto-closes: Add triggered positions to close queue
  5. Execute closes: Place reverse orders to close positions
  6. Update database: Set status=CLOSED, exitPrice, realizedPnl, closeTrigger
  7. Emit events: Notify UI of position closures
The simulator restores OPEN positions from the database on startup to ensure auto-close triggers survive server restarts. See exchangeSimulator.ts:203 for the restoration logic.

P&L Calculation

Unrealized P&L (OPEN Positions)

Calculated live from current mark prices, not stored in the database.
Example (LONG):
  • Entry: 1.0 BTC @ $50,000
  • Mark: $51,000
  • Unrealized P&L: (51,000−51,000 - 50,000) × 1.0 = $1,000
Example (SHORT):
  • Entry: 1.0 BTC @ $50,000
  • Mark: $49,000
  • Unrealized P&L: (50,000−50,000 - 49,000) × 1.0 = $1,000

Realized P&L (CLOSED Positions)

Calculated once at close and stored in realizedPnl field.
Example (LONG):
  • Entry: 1.0 BTC @ $50,000
  • Exit: 1.0 BTC @ $52,000
  • Realized P&L: (52,000−52,000 - 50,000) × 1.0 = $2,000

Notional Values

Entry Notional: entryPrice × quantity Exit Notional: exitPrice × quantity These are derived values, not stored in the database. Calculated on-the-fly when needed.
Notional values are useful for calculating return percentages: Return % = (exitNotional - entryNotional) / entryNotional × 100

Position Lifecycle

1

Position Created

  • Order placed and filled on exchange/simulator
  • Orders table record created with status=OPEN
  • SL/TP orders placed (live mode) or exit plan stored (simulation)
  • openedAt timestamp recorded
2

Position Active

  • Unrealized P&L calculated live from mark prices
  • Exit plan can be updated via updateExitPlanTool
  • Additional quantity can be added via position scaling
  • SL/TP orders updated when exit plan changes
3

Position Closed

  • Reverse order placed to close position
  • Exit price and realized P&L calculated
  • Orders table updated: status=CLOSED, exitPrice, realizedPnl, closedAt
  • closeTrigger set: null (manual), "STOP", or "TARGET"
  • SL/TP orders cancelled (live mode)

Best Practices

Always Set SL/TP

Every position should have a stop-loss to limit downside risk. Take-profit targets help lock in gains.

Update Exit Plans Dynamically

Use updateExitPlanTool to adjust stops and targets as market conditions evolve.

Store Confidence

Record AI confidence in exit plans to help analyze which strategies work best.

Use Descriptive Invalidations

Provide clear text descriptions of invalidation conditions to help with post-trade analysis.

Next Steps

Risk Controls

Learn about position sizing and risk management

Order Execution

Understand how orders are placed and filled