Skip to content

Refresh Account Profile Data

Overview

The article teaches how to refresh an account's profile data. The idea behind this functionality is that when some settings are changed on the server, it sends a flag to the client indicating what data needs to be refreshed. This method returns a set of values that define which managers in FCLite need to execute the refresh() method to download the updated data from the server.

How to Refresh Profiles of Account

In this article you will learn how to use the FCLite API to refresh profiles of an account. To get the refresh profile flags of an account, you can use the getRefreshProfileFlags() method. Below, is an example that shows how to process refresh profile flags:

  1. Login (see the tutorial here)

  2. Create instance of the instruments manager.

  1. Login (see the tutorial here)

  2. Create instance of the instruments manager.

  3. Create an account listener to listen for changes

  4. The main JavaScript file.

  1. Login (see the tutorial here)

  2. Create instance of the accounts manager.

  3. Create an account listener to listen for changes

  4. Printing the results in a readable format.

  5. Updating the html to include our new JavaScript files.

  6. The main JavaScript file.

Step 1: Login

Follow the steps in the login tutorial here

Step 2: Create instance of the instruments manager

public static processAccountRefreshProfileFlags(account: FXConnectLite.Account): void {
    let  refreshProfileFlags = account.getRefreshProfileFlags();
    if (refreshProfileFlags) {
        Printer.print(`{RefreshProfileFlags is ${refreshProfileFlags}}`)
        const  aFlags = Array.from(refreshProfileFlags);
        aFlags.forEach(function (flag) {
            switch(flag ) { 
                case 'A':
                case 'a':
                case 'B':
                case 'b':
                case 'P':
                    Printer.print(`AccountCommissionsManager refresh`)
                    Application.session.getAccountCommissionsManager().refresh();
                    break; 

                case 'L':
                case 'l':
                case 'M':
                case 'm':
                    Printer.print(`LeverageProfilesManager refresh`)
                    Application.session.getLeverageProfilesManager().refresh();
                    break; 

                case 'R':
                case 'r':
                case 'Y':
                    Printer.print(`RolloverProfilesManager refresh`)
                    Application.session.getRolloverProfilesManager().refresh();
                    break; 

                case 'X':
                    Printer.print(`AccountCommissionsManager LeverageProfilesManager refresh`)
                    Application.session.getAccountCommissionsManager().refresh();
                    Application.session.getLeverageProfilesManager().refresh();
                    break; 
            }
        }); 
    } 
    else {
        Printer.print(`RefreshProfileFlags is empty`)
    }
}

accounts/account-worker

import { loadManager } from '../common/common.js';


class AccountWorker {
    constructor(session, accountsManager) {
        this.accountsManager = accountsManager;
        this.session = session;
    }


    async #refreshAccountCommissionsManager() {
        let accountCommissionsManager = this.session.getAccountCommissionsManager();
        await loadManager(accountCommissionsManager);
    }


    async #refreshLeverageProfilesManager() {
        let leverageProfilesManager = this.session.getLeverageProfilesManager();
        await loadManager(leverageProfilesManager);
    }


    async #refreshRolloverProfilesManager() {
        let rolloverProfilesManager = this.session.getRolloverProfilesManager()
        await loadManager(rolloverProfilesManager);
    }


    async processAccountRefreshProfileFlags(account) {
        let refreshProfileFlags = account.getRefreshProfileFlags();
        if (refreshProfileFlags === '')
            return;

        await refreshProfileFlags.forEach(async (flag) => {
            switch (flag.toLower()) {
                case 'a':
                case 'b':
                case 'p': 
                    await this.#refreshAccountCommissionsManager();
                    break;
                case 'l':
                case 'm': 
                    await this.#refreshLeverageProfilesManager();
                    break;
                case 'r':
                case 'y':
                    await this.#refreshRolloverProfilesManager();
                    break;
                case 'x':
                    await this.#refreshAccountCommissionsManager();
                    await this.#refreshLeverageProfilesManager();
                    break;
            }
        });
    }

    showAccountDetails(account) {
        let accountDetails = `
        AccountId = ${account.getAccountId()}
        AccountName = ${account.getAccountName()}
        AccountKind = ${account.getAccountKind()}
        Base currency = ${account.getBaseCurrency()}
        Base currency precision = ${account.getBaseCurrencyPrecision()}
        ATPId = ${account.getATPId()}
        Balance = ${account.getBalance()}
        BaseUnitSize = ${account.getBaseUnitSize()}
        DayPL = ${account.getDayPL()}
        Equity = ${account.getEquity()}
        GrossPL = ${account.getGrossPL()}
        LastMarginCallDate = ${account.getLastMarginCallDate()}
        LeverageProfileId = ${account.getLeverageProfileId()}
        M2MEquity = ${account.getM2MEquity()}
        MaintenanceFlag = ${account.getMaintenanceFlag()}
        MaintenanceType = ${account.getMaintenanceType()}
        ManagerAccountId = ${account.getManagerAccountId()}
        MarginCallFlag = ${account.getMarginCallFlag()}
        NonTradeEquity = ${account.getNonTradeEquity()}
        OrderAmountLimit = ${account.getOrderAmountLimit()}
        UsableMaintenanceMargin = ${account.getUsableMaintenanceMargin()}
        UsableMaintenanceMarginPercentage = ${account.getUsableMaintenanceMarginPercentage()}
        UsableMargin = ${account.getUsableMargin()}
        UsableMarginPercentage = ${account.getUsableMarginPercentage()}
        UsedMaintenanceMargin = ${account.getUsedMaintenanceMargin()}
        UsedMargin = ${account.getUsedMargin()}
        `;

        console.log('Account details:');
        console.log(accountDetails);
    }


    showAccounts() {
        let accountsInfo = this.accountsManager.getAccountsInfo();

        accountsInfo.forEach((account) => {
            let message = `
            ID = ${account.id}
            Name = ${account.name}
            Type = ${account.type}

            `;

            console.log(message);
        });
    }
}


