or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

account.mdcore.mdindex.mdorder.mdposition.mdpricing.mdtrade.mdtransaction.mduser.md
tile.json

position.mddocs/

Position Management

Position tracking and management operations for viewing all positions by instrument, listing open positions, retrieving position details with separate long/short side information, and closing positions.

All position operations are accessed via ctx.position where ctx is a Context instance.

Capabilities

List Positions

Get a list of all Positions for an Account.

/**
 * Get list of all Positions for Account
 * @param accountID - Account identifier
 * @param responseHandler - Callback receiving Response object
 * Response body contains: { positions: Position[], lastTransactionID: string }
 */
list(accountID, responseHandler);

Usage Example:

ctx.position.list('001-001-1234567-001', response => {
  if (response.isSuccess()) {
    response.body.positions.forEach(position => {
      console.log(`${position.instrument}:`);
      console.log(`  Long: ${position.long.units} units, P/L: ${position.long.pl}`);
      console.log(`  Short: ${position.short.units} units, P/L: ${position.short.pl}`);
      console.log(`  Total Unrealized P/L: ${position.unrealizedPL}`);
    });
  }
});

List Open Positions

Get a list of all open Positions for an Account (positions with non-zero units).

/**
 * Get list of open Positions
 * @param accountID - Account identifier
 * @param responseHandler - Callback receiving Response object
 * Response body contains: { positions: Position[], lastTransactionID: string }
 */
listOpen(accountID, responseHandler);

Usage Example:

ctx.position.listOpen('001-001-1234567-001', response => {
  if (response.isSuccess()) {
    const positions = response.body.positions;
    console.log(`${positions.length} open positions`);
    positions.forEach(position => {
      const longUnits = parseFloat(position.long.units);
      const shortUnits = parseFloat(position.short.units);
      const netUnits = longUnits + shortUnits;

      console.log(`${position.instrument}: ${netUnits} units (${netUnits > 0 ? 'LONG' : 'SHORT'})`);
      console.log(`  Unrealized P/L: ${position.unrealizedPL}`);
      console.log(`  Margin Used: ${position.marginUsed}`);
    });
  }
});

Get Position Details

Get the details of a single Position for a specific instrument.

/**
 * Get details of specific Position
 * @param accountID - Account identifier
 * @param instrument - Instrument name (e.g., "EUR_USD")
 * @param responseHandler - Callback receiving Response object
 * Response body contains: { position: Position, lastTransactionID: string }
 */
get(accountID, instrument, responseHandler);

Usage Example:

ctx.position.get('001-001-1234567-001', 'EUR_USD', response => {
  if (response.isSuccess()) {
    const position = response.body.position;

    console.log(`Position for ${position.instrument}:`);

    if (parseFloat(position.long.units) !== 0) {
      console.log('Long Side:');
      console.log(`  Units: ${position.long.units}`);
      console.log(`  Average Price: ${position.long.averagePrice}`);
      console.log(`  Unrealized P/L: ${position.long.unrealizedPL}`);
      console.log(`  Trade IDs: ${position.long.tradeIDs.join(', ')}`);
    }

    if (parseFloat(position.short.units) !== 0) {
      console.log('Short Side:');
      console.log(`  Units: ${position.short.units}`);
      console.log(`  Average Price: ${position.short.averagePrice}`);
      console.log(`  Unrealized P/L: ${position.short.unrealizedPL}`);
      console.log(`  Trade IDs: ${position.short.tradeIDs.join(', ')}`);
    }

    console.log(`Total Unrealized P/L: ${position.unrealizedPL}`);
    console.log(`Margin Used: ${position.marginUsed}`);
  }
});

Close Position

Close a Position by closing all open Trades for the specified instrument.

