@pingleware/metatrader4-oanda
Version:
Metatrader 4 to OANDA v2.0 REST API proxy
686 lines (659 loc) • 43.3 kB
JavaScript
"use strict"
const {
SendRequest
} = require('./send');
var {
account,
getAccountContext,
} = require('./account');
const MARKETINFO_MODE = {
MODE_LOW: 1, // Low day price
MODE_HIGH: 2, // High day price
MODE_TIME: 5, // The last incoming tick time (last known server time)
MODE_BID: 9, // Last incoming bid price. For the current symbol, it is stored in the predefined variable Bid
MODE_ASK: 10, // Last incoming ask price. For the current symbol, it is stored in the predefined variable Ask
MODE_POINT: 11, // Point size in the quote currency. For the current symbol, it is stored in the predefined variable Point
MODE_DIGITS: 12, // Count of digits after decimal point in the symbol prices. For the current symbol, it is stored in the predefined variable Digits
MODE_SPREAD: 13, // Spread value in points
MODE_STOPLEVEL: 14, // Stop level in points. A zero value of MODE_STOPLEVEL means either absence of any restrictions on the minimal distance for Stop Loss/Take Profit or the fact that a trade server utilizes some external mechanisms for dynamic level control, which cannot be translated in the client terminal. In the second case, GetLastError() can return error 130, because MODE_STOPLEVEL is actually "floating" here.
MODE_LOTSIZE: 15, // Lot size in the base currency
MODE_TICKVALUE: 16, // Tick value in the deposit currency
MODE_TICKSIZE: 17, // Tick size in points
MODE_SWAPLONG: 18, // Swap of the buy order
MODE_SWAPSHORT: 19, // Swap of the sell order
MODE_STARTING: 20, // Market starting date (usually used for futures)
MODE_EXPIRATION: 21, // Market expiration date (usually used for futures)
MODE_TRADEALLOWED: 22, // Trade is allowed for the symbol
MODE_MINLOT: 23, // Minimum permitted amount of a lot
MODE_LOTSTEP: 24, // Step for changing lots
MODE_MAXLOT: 25, // Maximum permitted amount of a lot
MODE_SWAPTYPE: 26, // Swap calculation method. 0 - in points; 1 - in the symbol base currency; 2 - by interest; 3 - in the margin currency
MODE_PROFITCALCMODE: 27, // Profit calculation mode. 0 - Forex; 1 - CFD; 2 - Futures
MODE_MARGINCALCMODE: 28, // Margin calculation mode. 0 - Forex; 1 - CFD; 2 - Futures; 3 - CFD for indices
MODE_MARGININIT: 29, // Initial margin requirements for 1 lot
MODE_MARGINMAINTENANCE: 30, // Margin to maintain open orders calculated for 1 lot
MODE_MARGINHEDGED: 31, // Hedged margin calculated for 1 lot
MODE_MARGINREQUIRED: 32, // Free margin required to open 1 lot for buying
MODE_FREEZELEVEL: 33,
MODE_CLOSEBY_ALLOWED: 34
}
const ENUM_SYMBOL_INFO_INTEGER = {
SYMBOL_SELECT: 0, // Symbol is selected in Market Watch. Some symbols can be hidden in Market Watch, but still they are considered as selected., bool
SYMBOL_VISIBLE: 76, // Symbol is visible in Market Watch. Some symbols (mostly, these are cross rates required for calculation of margin requirements or profits in deposit currency) are selected automatically, but generally are not visible in Market Watch. To be displayed such symbols have to be explicitly selected., bool
SYMBOL_SESSION_DEALS: 56, // Not supported, long
SYMBOL_SESSION_BUY_ORDERS: 60, // Not supported, long
SYMBOL_SESSION_SELL_ORDERS: 61, // Not supported, long
SYMBOL_VOLUME: 10, // Not supported, long
SYMBOL_VOLUMEHIGH: 11, // Not supported, long
SYMBOL_VOLUMELOW: 12, // Not supported, long
SYMBOL_TIME: 15, // Time of the last quote, datetime
SYMBOL_DIGITS: 17, // Digits after a decimal point, int
SYMBOL_SPREAD_FLOAT: 41, // Indication of a floating spread, bool
SYMBOL_SPREAD: 18, // Spread value in points, int
SYMBOL_TRADE_CALC_MODE: 29, // Contract price calculation mode, int
SYMBOL_TRADE_MODE: 30, // Order execution type, ENUM_SYMBOL_TRADE_MODE
SYMBOL_START_TIME: 51, // Date of the symbol trade beginning (usually used for futures), datetime
SYMBOL_EXPIRATION_TIME: 52, // Date of the symbol trade end (usually used for futures), datetime
SYMBOL_FILLING_MODE: 50, // Not supported, int
SYMBOL_EXPIRATION_MODE: 49, // Not supported, int
SYMBOL_SWAP_ROLLOVER3DAYS: 40, // Day of week to charge 3 days swap rollover, ENUM_DAY_OF_WEEK
SYMBOL_SWAP_MODE: 37, // Swap calculation model, int
SYMBOL_TRADE_EXEMODE: 33, // Deal execution mode, ENUM_SYMBOL_TRADE_EXECUTION
SYMBOL_TRADE_FREEZE_LEVEL: 32, // Distance to freeze trade operations in points, int
SYMBOL_TRADE_STOPS_LEVEL: 31, // Minimal indention in points from the current close price to place Stop orders, int
SYMBOL_ORDER_MODE: 71, // Not supported, int
};
const ENUM_SYMBOL_INFO_DOUBLE = {
SYMBOL_BID: 1, // Bid - best sell offer, double
SYMBOL_BIDHIGH: 2, // Not supported, double
SYMBOL_BIDLOW: 3, // Not supported, double
SYMBOL_ASK: 4, // Ask - best buy offer, double
SYMBOL_ASKHIGH: 5, // Not supported, double
SYMBOL_ASKLOW: 6, // Not supported, double
SYMBOL_LAST: 7, // Not supported, double
SYMBOL_LASTHIGH: 8, // Not supported, double
SYMBOL_LASTLOW: 9, // Not supported, double
SYMBOL_POINT: 16, // Symbol point value, double
SYMBOL_TRADE_TICK_VALUE: 26, // Value of SYMBOL_TRADE_TICK_VALUE_PROFIT, double
SYMBOL_TRADE_TICK_VALUE_PROFIT: 53, // Not supported, double
SYMBOL_TRADE_TICK_VALUE_LOSS: 54, // Not supported, double
SYMBOL_TRADE_TICK_SIZE: 27, // Minimal price change, double
SYMBOL_TRADE_CONTRACT_SIZE: 28, // Trade contract size, double
SYMBOL_VOLUME_MIN: 34, // Minimal volume for a deal, double
SYMBOL_VOLUME_MAX: 35, // Maximal volume for a deal, double
SYMBOL_VOLUME_STEP: 36, // Minimal volume change step for deal execution, double
SYMBOL_VOLUME_LIMIT: 55, // Not supported, double
SYMBOL_SWAP_LONG: 38, // Buy order swap value, double
SYMBOL_SWAP_SHORT: 39, // Sell order swap value, double
SYMBOL_MARGIN_INITIAL: 42, // Initial margin means the amount in the margin currency required for opening an order with the volume of one lot. It is used for checking a client's assets when he or she enters the market., double
SYMBOL_MARGIN_MAINTENANCE: 43, // The maintenance margin. If it is set, it sets the margin amount in the margin currency of the symbol, charged from one lot. It is used for checking a client's assets when his/her account state changes. If the maintenance margin is equal to 0, the initial margin is used., double
SYMBOL_MARGIN_LONG: 44, // Not supported, double
SYMBOL_MARGIN_SHORT: 45, // Not supported, double
SYMBOL_MARGIN_LIMIT: 46, // Not supported, double
SYMBOL_MARGIN_STOP: 47, // Not supported, double
SYMBOL_MARGIN_STOPLIMIT: 48, // Not supported, double
SYMBOL_SESSION_VOLUME: 57, // Not supported, double
SYMBOL_SESSION_TURNOVER: 58, // Not supported, double
SYMBOL_SESSION_INTEREST: 59, // Not supported, double
SYMBOL_SESSION_BUY_ORDERS_VOLUME: 61, // Not supported, double
SYMBOL_SESSION_SELL_ORDERS_VOLUME: 63, // Not supported, double
SYMBOL_SESSION_OPEN: 64, // Not supported, double
SYMBOL_SESSION_CLOSE: 65, // Not supported, double
SYMBOL_SESSION_AW: 66, // Not supported, double
SYMBOL_SESSION_PRICE_SETTLEMENT: 67, // Not supported, double
SYMBOL_SESSION_PRICE_LIMIT_MIN: 68, // Not supported, double
SYMBOL_SESSION_PRICE_LIMIT_MAX : 69, // Not supported, double
};
const ENUM_SYMBOL_INFO_STRING = {
SYMBOL_CURRENCY_BASE: 22, // Basic currency of a symbol, string
SYMBOL_CURRENCY_PROFIT: 23, // Profit currency, string
SYMBOL_CURRENCY_MARGIN: 24, // Margin currency, string
SYMBOL_DESCRIPTION: 20, // Symbol description, string
SYMBOL_PATH: 21, // Path in the symbol tree, string
};
const ENUM_SYMBOL_TRADE_MODE = {
SYMBOL_TRADE_MODE_DISABLED: 0, // Trade is disabled for the symbol
SYMBOL_TRADE_MODE_LONGONLY: 3, // Allowed only long positions
SYMBOL_TRADE_MODE_SHORTONLY: 4, // Allowed only short positions
SYMBOL_TRADE_MODE_CLOSEONLY: 1, // Allowed only position close operations
SYMBOL_TRADE_MODE_FULL: 2, // No trade restrictions
};
const ENUM_SYMBOL_TRADE_EXECUTION = {
SYMBOL_TRADE_EXECUTION_REQUEST: 0, // Execution by request
SYMBOL_TRADE_EXECUTION_INSTANT: 1, // Instant execution
SYMBOL_TRADE_EXECUTION_MARKET: 2, // Market execution
SYMBOL_TRADE_EXECUTION_EXCHANGE: 3 // Exchange execution
};
const ENUM_DAY_OF_WEEK = {
SUNDAY: 0,
MONDAY: 1,
TUESDAY: 2,
WEDNESDAY: 3,
THURSDAY: 4,
FRIDAY: 5,
SATURDAY: 6
};
function datetime(value) {
return new Date(value).getTime();
}
/**
* MarketInfo
* Returns various data about securities listed in the "Market Watch" window
*/
function MarketInfo(symbol, information_type, callback) {
var context = getAccountContext();
SendRequest(context,`v3/accounts/${account.number}/instruments`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, path: `v3/accounts/${account.number}/`, function: 'MarketInfo'});
} else {
var instruments = data.instruments;
instruments.forEach(function(instrument){
if (instrument.name == symbol) {
switch(information_type) {
case MARKETINFO_MODE.MODE_LOW:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_HIGH:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_TIME:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_BID:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_ASK:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_POINT:
callback({status: 'success', point: Number(instrument.displayPrecision), function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_DIGITS:
callback({status: 'success', digits: Number(instrument.displayPrecision), function: 'MarketInfo'});
case MARKETINFO_MODE.MODE_SPREAD:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_STOPLEVEL:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_LOTSIZE:
callback({status: 'success', lotsize: Number(instrument.commission.unitsTraded), function: 'MarketInfo'});
case MARKETINFO_MODE.MODE_TICKVALUE:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_TICKSIZE:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_SWAPLONG:
callback({status: 'success', swaplong: Number(instrument.financing.longRate), function: 'MarketInfo'});
case MARKETINFO_MODE.MODE_SWAPSHORT:
callback({status: 'success', swapshort: Number(instrument.financing.shortRate), function: 'MarketInfo'});
case MARKETINFO_MODE.MODE_STARTING:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_EXPIRATION:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_TRADEALLOWED:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_MINLOT:
callback({status: 'success', minlot: Number(instrument.minimumTradeSize), function: 'MarketInfo'});
case MARKETINFO_MODE.MODE_LOTSTEP:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_MAXLOT:
callback({status: 'success', maxlot: Number(instrument.maximumOrderUnits), function: 'MarketInfo'});
case MARKETINFO_MODE.MODE_SWAPTYPE:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_PROFITCALCMODE:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_MARGINCALCMODE:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_MARGININIT:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_MARGINMAINTENANCE:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_MARGINHEDGED:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_MARGINREQUIRED:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_FREEZELEVEL:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
case MARKETINFO_MODE.MODE_CLOSEBY_ALLOWED:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
break;
default:
callback({ststus: 'error', message: 'not implemented', function: 'MarketInfo'});
}
}
});
}
});
}
var MarketWatch = [];
/**
* SymbolsTotal
* Returns the number of available (selected in Market Watch or all) symbols
*/
function SymbolsTotal(selected, callback) {
if (selected) {
callback({status: 'success', total: MarketWatch.length, function: 'SymbolsTotal'});
} else {
var context = getAccountContext();
SendRequest(context,`v3/accounts/${account.number}/instruments`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, function: 'SymbolsTotal'});
} else {
var instruments = data.instruments;
instruments.forEach(function(symbol){
MarketWatch.push(symbol.name);
});
callback({status: 'success', total: MarketWatch.length, function: 'SymbolsTotal'});
}
});
}
}
/**
* SymbolName
* Returns the name of a specified symbol
*/
function SymbolName(pos,selected,callback) {
if (selected) {
try {
var symbol = MarketWatch[pos];
callback({status: 'success', name: symbol, function: 'SymbolName'});
} catch(error) {
callback({status: 'error', message: error, function: 'SymbolName'});
}
} else {
var context = getAccountContext();
SendRequest(context,`v3/accounts/${account.number}/instruments`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, function: 'SymbolName'});
} else {
try {
var symbol = data.instruments[pos].name;
callback({status: 'success', name: symbol, function: 'SymbolName'});
} catch(error) {
callback({status: 'error', message: error, function: 'SymbolName'});
}
}
});
}
}
/**
* SymbolSelect
* Selects a symbol in the Market Watch window or removes a symbol from the window
*/
function SymbolSelect(symbol,add_remove,callback) {
if (add_remove) {
MarketWatch.push(symbol);
} else {
MarketWatch.pop(symbol);
}
callback({status: 'success', symbol: symbol, added: add_remove, function: 'SymbolSelect'});
}
/**
* SymbolInfoDouble
* Returns the double value of the symbol for the corresponding property
*/
function SymbolInfoDouble(symbol, property_id, callback) {
var context = getAccountContext();
SendRequest(context,`v3/accounts/${account.number}/instruments`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, function: 'SymbolInfoDouble'});
} else {
var instruments = data.instruments;
instruments.forEach(function(instrument){
if (instrument.name == symbol) {
switch(property_id) {
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID: //1, // Bid - best sell offer, double
callback({status: 'success', bid: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BIDHIGH: //2, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BIDLOW: //3, // Not supported, double
callback({status: 'error', message: 'not supported', function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_ASK: //4, // Ask - best buy offer, double
callback({status: 'success', ask: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_ASKHIGH: //5, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_ASKLOW: //6, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_LAST: //7, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_LASTHIGH: //8, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_LASTLOW: //9, // Not supported, double
callback({status: 'error', message: 'not supported', function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_POINT: //16, // Symbol point value, double
callback({status: 'success', point: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_TRADE_TICK_VALUE: //26, // Value of SYMBOL_TRADE_TICK_VALUE_PROFIT, double
callback({status: 'success', tick_value: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_TRADE_TICK_VALUE_PROFIT: //53, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_TRADE_TICK_VALUE_LOSS: //54, // Not supported, double
callback({status: 'error', message: 'not supported', function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_TRADE_TICK_SIZE: //27, // Minimal price change, double
callback({status: 'success', tick_size: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_TRADE_CONTRACT_SIZE: //28, // Trade contract size, double
callback({status: 'success', contract_size: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_MIN: //34, // Minimal volume for a deal, double
callback({status: 'success', volume_min: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_MAX: //35, // Maximal volume for a deal, double
callback({status: 'success', volume_max: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_STEP: //36, // Minimal volume change step for deal execution, double
callback({status: 'success', volume_step: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_LIMIT: //55, // Not supported, double
callback({status: 'error', message: 'not supported', function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SWAP_LONG: //38, // Buy order swap value, double
callback({status: 'success', swap_long: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SWAP_SHORT: //39, // Sell order swap value, double
callback({status: 'success', swap_short: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_MARGIN_INITIAL: //42, // Initial margin means the amount in the margin currency required for opening an order with the volume of one lot. It is used for checking a client's assets when he or she enters the market., double
callback({status: 'success', margin_initial: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_MARGIN_MAINTENANCE: //43, // The maintenance margin. If it is set, it sets the margin amount in the margin currency of the symbol, charged from one lot. It is used for checking a client's assets when his/her account state changes. If the maintenance margin is equal to 0, the initial margin is used., double
callback({status: 'success', margin_maintenance: 0, function: 'SymbolInfoDouble'});
break;
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_MARGIN_LONG: //44, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_MARGIN_SHORT: //45, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_MARGIN_LIMIT: //46, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_MARGIN_STOP: //47, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_MARGIN_STOPLIMIT: //48, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_VOLUME: //57, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_TURNOVER: //58, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_INTEREST: //59, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_BUY_ORDERS_VOLUME: //61, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_SELL_ORDERS_VOLUME: //63, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_OPEN: //64, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_CLOSE: //65, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_AW: //66, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_PRICE_SETTLEMENT: //67, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_PRICE_LIMIT_MIN: //68, // Not supported, double
case ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_SESSION_PRICE_LIMIT_MAX : //69, // Not supported, double
default:
callback({status: 'error', message: 'not supported', function: 'SymbolInfoDouble'});
break;
}
}
});
}
});
}
/**
* SymbolInfoInteger
* Returns a value of an integer type (long, datetime, int or bool) of a specified symbol for the corresponding property
*/
function SymbolInfoInteger(symbol, property_id, callback) {
var context = getAccountContext();
SendRequest(context,`v3/accounts/${account.number}/instruments`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, function: 'SymbolInfoInteger'});
} else {
var instruments = data.instruments;
instruments.forEach(function(instrument){
if (instrument.name == symbol) {
switch(property_id) {
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SELECT: //0, // Symbol is selected in Market Watch. Some symbols can be hidden in Market Watch, but still they are considered as selected., bool
callback({status: 'success', symbol_select: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_VISIBLE: //76, // Symbol is visible in Market Watch. Some symbols (mostly, these are cross rates required for calculation of margin requirements or profits in deposit currency) are selected automatically, but generally are not visible in Market Watch. To be displayed such symbols have to be explicitly selected., bool
callback({status: 'success', symbol_visible: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SESSION_DEALS: //56, // Not supported, long
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SESSION_BUY_ORDERS: //60, // Not supported, long
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SESSION_SELL_ORDERS: //61, // Not supported, long
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_VOLUME: //10, // Not supported, long
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_VOLUMEHIGH: //11, // Not supported, long
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_VOLUMELOW: //12, // Not supported, long
callback({status: 'error', message: 'not supported', function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_TIME: //15, // Time of the last quote, datetime
callback({status: 'success', symbol_time: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_DIGITS: //17, // Digits after a decimal point, int
callback({status: 'success', symbol_digits: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD_FLOAT: //41, // Indication of a floating spread, bool
callback({status: 'success', symbol_spread_float: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD: //18, // Spread value in points, int
callback({status: 'success', symbol_spread: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_TRADE_CALC_MODE: //29, // Contract price calculation mode, int
callback({status: 'success', symbol_trade_calc_mode: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_TRADE_MODE: //30, // Order execution type, ENUM_SYMBOL_TRADE_MODE
callback({status: 'success', symbol_trade_mode: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_START_TIME: //51, // Date of the symbol trade beginning (usually used for futures), datetime
callback({status: 'success', symbol_start_time: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_EXPIRATION_TIME: //52, // Date of the symbol trade end (usually used for futures), datetime
callback({status: 'success', symbol_expiration_time: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_FILLING_MODE: //50, // Not supported, int
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_EXPIRATION_MODE: //49, // Not supported, int
callback({status: 'error', message: 'not supported', function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SWAP_ROLLOVER3DAYS: //40, // Day of week to charge 3 days swap rollover, ENUM_DAY_OF_WEEK
callback({status: 'success', symbol_swap_rollover3days: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SWAP_MODE: //37, // Swap calculation model, int
callback({status: 'success', symbol_swap_mode: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_TRADE_EXEMODE: //33, // Deal execution mode, ENUM_SYMBOL_TRADE_EXECUTION
callback({status: 'success', symbol_trade_exemode: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_TRADE_FREEZE_LEVEL: //32, // Distance to freeze trade operations in points, int
callback({status: 'success', symbol_trade_freeze_level: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_TRADE_STOPS_LEVEL: //31, // Minimal indention in points from the current close price to place Stop orders, int
callback({status: 'success', symbol_trade_stops_level: 0, function: 'SymbolInfoInteger'});
break;
case ENUM_SYMBOL_INFO_INTEGER.SYMBOL_ORDER_MODE: //71, // Not supported, int
default:
callback({status: 'error', message: 'not supported', function: 'SymbolInfoInteger'});
break;
}
}
});
}
});
}
/**
* SymbolInfoString
* Returns a value of the string type of a specified symbol for the corresponding property
*/
function SymbolInfoString(symbol, property_id, callback) {
var context = getAccountContext();
SendRequest(context,`v3/accounts/${account.number}/instruments`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, function: 'SymbolInfoString'});
} else {
var instruments = data.instruments;
instruments.forEach(function(instrument){
if (instrument.name == symbol) {
switch(property_id) {
case ENUM_SYMBOL_INFO_STRING.SYMBOL_CURRENCY_BASE: //22, // Basic currency of a symbol, string
callback({status: 'success', currency_base: '', function: 'SymbolInfoString'});
break;
case ENUM_SYMBOL_INFO_STRING.SYMBOL_CURRENCY_PROFIT: //23, // Profit currency, string
callback({status: 'success', currency_profit: '', function: 'SymbolInfoString'});
break;
case ENUM_SYMBOL_INFO_STRING.SYMBOL_CURRENCY_MARGIN: //24, // Margin currency, string
callback({status: 'success', currency_margin: '', function: 'SymbolInfoString'});
break;
case ENUM_SYMBOL_INFO_STRING.SYMBOL_DESCRIPTION: //20, // Symbol description, string
callback({status: 'success', description: '', function: 'SymbolInfoString'});
break;
case ENUM_SYMBOL_INFO_STRING.SYMBOL_PATH: //21, // Path in the symbol tree, string
callback({status: 'success', path: '', function: 'SymbolInfoString'});
break;
default:
callback({status: 'error', message: 'not supported', function: 'SymbolInfoString'});
break;
}
}
});
}
});
}
/**
* SymbolInfoTick
* Returns the current prices for the specified symbol in a variable of the MqlTick type
*/
function SymbolInfoTick(symbol, callback) {
var context = getAccountContext();
SendRequest(context,`v3/accounts/${account.number}/pricing?instruments=${symbol}`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, path: `v3/accounts/${account.number}/`, function: 'SymbolInfoTick'});
} else {
var MqlTick = {
time: data.time, // Time of the last prices update
bid: data.prices[0].bids[0].price, // Current Bid price
ask: data.prices[0].asks[0].price, // Current Ask price
last: data.prices[0].closeoutBid, // Price of the last deal (Last)
volume: 0 // Volume for the current Last price
};
callback({status: 'success', mqltikc: MqlTick, function: 'SymbolInfoTick'});
}
});
}
/**
* SymbolInfoSessionQuote
* Allows receiving time of beginning and end of the specified quoting sessions for a specified symbol and day of week.
*/
function SymbolInfoSessionQuote(symbol,day_of_week,session_index,from,to,callback) {
callback({status: 'error', message: 'not implemented', function: 'SymbolInfoSessionQuote'});
}
/**
* SymbolInfoSessionTrade
* Allows receiving time of beginning and end of the specified trading sessions for a specified symbol and day of week
*/
function SymbolInfoSessionTrade(symbol,day_of_week,session_index,from,to,callback) {
callback({status: 'error', message: 'not implemented', function: 'SymbolInfoSessionTrade'});
}
/**
* OrderBook
*/
function OrderBook(symbol,callback) {
var context = getAccountContext();
SendRequest(context,`v3/instruments/${symbol}/orderBook`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, path: `v3/accounts/instruments/${symbol}/orderBook`, function: 'OrderBook'});
} else {
let totals = 0;
let price = 0;
let longPercentage = 0;
let shortPercentage = 0;
data.orderBook.buckets.forEach(function(bucket){
price += Number(bucket.price);
longPercentage += Number(bucket.longCountPercent);
shortPercentage += Number(bucket.shortCountPercent);
totals++;
});
price = Number((price / totals) * 100).toFixed(0);
longPercentage = Number((longPercentage / totals) * 100).toFixed(0);
shortPercentage = Number((shortPercentage / totals) * 100).toFixed(0);
callback({status: 'success', price: price, longPercentage: longPercentage, shortPercentage: shortPercentage, function: 'OrderBook'});
}
});
}
function PositionBook(symbol,callback) {
var context = getAccountContext();
SendRequest(context,`v3/instruments/${symbol}/positionBook`,'GET',null,function(json){
var data = JSON.parse(json);
if (data.errorMessage) {
callback({status: 'error', message: data.errorMessage, path: `v3/accounts/instruments/${symbol}/positionBook`, function: 'PositionBook'});
} else {
let totals = 0;
let price = 0;
let longPercentage = 0;
let shortPercentage = 0;
/**
* {
* #
* # The lowest price (inclusive) covered by the bucket. The bucket covers the
* # price range from the price to price + the position book’s bucketWidth.
* #
* price : (PriceValue),
*
* #
* # The percentage of the total number of positions represented by the long
* # positions found in this bucket.
* #
* longCountPercent : (DecimalNumber),
*
* # # The percentage of the total number of positions represented by the short
* # positions found in this bucket.
* #
* shortCountPercent : (DecimalNumber)
* }
*
* Calculate the average percentage @see https://www.indeed.com/career-advice/career-development/how-to-calculate-average-percentage
*
* [(Percentage 1 + percentage 2)/(sample size 1 + sample size 2)] x 100 = average percentage
*
*/
data.positionBook.buckets.forEach(function(bucket){
price += Number(bucket.price);
longPercentage += Number(bucket.longCountPercent);
shortPercentage += Number(bucket.shortCountPercent);
totals++;
});
price = Number((price / totals) * 100).toFixed(0);
longPercentage = Number((longPercentage / totals) * 100).toFixed(0);
shortPercentage = Number((shortPercentage / totals) * 100).toFixed(0);
callback({status: 'success', price: price, longPercentage: longPercentage, shortPercentage: shortPercentage, function: 'PositionBook'});
}
});
}
module.exports = {
MARKETINFO_MODE,
ENUM_SYMBOL_INFO_INTEGER,
ENUM_SYMBOL_INFO_DOUBLE,
ENUM_SYMBOL_INFO_STRING,
ENUM_SYMBOL_TRADE_MODE,
ENUM_SYMBOL_TRADE_EXECUTION,
ENUM_DAY_OF_WEEK,
MarketWatch,
MarketInfo,
SymbolsTotal,
SymbolName,
SymbolSelect,
SymbolInfoDouble,
SymbolInfoInteger,
SymbolInfoString,
SymbolInfoTick,
SymbolInfoSessionQuote,
SymbolInfoSessionTrade,
OrderBook,
PositionBook
}