export default AccountWorker;

Step 3: Create an account listener to listen for changes or additions, which will call two other classes when changes are received from the server

accounts/account-change listener

class AccountChangeListener {
    constructor(accountsManager, accountWorker) {
        this.accountsManager = accountsManager;
        this.accountWorker = accountWorker;
    }

    onChange(accountInfo) {
        let callback = new GetAccountCallback(this.accountWorker);
        this.accountsManager.getAccount(accountInfo, callback);
    }

    onAdd(accountInfo) {
        let callback = new GetAccountCallback(this.accountWorker);
        this.accountsManager.getAccount(accountInfo, callback);
    }

    onDelete(accountInfo) {
        // do nothing
    }

    onRefresh() {
        let callback = new GetAccountsSnapshotCallback(this.accountWorker);
        this.accountsManager.getAccountsSnapshot(callback);
    }
}
accounts\get-account-callback.js This first class is used when the listener received info from the server about changes or items added to the users account. It first creates an instance of the class and will use it as a callback, which means, that the data returned from the server async will be passed directly into this class. As you can see in the GetAccountCallback class, the system looks for a method named onAccountReceived and calls it with the account details from the server. This method then uses the account Worker to refresh the details of the account on the page.
class GetAccountCallback {
    constructor(accountWorker) {
        this.accountWorker = accountWorker;
    }

    async onAccountReceived(account) {
        this.accountWorker.showAccountDetails(account);
        await this.accountWorker.processAccountRefreshProfileFlags(account);
    }
}
and accounts\get-accounts-snapshot-callback.js This second class works the same as the first, except that it cycles through an array of accounts that are returned.
class GetAccountsSnapshotCallback {
    constructor(accountWorker) {
        this.accountWorker = accountWorker;
    }

    async onAccountsReceived(accounts) {
        await accounts.forEach(async (account) => {
            await this.accountWorker.processAccountRefreshProfileFlags(account);
        });

        this.accountWorker.showAccounts(accounts);
    }
}

Step 4: The main JavaScript file.

index.js

import process from 'node:process';
import { FXConnectLiteSessionFactory } from '@gehtsoft/forex-connect-lite-node';
import { login, logout } from './connection_management/connection-management.js';
import { AccountChangeListener, AccountWorker } from './accounts/accounts.js';

async function accountRefreshProfileFlags(session) {    
    let accountsManager = session.getAccountsManager();

    let accountWorker = new AccountWorker(session, accountsManager);
    let accountChangeListener = new AccountChangeListener(accountsManager, accountWorker);
    accountsManager.subscribeAccountChange(accountChangeListener);

    accountWorker.showAccounts();
}

try {
    let session = FXConnectLiteSessionFactory.create('RefreshAccountProfileDataSample');
    await login(session, process.env.API_USER_NAME, process.env.API_PASSWORD, process.env.TRADING_SYSTEM_URL, process.env.CONNECTION_NAME);

    await accountRefreshProfileFlags(session);

    await logout(session);
    process.exit(0);
} catch (ex) {
    console.log(ex);
    process.exit(1);
}

In our main index file index.js we have a method accountRefreshProfileFlags in which we create our accounts manager

async function accountRefreshProfileFlags(session) {    
    let accountsManager = session.getAccountsManager();

    let accountWorker = new AccountWorker(session, accountsManager);
    let accountChangeListener = new AccountChangeListener(accountsManager, accountWorker);
    accountsManager.subscribeAccountChange(accountChangeListener);

    accountWorker.showAccounts();
}