/**
 * Close a Position
 * @param accountID - Account identifier
 * @param instrument - Instrument name (e.g., "EUR_USD")
 * @param bodyParams - Body parameters object
 *   - longUnits: string (units to close on long side, "ALL" or "NONE", optional)
 *   - longClientExtensions: ClientExtensions (optional)
 *   - shortUnits: string (units to close on short side, "ALL" or "NONE", optional)
 *   - shortClientExtensions: ClientExtensions (optional)
 * @param responseHandler - Callback receiving Response object
 * Response body contains: {
 *   longOrderCreateTransaction?: MarketOrderTransaction,
 *   longOrderFillTransaction?: OrderFillTransaction,
 *   longOrderCancelTransaction?: OrderCancelTransaction,
 *   shortOrderCreateTransaction?: MarketOrderTransaction,
 *   shortOrderFillTransaction?: OrderFillTransaction,
 *   shortOrderCancelTransaction?: OrderCancelTransaction,
 *   relatedTransactionIDs: string[],
 *   lastTransactionID: string
 * }
 */
close(accountID, instrument, bodyParams, responseHandler);

Usage Example:

// Close entire position (both long and short sides)
ctx.position.close('001-001-1234567-001', 'EUR_USD', {
  longUnits: 'ALL',
  shortUnits: 'ALL'
}, response => {
  if (response.isSuccess()) {
    console.log('Position closed');

    if (response.body.longOrderFillTransaction) {
      const longFill = response.body.longOrderFillTransaction;
      console.log(`Long side closed: ${longFill.units} units @ ${longFill.price}`);
      console.log(`  P/L: ${longFill.pl}`);
    }

    if (response.body.shortOrderFillTransaction) {
      const shortFill = response.body.shortOrderFillTransaction;
      console.log(`Short side closed: ${shortFill.units} units @ ${shortFill.price}`);
      console.log(`  P/L: ${shortFill.pl}`);
    }
  }
});

// Close only long side
ctx.position.close('001-001-1234567-001', 'EUR_USD', {
  longUnits: 'ALL',
  shortUnits: 'NONE'
}, response => {
  if (response.isSuccess()) {
    console.log('Long position closed');
  }
});

// Close only short side with client extensions
ctx.position.close('001-001-1234567-001', 'EUR_USD', {
  longUnits: 'NONE',
  shortUnits: 'ALL',
  shortClientExtensions: {
    comment: 'Closing short position'
  }
}, response => {
  if (response.isSuccess()) {
    console.log('Short position closed');
  }
});

Types

Position

Representation of a Position for a single instrument.

interface Position {
  // Identification
  instrument: string;

  // Financial summary over account lifetime
  pl: string;  // Total realized P/L
  resettablePL: string;
  financing: string;
  commission: string;
  guaranteedExecutionFees: string;

  // Current state
  unrealizedPL: string;
  marginUsed: string;

  // Long and short sides
  long: PositionSide;
  short: PositionSide;
}

PositionSide

One side (long or short) of a Position.

interface PositionSide {
  // Position details
  units: string;  // Number of units (0 if no position on this side)
  averagePrice?: string;  // Volume-weighted average price (if units != 0)

  // Trade references
  tradeIDs: string[];  // Trade IDs contributing to this position side

  // Financial summary
  pl: string;  // Total realized P/L for this side
  unrealizedPL: string;  // Current unrealized P/L
  resettablePL: string;
  financing: string;
  guaranteedExecutionFees: string;
}

CalculatedPositionState

Calculated price-dependent state of a Position.

interface CalculatedPositionState {
  instrument: string;
  netUnrealizedPL: string;
  longUnrealizedPL: string;
  shortUnrealizedPL: string;
  marginUsed: string;
}

Position Concepts

Long vs Short Positions

In OANDA's v20 API, positions are tracked separately for long and short sides:

  • Long Position: Positive units (buying the base currency)
  • Short Position: Negative units (selling the base currency)

An account can have simultaneous long and short positions in the same instrument (hedging).

Net Position

The net position is calculated as: long.units + short.units

  • If positive: Overall long position
  • If negative: Overall short position
  • If zero: No net position (positions may still exist on both sides if hedging)

Position Closeout

When closing a position, you can:

  • Close both sides simultaneously
  • Close only the long side
  • Close only the short side
  • Specify client extensions for tracking

Closing a position creates Market Orders for each side being closed, which immediately close all contributing trades on that side.