Skip to main content
The order management system tracks your positions from creation to closure, providing real-time updates on profit/loss and allowing you to close positions at any time.

Order Lifecycle

Every order goes through these stages:
All open orders are held in-memory in the Engine for instant access and real-time P/L calculations.

Viewing Open Orders

Retrieve all your active positions:
curl -X GET https://api.exness.com/api/v1/trade/open \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Order Details

Each order includes:
FieldDescription
orderIdUnique identifier for the order
symbolTrading pair (btc, eth, sol)
typebuy or sell
quantityAmount traded
leverageLeverage multiplier used
openPricePrice when order was created
currentPriceLive market price (updated in real-time)
openTimeTimestamp when order opened
takeProfitAuto-close price for profits
stopLossAuto-close price for losses
statusCurrent order status

Fetching Open Orders

The backend retrieves orders from the Engine via Redis Streams:
// apps/Backend/src/routes/trade.routes.ts
tradeRouter.get("/open", authMiddleware, async (req: Request, res: Response) => {
  const userId = req.user?.id;
  if (!userId) {
    return res.status(401).json({ error: "Unauthorized" });
  }

  const RedisStreams = req.app.locals.redisStreams;
  
  // Request open orders from Engine
  const streamResult = await RedisStreams.addToRedisStream(
    constant.redisStream,
    {
      function: "getOpenOrder",
      userId
    }
  );
  
  const requestId = streamResult?.requestId;

  // Wait for Engine response (5 second timeout)
  const result = await RedisStreams.readNextFromRedisStream(
    constant.secondaryRedisStream,
    5000,
    { requestId }
  );

  if (result && result.function === "getOpenOrder") {
    res.json({
      message: result.message // JSON string of orders
    });
  } else {
    res.json({
      message: JSON.stringify([])
    });
  }
});
Open orders are stored in-memory for instant access. The Engine updates current prices every 3 seconds from the Price Poller.

Closing an Order

Close a position to realize profits or losses:
curl -X POST https://api.exness.com/api/v1/trade/close \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "orderId": "550e8400-e29b-41d4-a716-446655440000"
  }'

Close Order Processing

When you close an order:
// apps/Backend/src/routes/trade.routes.ts
tradeRouter.post("/close", authMiddleware, async (req: Request, res: Response) => {
  const { orderId } = req.body;
  const userId = req.user?.id;
  
  if (!orderId) {
    return res.status(400).json({
      error: "Missing required parameters: orderId"
    });
  }

  const RedisStreams = req.app.locals.redisStreams;
  
  // Send close request to Engine
  const streamResult = await RedisStreams.addToRedisStream(
    constant.redisStream,
    {
      function: "createCloseOrder",
      orderId,
      userId
    }
  );
  
  const requestId = streamResult?.requestId;

  // Wait for Engine response
  const result = await RedisStreams.readNextFromRedisStream(
    constant.secondaryRedisStream,
    5000,
    { requestId }
  );

  if (result && result.function === "createCloseOrder") {
    const orderData = JSON.parse(result.message);
    
    if (orderData.error) {
      return res.status(400).json({ error: orderData.error });
    }
    
    res.json({
      message: "Order closed successfully",
      order: orderData
    });
  }
});

Profit/Loss Calculation

The platform calculates P/L based on order type:

Buy Orders

// Profit when price increases
profitLoss = (closePrice - openPrice) × quantity

// Example: Buy 0.1 BTC at $43,000, close at $43,500
profitLoss = (43500 - 43000) × 0.1 = $50

Sell Orders

// Profit when price decreases
profitLoss = (openPrice - closePrice) × quantity

// Example: Sell 1 ETH at $2,500, close at $2,400
profitLoss = (2500 - 2400) × 1 = $100
P/L is calculated without accounting for leverage. Your actual return percentage is multiplied by your leverage.

Viewing Closed Orders

Access your trading history:
curl -X GET https://api.exness.com/api/v1/trade/close \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
Closed orders are persisted to the database by the DBStorage service and can be queried at any time.

Take Profit & Stop Loss

Automate your exit strategy with conditional closes:

Take Profit

Automatically close when price reaches your profit target:
// Buy BTC at $43,000 with take profit at $45,000
{
  "symbol": "BTCUSDT",
  "type": "buy",
  "quantity": 0.1,
  "leverage": 10,
  "takeProfit": 45000  // Auto-close when price hits $45,000
}

Stop Loss

Automatically close to limit losses:
// Buy BTC at $43,000 with stop loss at $42,000
{
  "symbol": "BTCUSDT",
  "type": "buy",
  "quantity": 0.1,
  "leverage": 10,
  "stopLoss": 42000  // Auto-close when price drops to $42,000
}
Always set both take profit and stop loss to manage risk. A common strategy is to set stop loss at 2% and take profit at 4% for a 2:1 risk-reward ratio.

Order States

StateDescriptionLocation
OpenActive position being monitoredEngine (in-memory)
ClosedPosition settled, P/L realizedDatabase (DBStorage)

Real-Time Updates

The Engine continuously monitors open orders:
// apps/Engine/src/functions/pricePoller.ts
export function pricePollerFunction(result: any) {
  const priceUpdates = JSON.parse(result.message);
  
  // Update global prices array
  priceUpdates.forEach((update: PriceUpdate) => {
    const idx = prices.findIndex((p) => p.asset === update.asset);
    if (idx !== -1) {
      prices[idx] = update;
    } else {
      prices.push(update);
    }
  });
  
  // Check all open orders for take profit / stop loss triggers
  openOrders.forEach((order) => {
    const priceData = prices.find((p) => p.asset === getPriceAssetName(order.symbol));
    if (!priceData) return;
    
    const currentPrice = order.type === "buy" ? priceData.bidValue : priceData.askValue;
    
    // Check take profit
    if (order.takeProfit && currentPrice >= order.takeProfit) {
      createCloseOrderFunction({ orderId: order.orderId, userId: order.userId });
    }
    
    // Check stop loss
    if (order.stopLoss && currentPrice <= order.stopLoss) {
      createCloseOrderFunction({ orderId: order.orderId, userId: order.userId });
    }
  });
}
Price updates arrive every 3 seconds. The Engine checks all open orders for take profit and stop loss triggers on each update.

Next Steps

Real-Time Trading

Learn how to place trades with live market data

Market Data

Access historical data and price charts

Build docs developers (and LLMs) love