Step 3: Create an account listener to listen for changes

In order to listen for changes to the account, we need to create a listener accounts\account-change-listener.js This listener uses the next two classes as you can see.

class AccountChangeListener {
    constructor(accountsManager, accountWorker) {
        this.accountsManager = accountsManager;
        this.accountWorker = accountWorker;
    }

    onChange(accountInfo) {
        let callback = new GetAccountCallback(this.accountWorker);
        this.accountsManager.getAccount(accountInfo, callback);
    }

    onAdd(accountInfo) {
        let callback = new GetAccountCallback(this.accountWorker);
        this.accountsManager.getAccount(accountInfo, callback);
    }

    onDelete(accountInfo) {
        // do nothing
    }

    onRefresh() {
        let callback = new GetAccountsSnapshotCallback(this.accountWorker);
        this.accountsManager.getAccountsSnapshot(callback);
    }
}
We also need to add some callback classes accounts\get-account-callback.js This first class is used when the listener received info from the server about changes or items added to the users account. It first creates an instance of the class and will use it as a callback, which means, that the data returned from the server will be passed directly into this class. As you can see in the GetAccountCallback class, the system looks for a method named onAccountReceived() and calls it with the account details from the server. If it is not found, then it uses the default one that is inside the API. This method then uses the accountWorker to refresh the details of the account on the page.
class GetAccountCallback {
    constructor(accountWorker) {
        this.accountWorker = accountWorker;
    }

    async onAccountReceived(account) {
        this.accountWorker.showAccountDetails(account);
        await this.accountWorker.processAccountRefreshProfileFlags(account);
    }
}
and accounts\get-accounts-snapshot-callback.js This second class works the same as the first, except that it cycles through an array of accounts that are returned.
class GetAccountsSnapshotCallback {
    constructor(accountWorker) {
        this.accountWorker = accountWorker;
    }

    async onAccountsReceived(accounts) {
        await accounts.forEach(async (account) => {
            await this.accountWorker.processAccountRefreshProfileFlags(account);
        });

        this.accountWorker.showAccounts(accounts);
    }
} 

Step 4: Printing the results in a readable format.

The first thing that we do is to create a worker accounts\account-worker.js that will pass the results of our queries to the printing classes.

class AccountWorker {
    constructor(session, accountsManager) {
        this.accountsManager = accountsManager;
        this.session = session;

        this.tableBuilder = new AccountTableBuilder();
    }

    async #refreshAccountCommissionsManager() {
        let accountCommissionsManager = this.session.getAccountCommissionsManager();
        await loadManager(accountCommissionsManager);
    }

    async #refreshLeverageProfilesManager() {
        let leverageProfilesManager = this.session.getLeverageProfilesManager();
        await loadManager(leverageProfilesManager);
    }

    async #refreshRolloverProfilesManager() {
        let rolloverProfilesManager = this.session.getRolloverProfilesManager()
        await loadManager(rolloverProfilesManager);
    }

    async processAccountRefreshProfileFlags(account) {
        let refreshProfileFlags = account.getRefreshProfileFlags();
        if (refreshProfileFlags === '')
            return;

        await refreshProfileFlags.forEach(async (flag) => {
            switch (flag.toLower()) {
                case 'a':
                case 'b':
                case 'p': 
                    await this.#refreshAccountCommissionsManager();
                    break;
                case 'l':
                case 'm': 
                    await this.#refreshLeverageProfilesManager();
                    break;
                case 'r':
                case 'y':
                    await this.#refreshRolloverProfilesManager();
                    break;
                case 'x':
                    await this.#refreshAccountCommissionsManager();
                    await this.#refreshLeverageProfilesManager();
                    break;
            }
        });
    }

   showAccountDetails(account) {
        this.tableBuilder.renderAccountDetailsSubtable(account);
   }

   showAccounts() {
        let accountsInfo = this.accountsManager.getAccountsInfo();
        this.tableBuilder.renderAccountTable(this.accountsManager, this, accountsInfo);
    }
} 

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.

Then we have the accounts table builder class accounts\account-table-builder.js that connects the main table builder to our workers results.

class AccountTableBuilder {
    constructor() {
        this.builder = new TableBuilder();
    }

