Skip to main content

JavaScript example of how to connect to server and place an order

var credentials = require('./credentials.json');
var payloadTypes = require('./payloadTypes.json');
var OAModel = require('./OAModel.json');
var fs = require('fs');
PROTO_HEARTBEAT_EVENT_PAYLOADTYPE = 51;
uid = (
(i) => () =>
'cm_id_' + i++
)(1);

// put two frequently needed credentials into variables
var { accountId: ctidTraderAccountId, accessToken } = credentials;

// initialize websocket
var ws = new WebSocket('wss://live.ctraderapi.com:5036'); // or 'demo.ctraderapi.com:5036'

// main function which is called after successful authentication
function main() {
console.log('ready to do something');

// request symbols list
var clientMsg = {
clientMsgId: uid(),
payloadType: payloadTypes.PROTO_OA_SYMBOLS_LIST_REQ,
payload: {
ctidTraderAccountId,
accessToken,
includeArchivedSymbols: false,
},
};
ws.send(JSON.stringify(clientMsg));

// place order
var clientMsg = {
clientMsgId: uid(),
payloadType: payloadTypes.PROTO_OA_NEW_ORDER_REQ,
payload: {
ctidTraderAccountId,
accessToken,
orderType: OAModel.ProtoOAOrderType.LIMIT,
tradeSide: OAModel.ProtoOATradeSide.BUY,
symbolId: 41, // XAUUSD
limitPrice: 2700.34,
volume: 100, // equals 0.01 lot
stopLoss: 2600.34,
takeProfit: 2750.34,
},
};
ws.send(JSON.stringify(clientMsg));
}

// main callback
function onResp(message) {
var { payloadType, payload } = message;

if (payloadType === payloadTypes.PROTO_OA_SYMBOLS_LIST_RES) {
var syms = payload.symbol;
fs.writeFileSync('syms.json', JSON.stringify(syms, null, 2));
console.log('got the symbol list and saved it as syms.json');
}

if (payloadType === payloadTypes.PROTO_OA_EXECUTION_EVENT) {
console.log('placed order successfully');
console.log('order id:', payload.order.orderId);
}
}

// setting up event listeners for the WebSocket instance

ws.onopen = function (e) {
console.log('connected');

// first thing after connecting is to request for app auth
var clientMsg = {
clientMsgId: uid(),
payloadType: payloadTypes.PROTO_OA_APPLICATION_AUTH_REQ,
payload: {
clientId: credentials.clientId,
clientSecret: credentials.clientSecret,
},
};
ws.send(JSON.stringify(clientMsg));
};

ws.onmessage = function (e) {
var serverMsg = JSON.parse(e.data);
var { payloadType } = serverMsg;

// apply custom logic on special server messages (i.e. auth results, errors, heartbeat events)

if (payloadType === payloadTypes.PROTO_OA_APPLICATION_AUTH_RES) {
console.log('app auth done');
// now must request for account auth
var clientMsg = {
clientMsgId: uid(),
payloadType: payloadTypes.PROTO_OA_ACCOUNT_AUTH_REQ,
payload: { ctidTraderAccountId, accessToken },
};
ws.send(JSON.stringify(clientMsg));
return;
}

if (payloadType === payloadTypes.PROTO_OA_ACCOUNT_AUTH_RES) {
console.log('account auth done');
// now everything is ready to do something
main();
return;
}

if (payloadType === payloadTypes.PROTO_OA_ERROR_RES) {
console.log('server sent error message', serverMsg.payload);
return;
}

if (payloadType === PROTO_HEARTBEAT_EVENT_PAYLOADTYPE) {
console.log('heartbeat event');
return;
}

// direct any other server messages to some other function
onResp(serverMsg);
};

ws.onerror = function (e) {
console.log('websocket error', e);
};

ws.onclose = function (e) {
console.log('disconnected', e.code, e.reason, e.wasClean);
};

How to setup environment

import ctrader_open_api.messages.OpenApiModelMessages_pb2 as OAModel
import json

# get payloadTypes
target_keys = filter(lambda i: i.startswith('PROTO_OA_'), dir(OAModel))
out = dict(map(lambda k: [k, getattr(OAModel, k)], target_keys))
with open('payloadTypes.json', 'w', encoding='utf-8') as f:
json.dump(out, f, ensure_ascii=False, indent=2)

# get OAModel stuff
target_keys = filter(lambda i: i.startswith('ProtoOA'), dir(OAModel))
ones_with_keyval = filter(lambda k: hasattr(getattr(OAModel,k),'keys'), target_keys)
out = {}
for key in ones_with_keyval:
prop = getattr(OAModel, key)
out[key] = dict(zip(prop.keys(), prop.values()))
with open('OAModel.json', 'w', encoding='utf-8') as f:
json.dump(out, f, ensure_ascii=False, indent=2)