ib-client
Version:
Interactive Brokers API client library for Node.js
1,260 lines (1,113 loc) • 92.3 kB
JavaScript
"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports["default"] = void 0;var _lodash = require("lodash");
var _constants = require("./constants");
var _errors = require("./errors");function _toConsumableArray(arr) {return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();}function _nonIterableSpread() {throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}function _unsupportedIterableToArray(o, minLen) {if (!o) return;if (typeof o === "string") return _arrayLikeToArray(o, minLen);var n = Object.prototype.toString.call(o).slice(8, -1);if (n === "Object" && o.constructor) n = o.constructor.name;if (n === "Map" || n === "Set") return Array.from(o);if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);}function _iterableToArray(iter) {if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);}function _arrayWithoutHoles(arr) {if (Array.isArray(arr)) return _arrayLikeToArray(arr);}function _arrayLikeToArray(arr, len) {if (len == null || len > arr.length) len = arr.length;for (var i = 0, arr2 = new Array(len); i < len; i++) {arr2[i] = arr[i];}return arr2;}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}function _createClass(Constructor, protoProps, staticProps) {if (protoProps) _defineProperties(Constructor.prototype, protoProps);if (staticProps) _defineProperties(Constructor, staticProps);return Constructor;}var
MessageEncoder = /*#__PURE__*/function () {
function MessageEncoder() {_classCallCheck(this, MessageEncoder);
this._serverVersion = _constants.SERVER_VERSION;
}_createClass(MessageEncoder, [{ key: "_error", value: function _error(
id, error, message) {
if (typeof error === 'string') {
throw new _errors.BrokerError({ id: id, code: null, message: error + ' ' + message });
} else {
throw new _errors.BrokerError({ id: id, code: error.code, message: error.message + ' ' + message });
}
} }, { key: "_encodeLengthHeader", value: function _encodeLengthHeader(
value) {
var arr = [];
var mask = 0xff;
arr.push(mask & value >> 24);
arr.push(mask & value >> 16);
arr.push(mask & value >> 8);
arr.push(mask & value);
return arr;
} }, { key: "_encodeString", value: function _encodeString(
value) {
if (value != null) {
return Array.from(value.concat(_constants.EOL), function (c) {return c.charCodeAt();});
} else {
return 0;
}
} }, { key: "_encodeBool", value: function _encodeBool(
value) {
return this._encodeString((value ? 1 : 0).toString());
} }, { key: "_encodeMax", value: function _encodeMax(
value) {
return value === 0xffffffff || value === Number.MAX_VALUE ?
this._encode('') :
this._encode(value);
} }, { key: "_encode", value: function _encode(
value) {
if (typeof value === 'boolean') return this._encodeBool(value);
return this._encodeString(value === undefined || value === null ? null : value.toString());
} }, { key: "encodeMessage", value: function encodeMessage(
data) {
var error = data[0];
var func = data[1];
var args = data.slice(2);
if (typeof this[func] !== 'function') throw new Error('Unknown broker API request - ' + func);
var tokens = (0, _lodash.flattenDeep)(this[func].apply(this, _toConsumableArray(args)));
return { error: error, func: func, args: args, message: this._prependV100LengthHeader(tokens) };
} }, { key: "setServerVersion", value: function setServerVersion(
version) {
this._serverVersion = version;
} }, { key: "_prependV100LengthHeader", value: function _prependV100LengthHeader(
message) {
var header = this._getV100LengthHeader(message.length);
return header.concat(message);
} }, { key: "_getV100LengthHeader", value: function _getV100LengthHeader(
length) {
return this._encodeLengthHeader(length);
} }, { key: "sendV100APIHeader", value: function sendV100APIHeader()
{
var prefix = this._encode('API');
var version = this._encode(
'v' + (_constants.MIN_VERSION < _constants.MAX_VERSION ? _constants.MIN_VERSION + '..' + _constants.MAX_VERSION : _constants.MIN_VERSION));
version.splice(-1);
return [prefix, this._getV100LengthHeader(version.length), version];
} }, { key: "startAPI", value: function startAPI(
clientId, optionalCapabilities) {
var version = 2;
var buffer = [this._encode(_constants.OUTGOING.START_API), this._encode(version), this._encode(clientId)];
if (this._serverVersion >= _constants.MIN_SERVER_VER.OPTIONAL_CAPABILITIES) {
buffer.push(this._encode(optionalCapabilities));
}
return buffer;
} }, { key: "cancelScannerSubscription", value: function cancelScannerSubscription(
tickerId) {
if (this._serverVersion < 24) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support API scanner subscription.');
}
var version = 1;
var buffer = [
this._encode(_constants.OUTGOING.CANCEL_SCANNER_SUBSCRIPTION),
this._encode(version),
this._encode(tickerId)];
return buffer;
} }, { key: "reqScannerParameters", value: function reqScannerParameters()
{
if (this._serverVersion < 24) {
return this._error(
_errors.BROKER_ERRORS.NO_VALID_ID,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support API scanner subscription.');
}
var version = 1;
return [this._encode(_constants.OUTGOING.REQ_SCANNER_PARAMETERS), this._encode(version)];
} }, { key: "reqScannerSubscription", value: function reqScannerSubscription(
tickerId,
subscription,
scannerSubscriptionOptions,
scannerSubscriptionFilterOptions)
{
if (this._serverVersion < 24) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support API scanner subscription.');
}
if (
this._serverVersion < _constants.MIN_SERVER_VER.SCANNER_GENERIC_OPTS &&
scannerSubscriptionFilterOptions != null)
{
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support API scanner subscription generic filter options');
}
var version = 4;
var buffer = [this._encode(_constants.OUTGOING.REQ_SCANNER_SUBSCRIPTION)];
if (this._serverVersion < _constants.MIN_SERVER_VER.SCANNER_GENERIC_OPTS) {
buffer.push(this._encode(version));
}
buffer.push(this._encode(tickerId));
buffer.push(this._encodeMax(subscription.numberOfRows));
buffer.push(this._encode(subscription.instrument));
buffer.push(this._encode(subscription.locationCode));
buffer.push(this._encode(subscription.scanCode));
buffer.push(this._encodeMax(subscription.abovePrice));
buffer.push(this._encodeMax(subscription.belowPrice));
buffer.push(this._encodeMax(subscription.aboveVolume));
buffer.push(this._encodeMax(subscription.marketCapAbove));
buffer.push(this._encodeMax(subscription.marketCapBelow));
buffer.push(this._encode(subscription.moodyRatingAbove));
buffer.push(this._encode(subscription.moodyRatingBelow));
buffer.push(this._encode(subscription.spRatingAbove));
buffer.push(this._encode(subscription.spRatingBelow));
buffer.push(this._encode(subscription.maturityDateAbove));
buffer.push(this._encode(subscription.maturityDateBelow));
buffer.push(this._encodeMax(subscription.couponRateAbove));
buffer.push(this._encodeMax(subscription.couponRateBelow));
buffer.push(this._encode(subscription.excludeConvertible));
if (this._serverVersion >= 25) {
buffer.push(this._encodeMax(subscription.averageOptionVolumeAbove));
buffer.push(this._encode(subscription.scannerSettingPairs));
}
if (this._serverVersion >= 27) {
buffer.push(this._encode(subscription.stockTypeFilter));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SCANNER_GENERIC_OPTS) {
buffer.push(this._encode(scannerSubscriptionFilterOptions));
}
// send scannerSubscriptionOptions parameter
if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) {
buffer.push(this._encode(scannerSubscriptionOptions));
}
return buffer;
} }, { key: "reqMktData", value: function reqMktData(
tickerId, contract, genericTickList, snapshot, regulatorySnapshot, mktDataOptions) {var _this = this;
if (this._serverVersion < _constants.MIN_SERVER_VER.SNAPSHOT_MKT_DATA && snapshot) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support snapshot market data requests.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support delta-neutral orders.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.REQ_MKT_DATA_CONID) {
return this._error(tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId parameter.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) {
if (!(0, _lodash.isEmpty)(contract.tradingClass)) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support tradingClass parameter in reqMarketData.');
}
}
var version = 11;
var buffer = [
this._encode(_constants.OUTGOING.REQ_MKT_DATA),
this._encode(version),
this._encode(tickerId)];
// send contract fields
if (this._serverVersion >= _constants.MIN_SERVER_VER.REQ_MKT_DATA_CONID) {
buffer.push(this._encode(contract.conId));
}
buffer.push(this._encode(contract.symbol));
buffer.push(this._encode(contract.secType));
buffer.push(this._encode(contract.expiry));
buffer.push(this._encode(contract.strike));
buffer.push(this._encode(contract.right));
if (this._serverVersion >= 15) {
buffer.push(this._encode(contract.multiplier));
}
buffer.push(this._encode(contract.exchange));
if (this._serverVersion >= 14) {
buffer.push(this._encode(contract.primaryExch));
}
buffer.push(this._encode(contract.currency));
if (this._serverVersion >= 2) {
buffer.push(this._encode(contract.localSymbol));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.tradingClass));
}
if (
this._serverVersion >= 8 &&
typeof contract.secType === 'string' &&
_constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase())
{
if (!Array.isArray(contract.comboLegs)) {
buffer.push(this._encode(0));
} else {
buffer.push(this._encode(contract.comboLegs.length));
contract.comboLegs.forEach(function (comboLeg) {
buffer.push(_this._encode(comboLeg.conId));
buffer.push(_this._encode(comboLeg.ratio));
buffer.push(_this._encode(comboLeg.action));
buffer.push(_this._encode(comboLeg.exchange));
});
}
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.DELTA_NEUTRAL) {
if ((0, _lodash.isPlainObject)(contract.deltaNeutralContract)) {
buffer.push(this._encode(true));
buffer.push(this._encode(contract.deltaNeutralContract.conId));
buffer.push(this._encode(contract.deltaNeutralContract.delta));
buffer.push(this._encode(contract.deltaNeutralContract.price));
} else {
buffer.push(this._encode(false));
}
}
if (this._serverVersion >= 31) {
/*
* Note: Even though SHORTABLE tick type supported only
* starting server version 33 it would be relatively
* expensive to expose this restriction here.
*
* Therefore we are relying on TWS doing validation.
*/
buffer.push(this._encode(genericTickList));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SNAPSHOT_MKT_DATA) {
buffer.push(this._encode(snapshot));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.REQ_SMART_COMPONENTS) {
buffer.push(this._encode(regulatorySnapshot));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) {
buffer.push(this._encode(mktDataOptions));
}
return buffer;
} }, { key: "cancelHistoricalData", value: function cancelHistoricalData(
tickerId) {
if (this._serverVersion < 24) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support historical data query cancellation.');
}
var version = 1;
var buffer = [
this._encode(_constants.OUTGOING.CANCEL_HISTORICAL_DATA),
this._encode(version),
this._encode(tickerId)];
return buffer;
} }, { key: "cancelRealTimeBars", value: function cancelRealTimeBars(
tickerId) {
if (this._serverVersion < _constants.MIN_SERVER_VER.REAL_TIME_BARS) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support realtime bar data query cancellation.');
}
var version = 1;
var buffer = [
this._encode(_constants.OUTGOING.CANCEL_REAL_TIME_BARS),
this._encode(version),
this._encode(tickerId)];
return buffer;
} }, { key: "reqHistoricalData", value: function reqHistoricalData(
tickerId,
contract,
endDateTime,
durationStr,
barSizeSetting,
whatToShow,
useRTH,
formatDate,
keepUpToDate,
chartOptions)
{var _this2 = this;
var version = 6;
if (this._serverVersion < 16) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support historical data backfill.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) {
if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support conId and tradingClass parameters in reqHistroricalData.');
}
}
var buffer = [this._encode(_constants.OUTGOING.REQ_HISTORICAL_DATA)];
if (this._serverVersion < _constants.MIN_SERVER_VER.SYNT_REALTIME_BARS) {
buffer.push(this._encode(version));
}
buffer.push(this._encode(tickerId));
// send contract fields
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.conId));
}
buffer.push(this._encode(contract.symbol));
buffer.push(this._encode(contract.secType));
buffer.push(this._encode(contract.expiry));
buffer.push(this._encode(contract.strike));
buffer.push(this._encode(contract.right));
buffer.push(this._encode(contract.multiplier));
buffer.push(this._encode(contract.exchange));
buffer.push(this._encode(contract.primaryExch));
buffer.push(this._encode(contract.currency));
buffer.push(this._encode(contract.localSymbol));
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.tradingClass));
}
if (this._serverVersion >= 31) {
buffer.push(this._encode(contract.includeExpired ? 1 : 0));
}
if (this._serverVersion >= 20) {
buffer.push(this._encode(endDateTime));
buffer.push(this._encode(barSizeSetting));
}
buffer.push(this._encode(durationStr));
buffer.push(this._encode(useRTH));
buffer.push(this._encode(whatToShow));
if (this._serverVersion > 16) {
buffer.push(this._encode(formatDate));
}
if (
typeof contract.secType === 'string' &&
_constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase())
{
if (!Array.isArray(contract.comboLegs)) {
buffer.push(this._encode(0));
} else {
buffer.push(this._encode(contract.comboLegs.length));
contract.comboLegs.forEach(function (comboLeg) {
buffer.push(_this2._encode(comboLeg.conId));
buffer.push(_this2._encode(comboLeg.ratio));
buffer.push(_this2._encode(comboLeg.action));
buffer.push(_this2._encode(comboLeg.exchange));
});
}
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SYNT_REALTIME_BARS) {
buffer.push(this._encode(keepUpToDate));
}
// send chartOptions parameter
if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) {
buffer.push(this._encode(chartOptions));
}
return buffer;
} }, { key: "reqHeadTimestamp", value: function reqHeadTimestamp(
reqId, contract, whatToShow, useRTH, formatDate) {
if (this._serverVersion < _constants.MIN_SERVER_VER.REQ_HEAD_TIMESTAMP) {
return this._error(reqId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support reqHeadTimeStamp');
}
return [
this._encode(_constants.OUTGOING.REQ_HEAD_TIMESTAMP),
this._encode(reqId),
this._encode(contract.conId),
this._encode(contract.symbol),
this._encode(contract.secType),
this._encode(contract.expiry),
this._encode(contract.strike),
this._encode(contract.right),
this._encode(contract.multiplier),
this._encode(contract.exchange),
this._encode(contract.primaryExchange),
this._encode(contract.currency),
this._encode(contract.localSymbol),
this._encode(contract.tradingClass),
this._encode(contract.includeExpired),
this._encode(useRTH),
this._encode(whatToShow),
this._encode(formatDate)];
} }, { key: "cancelHeadTimestamp", value: function cancelHeadTimestamp(
reqId) {
if (this._serverVersion < _constants.MIN_SERVER_VER.CANCEL_HEADTIMESTAMP) {
return this._error(
reqId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support head time stamp requests canceling.');
}
return [this._encode(_constants.OUTGOING.CANCEL_HEAD_TIMESTAMP), this._encode(reqId)];
} }, { key: "reqRealTimeBars", value: function reqRealTimeBars(
tickerId, contract, barSize, whatToShow, useRTH, realTimeBarsOptions) {
if (this._serverVersion < _constants.MIN_SERVER_VER.REAL_TIME_BARS) {
return this._error(tickerId, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support real time bars.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) {
if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support conId and tradingClass parameters in reqRealTimeBars.');
}
}
var version = 3;
// send req mkt data msg
var buffer = [
this._encode(_constants.OUTGOING.REQ_REAL_TIME_BARS),
this._encode(version),
this._encode(tickerId)];
// send contract fields
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.conId));
}
buffer.push(this._encode(contract.symbol));
buffer.push(this._encode(contract.secType));
buffer.push(this._encode(contract.expiry));
buffer.push(this._encode(contract.strike));
buffer.push(this._encode(contract.right));
buffer.push(this._encode(contract.multiplier));
buffer.push(this._encode(contract.exchange));
buffer.push(this._encode(contract.primaryExch));
buffer.push(this._encode(contract.currency));
buffer.push(this._encode(contract.localSymbol));
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.tradingClass));
}
buffer.push(this._encode(barSize)); // this parameter is not currently used
buffer.push(this._encode(whatToShow));
buffer.push(this._encode(useRTH));
// send realTimeBarsOptions parameter
if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) {
buffer.push(this._encode(realTimeBarsOptions));
}
return buffer;
} }, { key: "reqContractDetails", value: function reqContractDetails(
reqId, contract) {
if (this._serverVersion < 4) {
return this._error(
reqId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'This feature is only available for versions of TWS >=4');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SEC_ID_TYPE) {
if (!(0, _lodash.isEmpty)(contract.secIdType) || !(0, _lodash.isEmpty)(contract.secId)) {
return this._error(
reqId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support secIdType and secId parameters.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) {
if (!(0, _lodash.isEmpty)(contract.tradingClass)) {
return this._error(
reqId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support tradingClass parameter in reqContractDetails.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.LINKING) {
if (!(0, _lodash.isEmpty)(contract.primaryExch)) {
return this._error(
reqId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support primaryExchange parameter in reqContractDetails.');
}
}
var version = 8;
// send req mkt data msg
var buffer = [this._encode(_constants.OUTGOING.REQ_CONTRACT_DATA), this._encode(version)];
if (this._serverVersion >= _constants.MIN_SERVER_VER.CONTRACT_DATA_CHAIN) {
buffer.push(this._encode(reqId));
}
// send contract fields
if (this._serverVersion >= _constants.MIN_SERVER_VER.CONTRACT_CONID) {
buffer.push(this._encode(contract.conId));
}
buffer.push(this._encode(contract.symbol));
buffer.push(this._encode(contract.secType));
buffer.push(this._encode(contract.expiry));
buffer.push(this._encode(contract.strike));
buffer.push(this._encode(contract.right));
if (this._serverVersion >= 15) {
buffer.push(this._encode(contract.multiplier));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.PRIMARYEXCH) {
buffer.push(this._encode(contract.exchange));
buffer.push(this._encode(contract.primaryExch));
} else if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) {
if (
!(0, _lodash.isEmpty)(contract.primaryExch) && (
'BEST' === contract.exchange || 'SMART' === contract.exchange))
{
buffer.push(this._encode(contract.exchange + ':' + contract.primaryExch));
} else {
buffer.push(this._encode(contract.exchange));
}
}
buffer.push(this._encode(contract.currency));
buffer.push(this._encode(contract.localSymbol));
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.tradingClass));
}
if (this._serverVersion >= 31) {
buffer.push(this._encode(contract.includeExpired));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SEC_ID_TYPE) {
buffer.push(this._encode(contract.secIdType));
buffer.push(this._encode(contract.secId));
}
return buffer;
} }, { key: "reqMktDepth", value: function reqMktDepth(
tickerId, contract, numRows, isSmartDepth, mktDepthOptions) {
if (this._serverVersion < 6) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'This feature is only available for versions of TWS >=6');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) {
if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support conId and tradingClass parameters in reqMktDepth.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SMART_DEPTH && isSmartDepth) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support SMART depth request.');
}
var version = 5;
// send req mkt data msg
var buffer = [
this._encode(_constants.OUTGOING.REQ_MKT_DEPTH),
this._encode(version),
this._encode(tickerId)];
// send contract fields
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.conId));
}
buffer.push(this._encode(contract.symbol));
buffer.push(this._encode(contract.secType));
buffer.push(this._encode(contract.expiry));
buffer.push(this._encode(contract.strike));
buffer.push(this._encode(contract.right));
if (this._serverVersion >= 15) {
buffer.push(this._encode(contract.multiplier));
}
buffer.push(this._encode(contract.exchange));
buffer.push(this._encode(contract.currency));
buffer.push(this._encode(contract.localSymbol));
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.tradingClass));
}
if (this._serverVersion >= 19) {
buffer.push(this._encode(numRows));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SMART_DEPTH) {
buffer.push(this._encode(isSmartDepth));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.LINKING) {
buffer.push(this._encode(mktDepthOptions));
}
return buffer;
} }, { key: "cancelMktData", value: function cancelMktData(
tickerId) {
var version = 1;
var buffer = [
this._encode(_constants.OUTGOING.CANCEL_MKT_DATA),
this._encode(version),
this._encode(tickerId)];
return buffer;
} }, { key: "cancelMktDepth", value: function cancelMktDepth(
tickerId, isSmartDepth) {
if (this._serverVersion < 6) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'This feature is only available for versions of TWS >=6.');
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SMART_DEPTH && isSmartDepth) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support SMART depth cancel.');
}
var version = 1;
var buffer = [
this._encode(_constants.OUTGOING.CANCEL_MKT_DEPTH),
this._encode(version),
this._encode(tickerId)];
if (this._serverVersion >= _constants.MIN_SERVER_VER.SMART_DEPTH) {
buffer.push(this._encode(isSmartDepth));
}
return buffer;
} }, { key: "exerciseOptions", value: function exerciseOptions(
tickerId, contract, exerciseAction, exerciseQuantity, account, override) {
var version = 2;
if (this._serverVersion < 21) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support options exercise from the API.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) {
if (!(0, _lodash.isEmpty)(contract.tradingClass) || contract.conId > 0) {
return this._error(
tickerId,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support conId and tradingClass parameters in exerciseOptions.');
}
}
var buffer = [
this._encode(_constants.OUTGOING.EXERCISE_OPTIONS),
this._encode(version),
this._encode(tickerId)];
// send contract fields
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.conId));
}
buffer.push(this._encode(contract.symbol));
buffer.push(this._encode(contract.secType));
buffer.push(this._encode(contract.expiry));
buffer.push(this._encode(contract.strike));
buffer.push(this._encode(contract.right));
buffer.push(this._encode(contract.multiplier));
buffer.push(this._encode(contract.exchange));
buffer.push(this._encode(contract.currency));
buffer.push(this._encode(contract.localSymbol));
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.tradingClass));
}
buffer.push(this._encode(exerciseAction));
buffer.push(this._encode(exerciseQuantity));
buffer.push(this._encode(account));
buffer.push(this._encode(override));
return buffer;
} }, { key: "placeOrder", value: function placeOrder(
id, contract, order) {var _this3 = this;
if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_ORDERS) {
if (
order.scaleInitLevelSize !== Number.MAX_VALUE ||
order.scalePriceIncrement !== Number.MAX_VALUE)
{
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support Scale orders.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SSHORT_COMBO_LEGS) {
if (Array.isArray(contract.comboLegs)) {
contract.comboLegs.forEach(
function (comboLeg) {
if (!(0, _lodash.isEmpty)(comboLeg.shortSaleSlot) || !(0, _lodash.isEmpty)(comboLeg.designatedLocation)) {
return this._emitError(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support SSHORT flag for combo legs.');
}
}.bind(this));
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.WHAT_IF_ORDERS) {
if (order.whatIf) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support what-if orders.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL) {
if (contract.deltaNeutralContract) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support delta-neutral orders.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_ORDERS2) {
if (order.scaleSubsLevelSize && order.scaleSubsLevelSize !== Number.MAX_VALUE) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support Subsequent Level Size for Scale orders.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.ALGO_ORDERS) {
if (!(0, _lodash.isEmpty)(order.algoStrategy)) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support algo orders.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.NOT_HELD) {
if (order.notHeld) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support notHeld parameter.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SEC_ID_TYPE) {
if (!(0, _lodash.isEmpty)(contract.secIdType) || !(0, _lodash.isEmpty)(contract.secId)) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support secIdType and secId parameters.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.PLACE_ORDER_CONID) {
if (contract.conId > 0) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support conId parameter.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SSHORTX) {
if (order.exemptCode && order.exemptCode !== -1) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support exemptCode parameter.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SSHORTX) {
if (Array.isArray(contract.comboLegs)) {
contract.comboLegs.forEach(
function (comboLeg) {return (
comboLeg.exemptCode !== -1 && _this3._error('It does not support exemptCode parameter.'));});
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.HEDGE_ORDERS) {
if (!(0, _lodash.isEmpty)(order.hedgeType)) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support hedge orders.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.OPT_OUT_SMART_ROUTING) {
if (order.optOutSmartRouting) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support optOutSmartRouting parameter.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL_CONID) {
if (
order.deltaNeutralConId > 0 ||
!(0, _lodash.isEmpty)(order.deltaNeutralSettlingFirm) ||
!(0, _lodash.isEmpty)(order.deltaNeutralClearingAccount) ||
!(0, _lodash.isEmpty)(order.deltaNeutralClearingIntent))
{
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.DELTA_NEUTRAL_OPEN_CLOSE) {
if (
!(0, _lodash.isEmpty)(order.deltaNeutralOpenClose) ||
order.deltaNeutralShortSale ||
order.deltaNeutralShortSaleSlot > 0 ||
!(0, _lodash.isEmpty)(order.deltaNeutralDesignatedLocation))
{
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support deltaNeutral parameters: OpenClose, ShortSale, ShortSaleSlot, DesignatedLocation.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_ORDERS3) {
if (order.scalePriceIncrement > 0 && order.scalePriceIncrement !== Number.MAX_VALUE) {
if (
order.scalePriceAdjustValue !== Number.MAX_VALUE ||
order.scalePriceAdjustInterval !== Number.MAX_VALUE ||
order.scaleProfitOffset !== Number.MAX_VALUE ||
order.scaleAutoReset ||
order.scaleInitPosition !== Number.MAX_VALUE ||
order.scaleInitFillQty !== Number.MAX_VALUE ||
order.scaleRandomPercent)
{
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support Scale order parameters: PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset, InitPosition, InitFillQty and RandomPercent');
}
}
}
if (
this._serverVersion < _constants.MIN_SERVER_VER.ORDER_COMBO_LEGS_PRICE &&
typeof contract.secType === 'string' &&
_constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase())
{
if (Array.isArray(order.orderComboLegs)) {
order.orderComboLegs.forEach(
function (orderComboLeg) {return (
orderComboLeg.price !== Number.MAX_VALUE &&
_this3._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support per-leg prices for order combo legs.'));});
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRAILING_PERCENT) {
if (order.trailingPercent && order.trailingPercent !== Number.MAX_VALUE) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support trailing percent parameter.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRADING_CLASS) {
if (!(0, _lodash.isEmpty)(contract.tradingClass)) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support tradingClass parameters in placeOrder.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.ALGO_ID && !(0, _lodash.isEmpty)(order.algoId)) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support algoId parameter.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.SCALE_TABLE) {
if (
!(0, _lodash.isEmpty)(order.scaleTable) ||
!(0, _lodash.isEmpty)(order.activeStartTime) ||
!(0, _lodash.isEmpty)(order.activeStopTime))
{
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support scaleTable, activeStartTime and activeStopTime parameters.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_SOLICITED) {
if (order.solicited) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support order solicited parameter.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.MODELS_SUPPORT) {
if (!(0, _lodash.isEmpty)(order.modelCode)) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support model code parameter.');
}
}
if (this._serverVersion < _constants.MIN_SERVER_VER.EXT_OPERATOR && !(0, _lodash.isEmpty)(order.extOperator)) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support ext operator');
}
if (
this._serverVersion < _constants.MIN_SERVER_VER.SOFT_DOLLAR_TIER &&
order.softDollarTier && (
!(0, _lodash.isEmpty)(order.softDollarTier.name) || !(0, _lodash.isEmpty)(order.softDollarTier.value)))
{
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support soft dollar tier.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.CASH_QTY) {
if (order.cashQty && order.cashQty != Number.MAX_VALUE) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support cash quantity parameter.');
}
}
if (
this._serverVersion < _constants.MIN_SERVER_VER.DECISION_MAKER && (
!(0, _lodash.isEmpty)(order.mifid2DecisionMaker) || !(0, _lodash.isEmpty)(order.mifid2DecisionAlgo)))
{
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support MIFID II decision maker parameters.');
}
if (
this._serverVersion < _constants.MIN_SERVER_VER.MIFID_EXECUTION && (
!(0, _lodash.isEmpty)(order.mifid2ExecutionTrader) || !(0, _lodash.isEmpty)(order.mifid2ExecutionAlgo)))
{
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
' It does not support MIFID II execution parameters');
}
if (
this._serverVersion < _constants.MIN_SERVER_VER.AUTO_PRICE_FOR_HEDGE &&
order.dontUseAutoPriceForHedge)
{
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
"It does not support don't use auto price for hedge parameter.");
}
if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_CONTAINER && order.isOmsContainer) {
return this._error(
id,
_errors.BROKER_ERRORS.UPDATE_TWS,
'It does not support oms container parameter.');
}
if (this._serverVersion < _constants.MIN_SERVER_VER.D_PEG_ORDERS && order.discretionaryUpToLimitPrice) {
return this._error(id, _errors.BROKER_ERRORS.UPDATE_TWS, 'It does not support D-Peg orders.');
}
var version = this._serverVersion < _constants.MIN_SERVER_VER.NOT_HELD ? 27 : 45;
// send place order msg
var buffer = [this._encode(_constants.OUTGOING.PLACE_ORDER)];
if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_CONTAINER) {
buffer.push(this._encode(version));
}
buffer.push(this._encode(id));
// send contract fields
if (this._serverVersion >= _constants.MIN_SERVER_VER.PLACE_ORDER_CONID) {
buffer.push(this._encode(contract.conId));
}
buffer.push(this._encode(contract.symbol));
buffer.push(this._encode(contract.secType));
buffer.push(this._encode(contract.expiry));
buffer.push(this._encode(contract.strike));
buffer.push(this._encode(contract.right));
if (this._serverVersion >= 15) {
buffer.push(this._encode(contract.multiplier));
}
buffer.push(this._encode(contract.exchange));
if (this._serverVersion >= 14) {
buffer.push(this._encode(contract.primaryExch));
}
buffer.push(this._encode(contract.currency));
if (this._serverVersion >= 2) {
buffer.push(this._encode(contract.localSymbol));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.TRADING_CLASS) {
buffer.push(this._encode(contract.tradingClass));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SEC_ID_TYPE) {
buffer.push(this._encode(contract.secIdType));
buffer.push(this._encode(contract.secId));
}
// send main order fields
buffer.push(this._encode(order.action));
if (this._serverVersion >= _constants.MIN_SERVER_VER.FRACTIONAL_POSITIONS)
buffer.push(this._encode(order.totalQuantity));else
buffer.push(this._encode(parseInt(order.totalQuantity, 10)));
buffer.push(this._encode(order.orderType));
if (this._serverVersion < _constants.MIN_SERVER_VER.ORDER_COMBO_LEGS_PRICE) {
buffer.push(this._encode(order.lmtPrice === Number.MAX_VALUE ? 0 : order.lmtPrice));
} else {
buffer.push(this._encodeMax(order.lmtPrice));
}
if (this._serverVersion < _constants.MIN_SERVER_VER.TRAILING_PERCENT) {
buffer.push(this._encode(order.auxPrice === Number.MAX_VALUE ? 0 : order.auxPrice));
} else {
buffer.push(this._encodeMax(order.auxPrice));
}
// send extended order fields
buffer.push(this._encode(order.tif));
buffer.push(this._encode(order.ocaGroup));
buffer.push(this._encode(order.account));
buffer.push(this._encode(order.openClose));
buffer.push(this._encode(order.origin));
buffer.push(this._encode(order.orderRef));
buffer.push(this._encode(order.transmit));
if (this._serverVersion >= 4) {
buffer.push(this._encode(order.parentId));
}
if (this._serverVersion >= 5) {
buffer.push(this._encode(order.blockOrder));
buffer.push(this._encode(order.sweepToFill));
buffer.push(this._encode(order.displaySize));
buffer.push(this._encode(order.triggerMethod));
if (this._serverVersion < 38) {
// will never happen
buffer.push(this._encode( /* order.ignoreRth */false));
} else {
buffer.push(this._encode(order.outsideRth));
}
}
if (this._serverVersion >= 7) {
buffer.push(this._encode(order.hidden));
}
// Send combo legs for BAG requests
if (
this._serverVersion >= 8 &&
typeof contract.secType === 'string' &&
_constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase())
{
if (!Array.isArray(contract.comboLegs)) {
buffer.push(this._encode(0));
} else {
buffer.push(this._encode(contract.comboLegs.length));
contract.comboLegs.forEach(function (comboLeg) {
buffer.push(_this3._encode(comboLeg.conId));
buffer.push(_this3._encode(comboLeg.ratio));
buffer.push(_this3._encode(comboLeg.action));
buffer.push(_this3._encode(comboLeg.exchange));
buffer.push(_this3._encode(comboLeg.openClose));
if (_this3._serverVersion >= _constants.MIN_SERVER_VER.SSHORT_COMBO_LEGS) {
buffer.push(_this3._encode(comboLeg.shortSaleSlot));
buffer.push(_this3._encode(comboLeg.designatedLocation));
}
if (_this3._serverVersion >= _constants.MIN_SERVER_VER.SSHORTX_OLD) {
buffer.push(_this3._encode(comboLeg.exemptCode));
}
});
}
}
// Send order combo legs for BAG requests
if (
this._serverVersion >= _constants.MIN_SERVER_VER.ORDER_COMBO_LEGS_PRICE &&
typeof contract.secType === 'string' &&
_constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase())
{
if (!Array.isArray(order.orderComboLegs)) {
buffer.push(this._encode(0));
} else {
buffer.push(this._encode(order.orderComboLegs.length));
order.orderComboLegs.forEach(function (orderComboLeg) {return (
buffer.push(_this3._encodeMax(orderComboLeg.price)));});
}
}
var smartComboRoutingParamsCount;
if (
this._serverVersion >= _constants.MIN_SERVER_VER.SMART_COMBO_ROUTING_PARAMS &&
typeof contract.secType === 'string' &&
_constants.SEC_TYPE.BAG.toUpperCase() === contract.secType.toUpperCase())
{
smartComboRoutingParamsCount = !Array.isArray(order.smartComboRoutingParams) ?
0 :
order.smartComboRoutingParams.length;
buffer.push(this._encode(smartComboRoutingParamsCount));
if (smartComboRoutingParamsCount > 0) {
order.smartComboRoutingParams.forEach(function (tagValue) {
buffer.push(_this3._encode(tagValue.tag));
buffer.push(_this3._encode(tagValue.value));
});
}
}
if (this._serverVersion >= 9) {
// send deprecated sharesAllocation field
buffer.push(this._encode(''));
}
if (this._serverVersion >= 10) {
buffer.push(this._encode(order.discretionaryAmt));
}
if (this._serverVersion >= 11) {
buffer.push(this._encode(order.goodAfterTime));
}
if (this._serverVersion >= 12) {
buffer.push(this._encode(order.goodTillDate));
}
if (this._serverVersion >= 13) {
buffer.push(this._encode(order.faGroup));
buffer.push(this._encode(order.faMethod));
buffer.push(this._encode(order.faPercentage));
buffer.push(this._encode(order.faProfile));
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.MODELS_SUPPORT) {
buffer.push(this._encode(order.modelCode));
}
if (this._serverVersion >= 18) {
// institutional short sale slot fields.
buffer.push(this._encode(order.shortSaleSlot)); // 0 only for retail, 1 or 2 only for institution.
buffer.push(this._encode(order.designatedLocation)); // only populate when order.shortSaleSlot = 2.
}
if (this._serverVersion >= _constants.MIN_SERVER_VER.SSHORTX_OLD) {
buffer.push(this._encode(order.exemptCode));
}
var lower;
var upper;
if (this._serverVersion >= 19) {
buffer.push(this._encode(order.ocaType));
if (this._serverVersion < 38) {
// will never happen
buffer.push(this._encode( /* order.rthOnly */false));
}
buffer.push(this._encode(order.rule80A));
buffer.push(this._encode(order.settlingFirm));
buffer.push(this._encode(order.allOrNone));
buffer.push(this._encodeMax(order.minQty));
buffer.push(this._encodeMax(order.percentOffset));
buffer.push(this._encode(order.eTradeOnly));
buffer.push(this._encode(order.firmQuoteOnly));
buffer.push(this._encodeMax(order.nbboPriceCap));
buffer.push(this._encodeMax(order.auctionStrategy));
buffer.push(this._encodeMax(order.startingPrice));
buffer.push(this._encodeMax(order.stockRefPrice));
buffer.push(this._encodeMax(order.delta));
// Volatility orders had specific watermark price attribs in server version 26
lower =
this._serverVersion === 26 && order.orderType === 'VOL' ?
Number.MAX_VALUE :
order.stockRangeLower;
upper =
this._serverVersion === 26 && order.orderType === 'VOL' ?
Number.MAX_VALUE :
order.stockRangeUpper;
buffer.push(this._encodeMax(lower));
buffer.push(this._encodeMax(upper));
}
if (this._serverVersion >= 22) {
buffer.push(this._encode(order.overridePercentageConstraints));
}
if (this._serverVersion >= 26) {
// Volatility orders
buffer.push(this._encodeMax(order.volatility));
buffer.push(this._encodeMax(order.volatilityType));
if (this._serverVersion < 28) {
buffer.push(this._encode(order.deltaNeutralOrderType.toUpperCase()) === 'MKT');