    #getAccountDetails(account) {
        return new Map([
            ['Balance', account.getBalance()],
            ['Base currency', account.getBaseCurrency()],
            ['Order amount limit', account.getOrderAmountLimit()],
            ['ATP ID', account.getATPId()],
            ['Size of one lot', account.getBaseUnitSize()],
            ['Last occurrence of a Margin Call', account.getLastMarginCallDate()],
            ['ID of an account leverage profile', account.getLeverageProfileId()],
            ['Equity balance at the beginning of the trading day', account.getM2MEquity()],
            ['Rollover maintenance flag', account.getMaintenanceFlag()],
            ['Type of position maintenance', account.getMaintenanceType()],
            ['ID of the funds manager account', account.getManagerAccountId()],
            ['The limitation state of the account', account.getMarginCallFlag()],
            ['The amount of transactions during the day', account.getNonTradeEquity()]
        ]);
    }

    #onAccountClick(id, accountManager, accountWorker) {
        let callback = function () {
            accountManager.getAccount({
                getId: function () {
                    return id;
                }
            }, new GetAccountCallback(accountWorker));
        };

        this.builder.onRowClick(id, callback);
    }

    #renderAccountTableHeader() {
        let columns = [
            { className: 'col-sm-2', value: 'ID' },
            { className: 'col-sm-5', value: 'Name' },
            { className: 'col-sm-5', value: 'Type' }
        ];

        this.builder.createHeaderTableRow(columns);
    }

    #renderDataTableRow(accountsManager, accountWorker, accountInfo) {
        let columns = [
            { className: 'col-sm-2', value: accountInfo.id },
            { className: 'col-sm-5', value: accountInfo.name },
            { className: 'col-sm-5', value: accountInfo.type }
        ];

        let row = this.builder.createDataTableRow(columns);
        row.onclick = () => this.#onAccountClick(accountInfo.id, accountsManager, accountWorker);
    }

    renderAccountDetailsSubtable(account) {
        let details = this.#getAccountDetails(account);
        let columns = this.builder.createDataSubtableColumns(details);

        let detailsRow = this.builder.createDataSubtable(account.getAccountId(), columns, 'row mb-3 details');
        detailsRow.onclick = () => this.builder.removeSubtable();
    }

    renderAccountTable(accountsManager, accountWorker, accountsInfo) {
        this.#renderAccountTableHeader();

        accountsInfo.forEach((accountInfo) => {
            this.#renderDataTableRow(accountsManager, accountWorker, accountInfo);
        });

        this.builder.showContainer();
    }
}

Step 5: Updating the main html file index.html to include our new JavaScript files.

Our main index.html file as from the login example, we add these scripts that we have just created.

<script src="accounts/account-change-listener.js"></script>
<script src="accounts/account-table-builder.js"></script>
<script src="accounts/account-worker.js"></script>
<script src="accounts/get-account-callback.js"></script>
<script src="accounts/get-accounts-snapshot-callback.js"></script>
<script src="common/table-builder.js"></script>
<script src="index.js"></script>

Step 6: The main JavaScript file.

Our main js file index.js

async function accountRefreshProfileFlags(session) {
    let accountsManager = session.getAccountsManager();

    let accountWorker = new AccountWorker(session, accountsManager);
    let accountChangeListener = new AccountChangeListener(accountsManager, accountWorker);
    accountsManager.subscribeAccountChange(accountChangeListener);

    accountWorker.showAccounts();
}

document.addEventListener('DOMContentLoaded', () => {
    let logLevel = FXConnectLite.LoggerFactory.LEVEL_DEBUG;
    let logger = FXConnectLite.LoggerFactory.createLogger(logLevel);

    let session = FXConnectLite.FXConnectLiteSessionFactory.create('RefreshAccountProfileDataSample');
    session.setLogger(logger);

    let callback = accountRefreshProfileFlags;
    let connectionStatusChangeListener = new ConnectionStatusChangeListener(session, callback);
    session.subscribeConnectionStatusChange(connectionStatusChangeListener);

    bindConnectionRelatedEvents(session, () => callback(session));
});

In this example, we first get the refresh profile flags of an account using the getRefreshProfileFlags method.
Then, we iterate over each flag and use a switch statement to determine which manager needs to execute the refresh() method. For example, if the flag is 'A', 'a', 'B', 'b', or 'P', we call the refresh() method on the AccountCommissionsManager. This will download the updated data from the server for that manager.

When account profile data is refreshed, you can:

  1. Get available instruments.
  2. Subscribe and Unsubscribe to instruments.
  3. Get price updates for an instrument.
  4. Get historical prices for an instrument.
  5. Create a market order.
  6. Create an entry order.

Conclusion

You have learned how to use the FCLite API to refresh profiles of an account. When some settings are changed on the server, it sends a flag to the client indicating what data needs to be refreshed. You can use the getRefreshProfileFlags() method to get the refresh profile flags of an account, which define which managers in FCLite need to execute the refresh() method to download the updated data from the server. By following the example provided, you can learn how to process refresh profile flags and ensure that your data is up-to-date.

Download the sample Node TypeScript, Node JavaScript, JavaScript.

Table of Contents
Accounts
API Commands used to get account history information
Get All Accounts
The article teaches how to get a list of all accounts.
Refresh Account Profile Data
The article teaches how to refresh an accounts profile data.