Close All Open Positions
Overview
When a trader chooses to "Close all open positions," they are issuing an order to their broker to exit all existing trades in their portfolio at the current market prices. This action is a convenient way to liquidate multiple positions swiftly, effectively "cleaning the slate" of open trades. It ensures that all open positions are immediately closed, allowing the trader to realize their gains or losses as of that moment. However, it's important to note that, like market orders, the final execution prices may slightly differ from the values at the time of issuing the order due to market fluctuations.
How to close all open positions
In this article you will learn how to close all open positions using the orders manager. Before you can close all open positions, you need to follow these steps:
-
Login (see the tutorial here)
-
Create an orders manager.
-
Create a request builder.
-
Close all open positions.
-
Create a listener function that handles the success or failure of the closing action.
-
Login (see the tutorial here)
-
Create an orders manager.
-
Create a request builder.
-
Close all open positions.
-
Create a listener function that handles the success or failure of the closing action.
-
Login (see the tutorial here)
-
Create an orders manager.
-
Create a request builder.
-
Close all open positions.
-
Create a listener function that handles the success or failure of the closing action.
-
Update the html to include our new JavaScript files.
Step 1: Login
Follow the steps in the login tutorial here
Step 2: Create an Orders Manager
let ordersManager = session.getOrdersManager();
let ordersManager = session.getOrdersManager();
In our index.js file we need to add a method closeAllOpenPositions which as the name states, we call to close all the positions.
In this method we declare three managers instrumentsManager, ordersManager, and openPositionsManager.
const sessionFactory = FXConnectLite.FXConnectLiteSessionFactory
const LoginError = FXConnectLite.LoginError
const LoggerFactory = FXConnectLite.LoggerFactory
document.addEventListener('DOMContentLoaded', () => {
let session = sessionFactory.create('LoginSample');
session.setLogger(LoggerFactory.createLogger(LoggerFactory.LEVEL_DEBUG));
session.subscribeConnectionStatusChange(new ConnectionStatusChangeListener(session));
let callback = closeAllOpenPositions;
bindConnectionRelatedEvents(session, () => callback(session));
});
async function closeAllOpenPositions(session) {
let instrumentsManager = session.getInstrumentsManager();
await loadManager(instrumentsManager);
let ordersManager = session.getOrdersManager();
await loadManager(ordersManager);
let openPositionsManager = session.getOpenPositionsManager();
await loadManager(openPositionsManager);
await loadManager(session.getOffersManager());
await loadManager(session.getAccountCommissionsManager());
let positionWorker = new PositionWorker(instrumentsManager, ordersManager);
let positions = openPositionsManager.getOpenPositionsSnapshot();
positionWorker.showPositions(positions);
let position = positions[0];
if (position) {
positionWorker.closeAll(position);
await wait(5000);
await loadManager(openPositionsManager);
positions = openPositionsManager.getOpenPositionsSnapshot();
positionWorker.showPositions(positions);
}
}
Step 3: Create a Request builder
A request builder is an object that defines the parameters of the closing action.
You can create a requestBuilder using the orders manager's getRequestFactory() method and passing it the createCloseAllPositionsRequestBuilder() method.
requestBuilder
let requestBuilder: FXConnectLite.CloseAllPositionsRequestBuilder = ordersManager.getRequestFactory().createCloseAllPositionsRequestBuilder();
requestBuilder.setCustomId("CloseOpenPositions#1")
.setAcctId(options.account)
.setTimeInForce("GTC");
let requestBuilder = ordersManager.getRequestFactory()
.createCloseAllPositionsRequestBuilder();
requestBuilder.setCustomId("CloseOpenPositions#1")
.setAcctId(options.account)
.setTimeInForce("GTC");
Here we need to create a worker class positions\position-worker.js which will assist us in passing information to be printed to the class that handles displaying information and it also handles forumlating the requests to close the positions.
class PositionWorker {
constructor(instrumentsManager, ordersManager) {
this.instrumentsManager = instrumentsManager;
this.ordersManager = ordersManager;
this.tableBuilder = new PositionTableBuilder();
}
#getSymbol(position) {
let offerId = position.offerId;
let instrument = this.instrumentsManager.getInstrumentByOfferId(offerId);
return instrument.symbol;
}
closeAll(position) {
let accountId = position.accountId;
let direction = position.buySell;
let symbol = this.#getSymbol(position);
let requestFactory = this.ordersManager.getRequestFactory();
let request = requestFactory.createCloseAllPositionsRequestBuilder()
.setAcctId(accountId)
.setSide(direction)
.setSymbol(symbol)
.build();
this.ordersManager.closeAllPositions(request);
}
showPositionDetails(position) {
this.tableBuilder.renderPositionDetailsSubtable(position);
}
showPositions(positions) {
this.tableBuilder.renderPositionTable(positions, this);
}
}
By default, the requestBuilder will close all open positions.
If you want to close only specific positions, you can add filters to the requestBuilder by calling one or both of these methods:
-
setSymbol(): This method takes an instrument symbol as an argument and closes only the positions for that instrument. -
setSide(): This method takes a direction (buy or sell) as an argument and closes only the positions in that direction.
Below, this code when added to the requestBuilder will close all buy positions for EUR/USD:
Add information to the requestBuilder
requestBuilder.setSide("B");
requestBuilder.setSymbol("EUR/USD");
requestBuilder.setSide("B");
requestBuilder.setSymbol("EUR/USD");
In the closeAll method of the worker class, we have the requestBuilder. Here is where we can specify which accountID, direction (Buy or Sell) and/or symbol that we want to close the positions for.
closeAll(position) {
let accountId = position.accountId;
let direction = position.buySell;
let symbol = this.#getSymbol(position);
let requestFactory = this.ordersManager.getRequestFactory();
let request = requestFactory.createCloseAllPositionsRequestBuilder()
.setAcctId(accountId)
.setSide(direction)
.setSymbol(symbol)
.build();
this.ordersManager.closeAllPositions(request);
}
position/position-table-builder
class PositionTableBuilder {
constructor() {
this.builder = new TableBuilder();
}
#getPositionDetails(position) {
return new Map([
[ 'Account ID', position.getAccountId() ],
[ 'Account Kind', position.getAccountKind() ],
[ 'Offer ID', position.getOfferId() ],
[ 'Open Time', position.getOpenTime() ],
[ 'Open Quote ID', position.getOpenQuoteId() ],
[ 'Open Order ID', position.getOpenOrderId() ],
[ 'Open Order Request ID', position.getOpenOrderReqId().substring(0, 25) + '...' ],
[ 'Open Order Request TXT', position.getOpenOrderRequestTXT() ],
[ 'Commission', position.getCommission() ],
[ 'Rollover Interest', position.getRolloverInterest() ],
[ 'Trade ID Origin', position.getTradeIdOrigin() ],
[ 'Value Date', position.getValueDate() ],
[ 'Parties', position.getParties() ],
[ 'P/L', position.getPL() ],
[ 'P/L Pips', position.getPLPips() ],
[ 'Gross P/L', position.getGrossPL() ],
[ 'Close Rate', position.getCloseRate() ],
[ 'Stop Rate', position.getStopRate() ],
[ 'Limit Rate', position.getLimitRate() ],
[ 'Used Margin', position.getUsedMargin() ]
]);
}
#onPositionClick(position, positionWorker) {
let callback = function() {
positionWorker.showPositionDetails(position);
};
this.builder.onRowClick(position.getTradeID(), callback);
}
#renderDataTableRow(position, positionWorker) {
let columns = [
{ className: 'col-sm-3', value: position.getTradeID() },
{ className: 'col-sm-3', value: position.getAccountName() },
{ className: 'col-sm-2', value: position.getBuySell() },
{ className: 'col-sm-2', value: position.getOpenRate() },
{ className: 'col-sm-2', value: position.getAmount() }
];
let row = this.builder.createDataTableRow(columns);
row.onclick = () => this.#onPositionClick(position, positionWorker);
}
#renderNoPositionsMessage() {
let columns = [
{ className: 'col-sm-12', value: 'No Positions' }
];
this.builder.createDataTableRow(columns);
}
#renderPositionTableHeader() {
let columns = [
{ className: 'col-sm-3', value: 'ID' },
{ className: 'col-sm-3', value: 'Account Name' },
{ className: 'col-sm-2', value: 'B/S' },
{ className: 'col-sm-2', value: 'Rate' },
{ className: 'col-sm-2', value: 'Amount' },
];
this.builder.createHeaderTableRow(columns);
}
renderPositionDetailsSubtable(position) {
let details = this.#getPositionDetails(position);
let columns = this.builder.createDataSubtableColumns(details);
let detailsRow = this.builder.createDataSubtable(position.getTradeID(), columns, 'row mb-3 details');
detailsRow.onclick = () => this.builder.removeSubtable();
}
renderPositionTable(positions, positionWorker) {
this.#renderPositionTableHeader();
if (positions.length === 0) {
this.#renderNoPositionsMessage();
} else {
for (let position of positions)
this.#renderDataTableRow(position, positionWorker);
}
this.builder.showContainer();
}
}
For printing the results of the command, we have first created a file which will contain our TableBuilder class.
Follow the instruction in the Table Builder tutorial here.
common/common.js
class DataManagerStateChangeListener {
constructor(manager, resolve, reject) {
this.manager = manager;
this.reject = reject;
this.resolve = resolve;
}
onStateChange(state) {
if (state.isLoaded()) {
this.manager.unsubscribeStateChange(this);
this.resolve(this.manager);
}
if (state.hasError()) {
this.manager.unsubscribeStateChange(this);
this.reject(state.getError());
}
}
}
function loadManager(manager) {
return new Promise((resolve, reject) => {
let listener = new DataManagerStateChangeListener(manager, resolve, reject);
manager.subscribeStateChange(listener);
manager.refresh();
});
}
async function wait(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
For example, this code will close all buy positions for EUR/USD.
See also getRequestFactory, createCloseAllPositionsRequestBuilder, closeAllPositionsRequestBuilder.
Step 4: Close all open positions
Then call the function
ordersManager.closeAllPositions(requestBuilder.build());
ordersManager.closeAllPositions(requestBuilder.build());
In the same method of our worker class, we call the closeAllpositionsRequestBuilder method to close all the positions that match the conditions.
closeAll(position) {
let accountId = position.accountId;
let direction = position.buySell;
let symbol = this.#getSymbol(position);
let requestFactory = this.ordersManager.getRequestFactory();
let request = requestFactory.createCloseAllPositionsRequestBuilder()
.setAcctId(accountId)
.setSide(direction)
.setSymbol(symbol)
.build();
this.ordersManager.closeAllPositions(request);
}
See also IOrdersManager, IOpenPositionsManager, closeAllPositions.
Step 5: Create a listener function
A listener function is a class that implements the ICloseAllPositionsCallback interface.
It has two methods: onClosed() and onError().
-
The
onClosed()method is called when a position is successfully closed. -
The
onError()method is called when there is an error in closing a position.
The listener function is called when the closing action is completed. It takes two parameters:
-
list of closed positions.
-
a list of errors.
If there are no errors, the second parameter is empty.
If there are errors, the function onError() is called for each error.
openPositionChangeListener
class OpenPositionChangeListener implements FXConnectLite.IOpenPositionChangeListener {
private openPositionsManager: FXConnectLite.IOpenPositionsManager;
constructor(openPositionsManager: FXConnectLite.IOpenPositionsManager) {
this.openPositionsManager = openPositionsManager;
}
onChange(openPositionInfo: FXConnectLite.OpenPositionInfo): void {
Printer.print(`OpenPosition ${openPositionInfo.getId()} is changed.`)
OpenPositionPrinter.print(this.openPositionsManager.getOpenPosition(openPositionInfo.getId()));
}
onAdd(openPositionInfo: FXConnectLite.OpenPositionInfo): void {
Printer.print(`OpenPosition ${openPositionInfo.getId()} is added.`)
OpenPositionPrinter.print(this.openPositionsManager.getOpenPosition(openPositionInfo.getId()));
}
onDelete(openPositionInfo: FXConnectLite.OpenPositionInfo): void {
Printer.print(`OpenPosition ${openPositionInfo.getId()} is deleted.`)
}
onRefresh(): void {
Printer.print(`Open positions refreshed`)
OpenPositionPrinter.printAll(this.openPositionsManager.getOpenPositionsSnapshot());
}
}
class OpenPositionChangeListener {
constructor(openPositionsManager) {
this.openPositionsManager = openPositionsManager
}
onChange(openPositionInfo) {
Printer.print(`OpenPosition ${openPositionInfo.getId()} is changed.`)
OpenPositionPrinter.print(
this.openPositionsManager.getOpenPosition(openPositionInfo.getId())
)
}
onAdd(openPositionInfo) {
Printer.print(`OpenPosition ${openPositionInfo.getId()} is added.`)
OpenPositionPrinter.print(
this.openPositionsManager.getOpenPosition(openPositionInfo.getId())
)
}
onDelete(openPositionInfo) {
Printer.print(`OpenPosition ${openPositionInfo.getId()} is deleted.`)
}
onRefresh() {
Printer.print(`Open positions refreshed`)
OpenPositionPrinter.printAll(
this.openPositionsManager.getOpenPositionsSnapshot()
)
}
}
In this sample we have not created a listener as the processing of this sample simply takes the parameters from the first open position and then closes all positions that match these parameters.
Now we can use this class:
Use openPositionChangeListener
let openPositionChangeListener = new OpenPositionChangeListener(openPositionsManager);
let openPositionChangeListener = new OpenPositionChangeListener(openPositionsManager);
In this sample we have not created a listener, however you can do so in order to re-list your open positions when some are closed.
Step 6: Update the html to include our new JavaScript files.
In the head of your HTML, you need to add this snippet. If you are using the login sample code or writing it from scratch, then you should have already added all the common scripts. You will need to add only these ones.
<!-- The script below are belong to this particular sample. Make sure they aren't copied from another samples. -->
<script src="connection_management/connection-management.js"></script>
<script src="connection_management/connection-status-change-listener.js"></script>
<script src="connection_management/login-callback.js"></script>
<script src="positions/position-worker.js"></script>
<script src="positions/position-table-builder.js"></script>
<script src="common/table-builder.js"></script>
<script src="common/common.js"></script>
<script src="index.js"></script>
When all positions are closed, you can:
Conclusion
You have learned how to close all open positions using the orders manager. Closing all open positions means you will exit the market and liquidate your assets. Before you can close all open positions, you need to create an orders manager, a request builder, and a listener function that handles the success or failure of the closing action. You have also learned how to create a request builder using the orders manager's getRequestFactory() method and passing it the createCloseAllPositionsRequestBuilder() method. By default, the request builder will close all open positions, but you can add filters to close only specific positions by calling the setSymbol() or setSide() methods. You can now use this knowledge to manage your open positions on the platform.
Download the sample Node TypeScript, Node JavaScript, JavaScript.
| Table of Contents |
|---|
| Get Open Positions The article teaches how to get a list of open positions. |
| Get Closed Positions The article teaches how to get a list of closed positions. |
| Get Position Details API Command used to get the details of a position |
| Close a Position API Command used to close a position |
| Close All Open Positions API Command used to close all open positions |