diff --git a/README.md b/README.md index 494a705..3a2cf1b 100644 --- a/README.md +++ b/README.md @@ -79,11 +79,11 @@ ib.connect() .reqExecutions(reqId, filter) .reqFundamentalData(reqId, contract, reportType) .reqGlobalCancel() -.reqHistoricalData(tickerId, contract, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH, formatDate) +.reqHistoricalData(tickerId, contract, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH, formatDate, keepUpToDate) .reqIds(numIds) .reqManagedAccts() .reqMarketDataType(marketDataType) -.reqMktData(tickerId, contract, genericTickList, snapshot) +.reqMktData(tickerId, contract, genericTickList, snapshot, regulatorySnapshot) .reqMktDepth(tickerId, contract, numRows) .reqNewsBulletins(allMsgs) .reqOpenOrders() diff --git a/lib/constants.js b/lib/constants.js index cdb5640..44ed691 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -210,9 +210,19 @@ exports.MIN_SERVER_VER = { REQ_HISTORICAL_NEWS : 117, REQ_HEAD_TIMESTAMP : 118, REQ_HISTOGRAM : 119, - SERVICE_DATA_TYPE : 120 + SERVICE_DATA_TYPE : 120, + AGG_GROUP : 121, + UNDERLYING_INFO : 122, + CANCEL_HEADTIMESTAMP : 123, + SYNT_REALTIME_BARS : 124, + CFD_REROUTE : 125, + MARKET_RULES : 126, + PNL : 127, + NEWS_QUERY_ORIGINS : 128, + SERVER_VER_UNREALIZED_PNL : 129 }; - + + exports.BAG_SEC_TYPE = 'BAG'; // FA msg data types @@ -318,7 +328,8 @@ exports.TICK_TYPE = { DELAYED_MODEL_OPTION:83, LAST_EXCH:84, LAST_REG_TIME:85, - NOT_SET:86 + FUTURES_OPEN_INTEREST:86, + UNKNOWN:2147483647 }; exports.EXERCISE_ACTION = { diff --git a/lib/index.js b/lib/index.js index c99bf5d..edbc0d5 100644 --- a/lib/index.js +++ b/lib/index.js @@ -270,7 +270,7 @@ IB.prototype.reqSecDefOptParams = function(reqId, underlyingSymbol, futFopExchan IB.prototype.reqHistoricalData = function (tickerId, contract, endDateTime, durationStr, - barSizeSetting, whatToShow, useRTH, formatDate) { + barSizeSetting, whatToShow, useRTH, formatDate, keepUpToDate) { assert(_.isNumber(tickerId), '"tickerId" must be an integer - ' + tickerId); assert(_.isPlainObject(contract), '"contract" must be a plain object - ' + contract); assert(_.isString(endDateTime), '"endDateTime" must be a string - ' + endDateTime); @@ -279,9 +279,10 @@ IB.prototype.reqHistoricalData = function (tickerId, contract, endDateTime, dura assert(_.isString(whatToShow), '"whatToShow" must be a string - ' + whatToShow); assert(_.isNumber(useRTH), '"useRTH" must be an integer - ' + useRTH); assert(_.isNumber(formatDate), '"formatDate" must be an integer - ' + formatDate); + assert(_.isBoolean(keepUpToDate), '"keepUpToDate" must be an boolean - ' + keepUpToDate); this._send('reqHistoricalData', tickerId, contract, endDateTime, durationStr, - barSizeSetting, whatToShow, useRTH, formatDate); + barSizeSetting, whatToShow, useRTH, formatDate, keepUpToDate); return this; }; @@ -308,13 +309,14 @@ IB.prototype.reqMarketDataType = function (marketDataType) { return this; }; -IB.prototype.reqMktData = function (tickerId, contract, genericTickList, snapshot) { +IB.prototype.reqMktData = function (tickerId, contract, genericTickList, snapshot, regulatorySnapshot) { assert(_.isNumber(tickerId), '"tickerId" must be an integer - ' + tickerId); assert(_.isPlainObject(contract), '"contract" must be a plain object - ' + contract); assert(_.isString(genericTickList), '"genericTickList" must be a string - ' + genericTickList); assert(_.isBoolean(snapshot), '"snapshot" must be a boolean - ' + snapshot); + assert(_.isBoolean(regulatorySnapshot), '"regulatorySnapshot" must be a boolean - ' + regulatorySnapshot); - this._send('reqMktData', tickerId, contract, genericTickList, snapshot); + this._send('reqMktData', tickerId, contract, genericTickList, snapshot, regulatorySnapshot); return this; }; diff --git a/lib/outgoing.js b/lib/outgoing.js index 3301f3c..000eda0 100644 --- a/lib/outgoing.js +++ b/lib/outgoing.js @@ -954,8 +954,8 @@ Outgoing.prototype.reqGlobalCancel = function () { }; Outgoing.prototype.reqHistoricalData = function (tickerId, contract, endDateTime, durationStr, - barSizeSetting, whatToShow, useRTH, formatDate) { - var version = 5; + barSizeSetting, whatToShow, useRTH, formatDate, keepUpToDate) { + var version = 6; if (this._controller._serverVersion < 16) { return this._controller.emitError('It does not support historical data backfill.'); @@ -1006,8 +1006,6 @@ Outgoing.prototype.reqHistoricalData = function (tickerId, contract, endDateTime args.push(formatDate); } - - if (_.isString(contract.secType) && C.BAG_SEC_TYPE.toUpperCase() === contract.secType.toUpperCase()) { if (!_.isArray(contract.comboLegs)) { @@ -1023,6 +1021,14 @@ Outgoing.prototype.reqHistoricalData = function (tickerId, contract, endDateTime }); } } + + if (this._controller._serverVersion >= C.MIN_SERVER_VER.SYNT_REALTIME_BARS) { + args.push(keepUpToDate); + } + + if (this._controller._serverVersion >= C.MIN_SERVER_VER.LINKING) { + args.push(""); + } this._send(args); }; @@ -1049,7 +1055,7 @@ Outgoing.prototype.reqMarketDataType = function (marketDataType) { this._send(C.OUTGOING.REQ_MARKET_DATA_TYPE, version, marketDataType); }; -Outgoing.prototype.reqMktData = function (tickerId, contract, genericTickList, snapshot) { +Outgoing.prototype.reqMktData = function (tickerId, contract, genericTickList, snapshot, regulatorySnapshot) { if (this._controller._serverVersion < C.MIN_SERVER_VER.SNAPSHOT_MKT_DATA && snapshot) { return this._controller.emitError('It does not support snapshot market data requests.'); } @@ -1068,7 +1074,7 @@ Outgoing.prototype.reqMktData = function (tickerId, contract, genericTickList, s } } - var version = 10; + var version = 11; var args = [C.OUTGOING.REQ_MKT_DATA, version, tickerId]; @@ -1143,6 +1149,14 @@ Outgoing.prototype.reqMktData = function (tickerId, contract, genericTickList, s if (this._controller._serverVersion >= C.MIN_SERVER_VER.SNAPSHOT_MKT_DATA) { args.push(snapshot); } + + if (this._controller._serverVersion >= C.MIN_SERVER_VER.REQ_SMART_COMPONENTS) { + args.push(regulatorySnapshot); + } + + if (this._controller._serverVersion >= C.MIN_SERVER_VER.LINKING) { + args.push(""); + } this._send(args); }; diff --git a/lib/util.js b/lib/util.js index c83282c..a89e83a 100644 --- a/lib/util.js +++ b/lib/util.js @@ -6,6 +6,8 @@ function _findKeyForValue(object, value) { return key; } } + + return C.TICK_TYPE.UNKNOWN; } function incomingToString(incoming) { diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b391cef --- /dev/null +++ b/package-lock.json @@ -0,0 +1,661 @@ +{ + "name": "ib", + "version": "0.1.26", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "requires": { + "underscore": "1.7.0", + "underscore.string": "2.4.0" + }, + "dependencies": { + "underscore.string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz", + "integrity": "sha1-ePlIXNFhtWbppsctcXDEJw6B22E=", + "dev": true, + "requires": { + "glob": "3.1.21" + } + }, + "coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "command-buffer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/command-buffer/-/command-buffer-0.1.0.tgz", + "integrity": "sha1-ztP0D3cokxTbkct37zsAwzLo4mg=" + }, + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "console-browserify": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz", + "integrity": "sha1-0SijwLuINQ61YmxufHGm8P1ImDw=", + "dev": true + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", + "dev": true + }, + "diff": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz", + "integrity": "sha1-JLuwAcSn1VIhaefKvbLCgU7ZHPQ=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "faye-websocket": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz", + "integrity": "sha1-wUxbO/FNdBf/v9mQwKdJXNnzN7w=", + "dev": true + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "requires": { + "glob": "3.2.11", + "lodash": "2.4.2" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "function-rate-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function-rate-limit/-/function-rate-limit-1.1.0.tgz", + "integrity": "sha1-7M3xr5GPyVnrZQkFhgPkYuN/1oM=" + }, + "gaze": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.4.3.tgz", + "integrity": "sha1-5Tj0/15P5kj0c6l+HrslPS3hJ7U=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "growl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz", + "integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto=", + "dev": true + }, + "grunt": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "dev": true, + "requires": { + "async": "0.1.22", + "coffee-script": "1.3.3", + "colors": "0.6.2", + "dateformat": "1.0.2-1.2.3", + "eventemitter2": "0.4.14", + "exit": "0.1.2", + "findup-sync": "0.1.3", + "getobject": "0.1.0", + "glob": "3.1.21", + "grunt-legacy-log": "0.1.3", + "grunt-legacy-util": "0.2.0", + "hooker": "0.2.3", + "iconv-lite": "0.2.11", + "js-yaml": "2.0.5", + "lodash": "0.9.2", + "minimatch": "0.2.14", + "nopt": "1.0.10", + "rimraf": "2.2.8", + "underscore.string": "2.2.1", + "which": "1.0.9" + }, + "dependencies": { + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + } + } + }, + "grunt-contrib-jshint": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-0.7.2.tgz", + "integrity": "sha1-KYWd3PQuf2xUxD/nXaPEvZA4So4=", + "dev": true, + "requires": { + "jshint": "2.3.0" + } + }, + "grunt-contrib-watch": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-0.5.3.tgz", + "integrity": "sha1-fZ61Rl1Qb6FPqspH5uh5CoLBye4=", + "dev": true, + "requires": { + "gaze": "0.4.3", + "tiny-lr": "0.0.4" + } + }, + "grunt-legacy-log": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "dev": true, + "requires": { + "colors": "0.6.2", + "grunt-legacy-log-utils": "0.1.1", + "hooker": "0.2.3", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "dev": true, + "requires": { + "colors": "0.6.2", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "dev": true, + "requires": { + "async": "0.1.22", + "exit": "0.1.2", + "getobject": "0.1.0", + "hooker": "0.2.3", + "lodash": "0.9.2", + "underscore.string": "2.2.1", + "which": "1.0.9" + }, + "dependencies": { + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + } + } + }, + "grunt-mocha-test": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.7.0.tgz", + "integrity": "sha1-mjx/QoOyTBePBost1miQYj6V7rs=", + "dev": true, + "requires": { + "mocha": "1.13.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true, + "requires": { + "argparse": "0.1.16", + "esprima": "1.0.4" + } + }, + "jshint": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.3.0.tgz", + "integrity": "sha1-GVBEVaLCDEbuGDNh64fzocC33Ec=", + "dev": true, + "requires": { + "cli": "0.4.5", + "console-browserify": "0.1.6", + "minimatch": "0.2.14", + "shelljs": "0.1.4", + "underscore": "1.4.4" + }, + "dependencies": { + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + } + } + }, + "lodash": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.6.1.tgz", + "integrity": "sha1-3wDBFkrSNrGDz8OIel6NOMxjy7w=" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "matchdep": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-0.3.0.tgz", + "integrity": "sha1-Qo5knOXCgY0iDgRj7/XA3p5Z1S4=", + "dev": true, + "requires": { + "findup-sync": "0.1.3", + "globule": "0.1.0", + "resolve": "0.5.1", + "stack-trace": "0.0.7" + } + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "mocha": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.13.0.tgz", + "integrity": "sha1-jY+k4xC5TMbv6z7SauypbeqTMHw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "debug": "0.7.4", + "diff": "1.0.7", + "glob": "3.2.3", + "growl": "1.7.0", + "jade": "0.26.3", + "mkdirp": "0.3.5" + }, + "dependencies": { + "glob": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true, + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + } + } + }, + "moment": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.4.0.tgz", + "integrity": "sha1-Bt2N+7/bU6A1EAgKx4gWPJSQ510=", + "dev": true + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "noptify": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/noptify/-/noptify-0.0.3.tgz", + "integrity": "sha1-WPZUpz2XU98MUdlobckhBKZ/S7s=", + "dev": true, + "requires": { + "nopt": "2.0.0" + }, + "dependencies": { + "nopt": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.0.0.tgz", + "integrity": "sha1-ynQW8gpeP5w7hhgPlilfo9C1Lg0=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + } + } + }, + "qs": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz", + "integrity": "sha1-MbGtBYVnZRxSaSFQa5qHk5EaA4Q=", + "dev": true + }, + "resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.5.1.tgz", + "integrity": "sha1-FeSiIsQja81M+FRUQSwtD7ZSRXY=", + "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "shelljs": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz", + "integrity": "sha1-37vnjVbDwBaNL7eeEOzR28sH7A4=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "stack-trace": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.7.tgz", + "integrity": "sha1-xy4Il0T8Nln1CM3ONiGvVjTsD/8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tiny-lr": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.0.4.tgz", + "integrity": "sha1-gGGFR/Y/aX0Fy0DEwsSwg1Ia77Y=", + "dev": true, + "requires": { + "debug": "0.7.4", + "faye-websocket": "0.4.4", + "noptify": "0.0.3", + "qs": "0.5.6" + } + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index a936b85..79b757c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ib", "description": "Interactive Brokers TWS (or IB Gateway) API client library for Node.js", - "version": "0.1.25", + "version": "0.1.26", "license": "MIT", "author": { "name": "Pilwon Huh", diff --git a/ref/client/AnyWrapper.java b/ref/client/AnyWrapper.java deleted file mode 100644 index 9a45995..0000000 --- a/ref/client/AnyWrapper.java +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.client; - -public interface AnyWrapper { - void error( Exception e); - void error( String str); - void error(int id, int errorCode, String errorMsg); - void connectionClosed(); -} - diff --git a/ref/client/AnyWrapperMsgGenerator.java b/ref/client/AnyWrapperMsgGenerator.java deleted file mode 100644 index 5aed303..0000000 --- a/ref/client/AnyWrapperMsgGenerator.java +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.client; - -public class AnyWrapperMsgGenerator { - public static String error( Exception ex) { return "Error - " + ex;} - public static String error( String str) { return str;} - - public static String error(int id, int errorCode, String errorMsg) { - String err = Integer.toString(id); - err += " | "; - err += Integer.toString(errorCode); - err += " | "; - err += errorMsg; - return err; - } - - public static String connectionClosed() { - return "Connection Closed"; - } -} diff --git a/ref/client/Bar.java b/ref/client/Bar.java new file mode 100644 index 0000000..9a24acd --- /dev/null +++ b/ref/client/Bar.java @@ -0,0 +1,57 @@ +package com.ib.client; + +public class Bar { + + private String m_time; + private double m_open; + private double m_high; + private double m_low; + private double m_close; + private long m_volume; + private int m_count; + private double m_wap; + + public Bar(String time, double open, double high, double low, double close, long volume, int count, double wap) { + this.m_time = time; + this.m_open = open; + this.m_high = high; + this.m_low = low; + this.m_close = close; + this.m_volume = volume; + this.m_count = count; + this.m_wap = wap; + } + + public String time() { + return m_time; + } + + public double open() { + return m_open; + } + + public double high() { + return m_high; + } + + public double low() { + return m_low; + } + + public double close() { + return m_close; + } + + public long volume() { + return m_volume; + } + + public int count() { + return m_count; + } + + public double wap() { + return m_wap; + } + +} \ No newline at end of file diff --git a/ref/client/BitMask.java b/ref/client/BitMask.java new file mode 100644 index 0000000..21998bd --- /dev/null +++ b/ref/client/BitMask.java @@ -0,0 +1,39 @@ +package com.ib.client; + +public class BitMask { + + private int m_mask = 0; + + public BitMask(int mask) { + m_mask = mask; + } + + public int getMask() { + return m_mask; + } + + public void clear() { + m_mask = 0; + } + + public boolean get(int index) { + if (index >= 32) { + throw new IndexOutOfBoundsException(); + } + + return (m_mask & (1 << index)) != 0; + } + + public boolean set(int index, boolean element) { + boolean res = get(index); + + if (element) { + m_mask |= 1 << index; + } else { + m_mask &= ~(1 << index); + } + + return res; + } + +} diff --git a/ref/client/Builder.java b/ref/client/Builder.java index c6849ae..f7ae6e8 100644 --- a/ref/client/Builder.java +++ b/ref/client/Builder.java @@ -1,20 +1,39 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.nio.charset.StandardCharsets; + /** This class is used to build messages so the entire message can be * sent to the socket in a single write. */ -public class Builder { +public class Builder implements ObjectOutput { private static final char SEP = 0; + private static final byte[] EMPTY_LENGTH_HEADER = new byte[ 4 ]; + + private final ByteBuffer m_sb; - private StringBuilder m_sb = new StringBuilder( 4096); + public Builder( int size ) { + m_sb = new ByteBuffer( size ); + } public void send(int a) { + send( String.valueOf(a) ); + } + + public void sendMax(int a) { send( a == Integer.MAX_VALUE ? "" : String.valueOf( a) ); } public void send(double a) { + send( String.valueOf( a) ); + } + + public void sendMax(double a) { send( a == Double.MAX_VALUE ? "" : String.valueOf( a) ); } @@ -23,21 +42,106 @@ public void send( boolean a) { } public void send( IApiEnum a) { - send( a.getApiString() ); + send( a == null ? null : a.getApiString() ); } public void send( String a) { if (a != null) { - m_sb.append( a); + byte[] buffer = a.getBytes(StandardCharsets.UTF_8); + m_sb.write( buffer, 0, buffer.length ); } - m_sb.append( SEP); + m_sb.write( SEP); } - public String toString() { - return m_sb.toString(); - } + public void send( byte[] bytes ) { + if ( bytes != null ) { + m_sb.write( bytes, 0, bytes.length ); + } + } + + public int allocateLengthHeader() { + int lengthHeaderPosition = m_sb.size(); + m_sb.write( EMPTY_LENGTH_HEADER, 0, EMPTY_LENGTH_HEADER.length ); + return lengthHeaderPosition; + } + + public void updateLength( int lengthHeaderPosition ) { + m_sb.updateLength( lengthHeaderPosition ); + } + + public void writeTo( DataOutputStream dos ) throws IOException { + m_sb.writeTo( dos ); + } + + // b[] must be at least b[position+4] + static void intToBytes(int val, byte b[], int position) { + b[position] = (byte)(0xff & (val >> 24)); + b[position+1] = (byte)(0xff & (val >> 16)); + b[position+2] = (byte)(0xff & (val >> 8)); + b[position+3] = (byte)(0xff & val); + } + + /** inner class: ByteBuffer - storage for bytes and direct access to buffer. */ + private static class ByteBuffer extends ByteArrayOutputStream { + private final int paddingSize; // 1 disables padding, 4 is normal if padding is used + + ByteBuffer(int capacity) { + super( capacity ); + paddingSize = 1; + } + + void updateLength(int lengthHeaderPosition) { + int len = this.count - EMPTY_LENGTH_HEADER.length - lengthHeaderPosition; + if ( paddingSize > 1 ) { + int padding = paddingSize - len%paddingSize; + if ( padding < paddingSize ) { + this.write( EMPTY_LENGTH_HEADER, 0, paddingSize ); // extra padding at the end + len = this.count - EMPTY_LENGTH_HEADER.length - lengthHeaderPosition; + } + } + intToBytes(len, this.buf, lengthHeaderPosition); + } + + void writeTo(DataOutputStream out) throws IOException { + out.write( this.buf, 0, this.count ); + } + } - public byte[] getBytes() { - return m_sb.toString().getBytes(); + @Override + public void writeBoolean(boolean arg0) throws IOException { send(arg0); } + @Override + public void writeByte(int arg0) throws IOException { send(arg0); } + @Override + public void writeBytes(String arg0) throws IOException { send(arg0); } + @Override + public void writeChar(int arg0) throws IOException { send(arg0); } + @Override + public void writeChars(String arg0) throws IOException { send(arg0); } + @Override + public void writeDouble(double arg0) throws IOException { send(arg0); } + @Override + public void writeFloat(float arg0) throws IOException { send(arg0); } + @Override + public void writeInt(int arg0) throws IOException { send(arg0); } + @Override + public void writeLong(long arg0) throws IOException { send(arg0); } + @Override + public void writeShort(int arg0) throws IOException { send(arg0); } + @Override + public void writeUTF(String arg0) throws IOException { send(arg0); } + @Override + public void close() throws IOException { + m_sb.close(); } + @Override + public void flush() throws IOException { } + @Override + public void write(int arg0) throws IOException { } + @Override + public void write(byte[] arg0) throws IOException { } + @Override + public void write(byte[] arg0, int arg1, int arg2) + throws IOException { } + @Override + public void writeObject(Object arg0) throws IOException { } } diff --git a/ref/client/ComboLeg.java b/ref/client/ComboLeg.java index bda5562..2f90156 100644 --- a/ref/client/ComboLeg.java +++ b/ref/client/ComboLeg.java @@ -3,22 +3,55 @@ package com.ib.client; +import com.ib.client.Types.Action; + public class ComboLeg { - public final static int SAME = 0; // open/close leg value is same as combo - public final static int OPEN = 1; - public final static int CLOSE = 2; - public final static int UNKNOWN = 3; + public enum OpenClose implements IApiEnum { + Same, Open, Close, Unknown; + + static OpenClose get( int i) { + return Types.getEnum( i, values() ); + } - public int m_conId; - public int m_ratio; - public String m_action; // BUY/SELL/SSHORT/SSHORTX - public String m_exchange; - public int m_openClose; + @Override + public String getApiString() { + return String.valueOf(ordinal()); + } + } + private int m_conid; + private int m_ratio; + private String m_action = "BUY"; // BUY/SELL/SSHORT/SSHORTX + private String m_exchange; + private int m_openClose = 0; // Same // for stock legs when doing short sale - public int m_shortSaleSlot; // 1 = clearing broker, 2 = third party - public String m_designatedLocation; - public int m_exemptCode; + private int m_shortSaleSlot; // 1 = clearing broker, 2 = third party + private String m_designatedLocation; + private int m_exemptCode; + + // Get + public Action action() { return Action.get(m_action); } + public String getAction() { return m_action; } + public int conid() { return m_conid; } + public int exemptCode() { return m_exemptCode; } + public int ratio() { return m_ratio; } + public int shortSaleSlot() { return m_shortSaleSlot; } + public OpenClose openClose() { return OpenClose.get(m_openClose); } + public int getOpenClose() { return m_openClose; } + public String designatedLocation() { return m_designatedLocation; } + public String exchange() { return m_exchange; } + + // Set + public void action(Action v) { m_action = ( v == null ) ? null : v.getApiString(); } + public void action(String v) { m_action = v; } + public void conid(int v) { m_conid = v; } + public void designatedLocation(String v) { m_designatedLocation = v; } + public void exchange(String v) { m_exchange = v; } + public void exemptCode(int v) { m_exemptCode = v; } + public void openClose(OpenClose v) { m_openClose = ( v == null ) ? 0 : v.ordinal(); } + public void openClose(int v) { m_openClose = v; } + public void ratio(int v) { m_ratio = v; } + public void shortSaleSlot(int v) { m_shortSaleSlot = v; } public ComboLeg() { this(/* conId */ 0, /* ratio */ 0, /* action */ null, @@ -41,7 +74,7 @@ public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange, public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange, int p_openClose, int p_shortSaleSlot, String p_designatedLocation, int p_exemptCode) { - m_conId = p_conId; + m_conid = p_conId; m_ratio = p_ratio; m_action = p_action; m_exchange = p_exchange; @@ -51,17 +84,18 @@ public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange, m_exemptCode = p_exemptCode; } + @Override public boolean equals(Object p_other) { - if ( this == p_other ) { + if (this == p_other) { return true; } - else if ( p_other == null ) { + if (!(p_other instanceof ComboLeg)) { return false; } ComboLeg l_theOther = (ComboLeg)p_other; - if (m_conId != l_theOther.m_conId || + if (m_conid != l_theOther.m_conid || m_ratio != l_theOther.m_ratio || m_openClose != l_theOther.m_openClose || m_shortSaleSlot != l_theOther.m_shortSaleSlot || @@ -77,4 +111,19 @@ else if ( p_other == null ) { return true; } + + @Override + public int hashCode() { + int result = m_conid; + result = result * 31 + m_ratio; + result = result * 31 + m_openClose; + result = result * 31 + m_shortSaleSlot; + result = result * 31 + m_exemptCode; + // Other fields are strings compared ignoring case and with null checks. Do not use them. + return result; + } + + @Override public String toString() { + return String.format( "%s %s %s", m_action, m_ratio, m_conid); + } } diff --git a/ref/client/CommissionReport.java b/ref/client/CommissionReport.java index 064cc47..38107bc 100644 --- a/ref/client/CommissionReport.java +++ b/ref/client/CommissionReport.java @@ -19,19 +19,21 @@ public CommissionReport() { m_yieldRedemptionDate = 0; } + @Override public boolean equals(Object p_other) { - boolean l_bRetVal = false; - - if ( p_other == null ) { - l_bRetVal = false; - } - else if ( this == p_other ) { - l_bRetVal = true; + if (this == p_other) { + return true; } - else { - CommissionReport l_theOther = (CommissionReport)p_other; - l_bRetVal = m_execId.equals( l_theOther.m_execId); + if (!(p_other instanceof CommissionReport)) { + return false; } - return l_bRetVal; + CommissionReport l_theOther = (CommissionReport)p_other; + return m_execId.equals(l_theOther.m_execId); + } + + @Override + public int hashCode() { + // Since equals() uses m_execId only, the hashCode should do as well. + return m_execId == null ? 0 : m_execId.hashCode(); } } diff --git a/ref/client/Contract.java b/ref/client/Contract.java index f076e2c..cdd7275 100644 --- a/ref/client/Contract.java +++ b/ref/client/Contract.java @@ -1,58 +1,115 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; -import java.util.Vector; +import java.util.ArrayList; +import java.util.List; -public class Contract implements Cloneable { - - public int m_conId; - public String m_symbol; - public String m_secType; - public String m_expiry; - public double m_strike; - public String m_right; - public String m_multiplier; - public String m_exchange; - - public String m_currency; - public String m_localSymbol; - public String m_tradingClass; - public String m_primaryExch; // pick a non-aggregate (ie not the SMART exchange) exchange that the contract trades on. DO NOT SET TO SMART. - public boolean m_includeExpired; // can not be set to true for orders. +import com.ib.client.Types.Right; +import com.ib.client.Types.SecIdType; +import com.ib.client.Types.SecType; - public String m_secIdType; // CUSIP;SEDOL;ISIN;RIC - public String m_secId; +public class Contract implements Cloneable { + private int m_conid; + private String m_symbol; + private String m_secType; + private String m_lastTradedateOrContractMonth; + private double m_strike; + private String m_right; + private String m_multiplier; // should be double + private String m_exchange; + private String m_primaryExch; // pick a non-aggregate (ie not the SMART exchange) exchange that the contract trades on. DO NOT SET TO SMART. + private String m_currency; + private String m_localSymbol; + private String m_tradingClass; + private String m_secIdType; // CUSIP;SEDOL;ISIN;RIC + private String m_secId; + private DeltaNeutralContract m_underComp; + private boolean m_includeExpired; // can not be set to true for orders // COMBOS - public String m_comboLegsDescrip; // received in open order version 14 and up for all combos - public Vector m_comboLegs = new Vector(); + private String m_comboLegsDescrip; // received in open order version 14 and up for all combos + private List m_comboLegs = new ArrayList<>(); // would be final except for clone + + // Get + public double strike() { return m_strike; } + public int conid() { return m_conid; } + public SecIdType secIdType() { return SecIdType.get(m_secIdType); } + public String getSecIdType() { return m_secIdType; } + public SecType secType() { return SecType.get(m_secType); } + public String getSecType() { return m_secType; } + public String currency() { return m_currency; } + public String exchange() { return m_exchange; } + public String primaryExch() { return m_primaryExch; } + public String lastTradeDateOrContractMonth() { return m_lastTradedateOrContractMonth; } + public String localSymbol() { return m_localSymbol; } + public String tradingClass() { return m_tradingClass; } + public String multiplier() { return m_multiplier; } + public Right right() { return Right.get(m_right); } + public String getRight() { return m_right; } + public String secId() { return m_secId; } + public String symbol() { return m_symbol; } + public boolean includeExpired() { return m_includeExpired; } + public DeltaNeutralContract underComp() { return m_underComp; } + public List comboLegs() { return m_comboLegs; } + public String comboLegsDescrip() { return m_comboLegsDescrip; } - // delta neutral - public UnderComp m_underComp; + // Set + public void conid(int v) { m_conid = v; } + public void currency(String v) { m_currency = v; } + public void exchange(String v) { m_exchange = v; } + public void lastTradeDateOrContractMonth(String v) { m_lastTradedateOrContractMonth = v; } + public void localSymbol(String v) { m_localSymbol = v; } + public void tradingClass(String v) { m_tradingClass = v; } + public void multiplier(String v) { m_multiplier = v; } + public void primaryExch(String v) { m_primaryExch = v; } + public void right(Right v) { m_right = ( v == null ) ? null : v.getApiString(); } + public void right(String v) { m_right = v; } + public void secId(String v) { m_secId = v; } + public void secIdType(SecIdType v) { m_secIdType = ( v == null ) ? null : v.getApiString(); } + public void secIdType(String v) { m_secIdType = v; } + public void secType(SecType v) { m_secType = ( v == null ) ? null : v.getApiString(); } + public void secType(String v) { m_secType = v; } + public void strike(double v) { m_strike = v; } + public void symbol(String v) { m_symbol = v; } + public void underComp(DeltaNeutralContract v) { m_underComp = v; } + public void includeExpired(boolean v) { m_includeExpired = v; } + public void comboLegs(List v) { m_comboLegs = v; } + public void comboLegsDescrip(String v) { m_comboLegsDescrip = v; } public Contract() { - m_conId = 0; + m_conid = 0; m_strike = 0; m_includeExpired = false; } - public Object clone() throws CloneNotSupportedException { - Contract retval = (Contract)super.clone(); - retval.m_comboLegs = (Vector)retval.m_comboLegs.clone(); - return retval; + @Override public Contract clone() { + try { + Contract copy = (Contract)super.clone(); + if ( copy.m_comboLegs != null ) { + copy.m_comboLegs = new ArrayList<>( copy.m_comboLegs); + } + else { + copy.m_comboLegs = new ArrayList<>(); + } + return copy; + } + catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } } - public Contract(int p_conId, String p_symbol, String p_secType, String p_expiry, + public Contract(int p_conId, String p_symbol, String p_secType, String p_lastTradeDateOrContractMonth, double p_strike, String p_right, String p_multiplier, String p_exchange, String p_currency, String p_localSymbol, String p_tradingClass, - Vector p_comboLegs, String p_primaryExch, boolean p_includeExpired, + List p_comboLegs, String p_primaryExch, boolean p_includeExpired, String p_secIdType, String p_secId) { - m_conId = p_conId; + m_conid = p_conId; m_symbol = p_symbol; m_secType = p_secType; - m_expiry = p_expiry; + m_lastTradedateOrContractMonth = p_lastTradeDateOrContractMonth; m_strike = p_strike; m_right = p_right; m_multiplier = p_multiplier; @@ -67,8 +124,8 @@ public Contract(int p_conId, String p_symbol, String p_secType, String p_expiry, m_secId = p_secId ; } + @Override public boolean equals(Object p_other) { - if (this == p_other) { return true; } @@ -79,7 +136,7 @@ public boolean equals(Object p_other) { Contract l_theOther = (Contract)p_other; - if (m_conId != l_theOther.m_conId) { + if (m_conid != l_theOther.m_conid) { return false; } @@ -94,13 +151,13 @@ public boolean equals(Object p_other) { return false; } - if (!Util.NormalizeString(m_secType).equals("BOND")) { + if (!"BOND".equals(m_secType)) { if (m_strike != l_theOther.m_strike) { return false; } - if (Util.StringCompare(m_expiry, l_theOther.m_expiry) != 0 || + if (Util.StringCompare(m_lastTradedateOrContractMonth, l_theOther.m_lastTradedateOrContractMonth) != 0 || Util.StringCompare(m_right, l_theOther.m_right) != 0 || Util.StringCompare(m_multiplier, l_theOther.m_multiplier) != 0 || Util.StringCompare(m_localSymbol, l_theOther.m_localSymbol) != 0 || @@ -118,7 +175,7 @@ public boolean equals(Object p_other) { } // compare combo legs - if (!Util.VectorEqualsUnordered(m_comboLegs, l_theOther.m_comboLegs)) { + if (!Util.listsEqualUnordered(m_comboLegs, l_theOther.m_comboLegs)) { return false; } @@ -130,7 +187,94 @@ public boolean equals(Object p_other) { return false; } } - return true; } + + @Override + public int hashCode() { + // Use a few fields only as a compromise between performance and hashCode quality. + int result = m_conid; + result = result * 31 + (m_symbol == null || "".equals(m_symbol) ? 0 : m_symbol.hashCode()); + long temp = Double.doubleToLongBits(m_strike); + result = result * 31 + (int) (temp ^ (temp >>> 32)); + return result; + } + + /** Returns a text description that can be used for display. */ + public String description() { + StringBuilder sb = new StringBuilder(); + + if (isCombo() ) { + int i = 0; + for (ComboLeg leg : m_comboLegs) { + if (i++ > 0) { + sb.append( "/"); + } + sb.append( leg.toString() ); + } + } + else { + sb.append( m_symbol); + app( sb, m_secType); + app( sb, m_exchange); + + if (m_exchange != null && m_exchange.equals( "SMART") && m_primaryExch != null) { + app( sb, m_primaryExch); + } + + app( sb, m_lastTradedateOrContractMonth); + + if (m_strike != 0) { + app( sb, m_strike); + } + + if( !Util.StringIsEmpty(m_right) ) { + app( sb, m_right); + } + } + return sb.toString(); + } + + private static void app(StringBuilder buf, Object obj) { + if (obj != null) { + buf.append( " "); + buf.append( obj); + } + } + + public boolean isCombo() { + return m_comboLegs.size() > 0; + } + + @Override public String toString() { + StringBuilder sb = new StringBuilder(); + + add( sb, "conid", m_conid); + add( sb, "symbol", m_symbol); + add( sb, "secType", m_secType); + add( sb, "lastTradeDateOrContractMonth", m_lastTradedateOrContractMonth); + add( sb, "strike", m_strike); + add( sb, "right", m_right); + add( sb, "multiplier", m_multiplier); + add( sb, "exchange", m_exchange); + add( sb, "currency", m_currency); + add( sb, "localSymbol", m_localSymbol); + add( sb, "tradingClass", m_tradingClass); + add( sb, "primaryExch", m_primaryExch); + add( sb, "secIdType", m_secIdType); + add( sb, "secId", m_secId); + + return sb.toString(); + } + + public static void add(StringBuilder sb, String tag, Object val) { + if (val == null || val instanceof String && ((String)val).length() == 0) { + return; + } + + sb.append( tag); + sb.append( '\t'); + sb.append( val); + sb.append( '\n'); + } } diff --git a/ref/client/ContractCondition.java b/ref/client/ContractCondition.java new file mode 100644 index 0000000..d61c34c --- /dev/null +++ b/ref/client/ContractCondition.java @@ -0,0 +1,62 @@ +package com.ib.client; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.List; + +public abstract class ContractCondition extends OperatorCondition { + + @Override + public String toString() { + return toString(null); + } + + public String toString(ContractLookuper lookuper) { + Contract c = new Contract(); + + c.conid(conId()); + c.exchange(exchange()); + + List list = lookuper == null ? null : lookuper.lookupContract(c); + String strContract = list != null && !list.isEmpty() ? + list.get(0).contract().symbol() + " " + list.get(0).contract().secType() + " on " + list.get(0).contract().exchange() : + conId() + ""; + + return type() + " of " + strContract + super.toString(); + } + + private int m_conId; + private String m_exchange; + + @Override + public void readFrom(ObjectInput in) throws IOException { + super.readFrom(in); + + m_conId = in.readInt(); + m_exchange = in.readUTF(); + } + + @Override + public void writeTo(ObjectOutput out) throws IOException { + super.writeTo(out); + out.writeInt(m_conId); + out.writeUTF(m_exchange); + } + + public int conId() { + return m_conId; + } + + public void conId(int m_conId) { + this.m_conId = m_conId; + } + + public String exchange() { + return m_exchange; + } + + public void exchange(String exchange) { + this.m_exchange = exchange; + } +} \ No newline at end of file diff --git a/ref/client/ContractDescription.java b/ref/client/ContractDescription.java new file mode 100644 index 0000000..5944962 --- /dev/null +++ b/ref/client/ContractDescription.java @@ -0,0 +1,56 @@ +/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +import java.util.Arrays; + +public class ContractDescription { + private Contract m_contract; + private String[] m_derivativeSecTypes; + + // Get + public Contract contract() { + return m_contract; + } + + public String[] derivativeSecTypes() { + return (m_derivativeSecTypes == null) ? null : Arrays.copyOf(m_derivativeSecTypes, m_derivativeSecTypes.length); + } + + // Set + public void contract(Contract contract) { + m_contract = contract; + } + + public void derivativeSecTypes(String[] derivativeSecTypes) { + if (derivativeSecTypes == null) { + m_derivativeSecTypes = null; + } else { + m_derivativeSecTypes = Arrays.copyOf(derivativeSecTypes, derivativeSecTypes.length); + } + } + + public ContractDescription() { + m_contract = new Contract(); + } + + public ContractDescription(Contract p_contract, String[] p_derivativeSecTypes) { + m_contract = p_contract; + if (p_derivativeSecTypes == null) { + m_derivativeSecTypes = null; + } else { + m_derivativeSecTypes = Arrays.copyOf(p_derivativeSecTypes, p_derivativeSecTypes.length); + } + } + + @Override + public String toString() { + return "conid: " + m_contract.conid() + "\n" + + "symbol: " + m_contract.symbol() + "\n" + + "secType: " + m_contract.secType().toString() + "\n" + + "primaryExch: " + m_contract.primaryExch() + "\n" + + "currency: " + m_contract.currency() + "\n" + + "derivativeSecTypes: " + Arrays.toString(m_derivativeSecTypes) + "\n"; + } +} diff --git a/ref/client/ContractDetails.java b/ref/client/ContractDetails.java index eff01fd..e920e34 100644 --- a/ref/client/ContractDetails.java +++ b/ref/client/ContractDetails.java @@ -3,64 +3,152 @@ package com.ib.client; -import java.util.Vector; +import java.util.List; public class ContractDetails { - public Contract m_summary; - public String m_marketName; - public double m_minTick; - public int m_priceMagnifier; - public String m_orderTypes; - public String m_validExchanges; - public int m_underConId; - public String m_longName; - public String m_contractMonth; - public String m_industry; - public String m_category; - public String m_subcategory; - public String m_timeZoneId; - public String m_tradingHours; - public String m_liquidHours; - public String m_evRule; - public double m_evMultiplier; - - public Vector m_secIdList; // CUSIP/ISIN/etc. + private Contract m_contract; + private String m_marketName; + private double m_minTick; + private int m_priceMagnifier; + private String m_orderTypes; + private String m_validExchanges; + private int m_underConid; + private String m_longName; + private String m_contractMonth; + private String m_industry; + private String m_category; + private String m_subcategory; + private String m_timeZoneId; + private String m_tradingHours; + private String m_liquidHours; + private String m_evRule; + private double m_evMultiplier; + private int m_mdSizeMultiplier; + private List m_secIdList; // CUSIP/ISIN/etc. + private int m_aggGroup; + private String m_underSymbol; + private String m_underSecType; + private String m_marketRuleIds; // BOND values - public String m_cusip; - public String m_ratings; - public String m_descAppend; - public String m_bondType; - public String m_couponType; - public boolean m_callable = false; - public boolean m_putable = false; - public double m_coupon = 0; - public boolean m_convertible = false; - public String m_maturity; - public String m_issueDate; - public String m_nextOptionDate; - public String m_nextOptionType; - public boolean m_nextOptionPartial = false; - public String m_notes; + private String m_cusip; + private String m_ratings; + private String m_descAppend; + private String m_bondType; + private String m_couponType; + private boolean m_callable = false; + private boolean m_putable = false; + private double m_coupon = 0; + private boolean m_convertible = false; + private String m_maturity; + private String m_issueDate; + private String m_nextOptionDate; + private String m_nextOptionType; + private boolean m_nextOptionPartial = false; + private String m_notes; + + // Get + public int conid() { return m_contract.conid(); } + public Contract contract() { return m_contract; } + public String marketName() { return m_marketName; } + public double minTick() { return m_minTick; } + public int priceMagnifier() { return m_priceMagnifier; } + public String orderTypes() { return m_orderTypes; } + public String validExchanges() { return m_validExchanges; } + public int underConid() { return m_underConid; } + public String longName() { return m_longName; } + public String contractMonth() { return m_contractMonth; } + public String industry() { return m_industry; } + public String category() { return m_category; } + public String subcategory() { return m_subcategory; } + public String timeZoneId() { return m_timeZoneId; } + public String tradingHours() { return m_tradingHours; } + public String liquidHours() { return m_liquidHours; } + public String evRule() { return m_evRule; } + public double evMultiplier() { return m_evMultiplier; } + public int mdSizeMultiplier() { return m_mdSizeMultiplier; } + public List secIdList() { return m_secIdList; } + public int aggGroup() { return m_aggGroup; } + public String underSymbol() { return m_underSymbol; } + public String underSecType() { return m_underSecType; } + public String marketRuleIds() { return m_marketRuleIds; } + + public String cusip() { return m_cusip; } + public String ratings() { return m_ratings; } + public String descAppend() { return m_descAppend; } + public String bondType() { return m_bondType; } + public String couponType() { return m_couponType; } + public boolean callable() { return m_callable; } + public boolean putable() { return m_putable; } + public double coupon() { return m_coupon; } + public boolean convertible() { return m_convertible; } + public String maturity() { return m_maturity; } + public String issueDate() { return m_issueDate; } + public String nextOptionDate() { return m_nextOptionDate; } + public String nextOptionType() { return m_nextOptionType; } + public boolean nextOptionPartial() { return m_nextOptionPartial; } + public String notes() { return m_notes; } + + // Set + public void contract(Contract contract) { m_contract = contract; } + public void marketName(String marketName) { m_marketName = marketName; } + public void minTick(double minTick) { m_minTick = minTick; } + public void priceMagnifier(int priceMagnifier) { m_priceMagnifier = priceMagnifier; } + public void orderTypes(String orderTypes) { m_orderTypes = orderTypes; } + public void validExchanges(String validExchanges) { m_validExchanges = validExchanges; } + public void underConid(int underConid) { m_underConid = underConid; } + public void longName(String longName) { m_longName = longName; } + public void contractMonth(String contractMonth) { m_contractMonth = contractMonth; } + public void industry(String industry) { m_industry = industry; } + public void category(String category) { m_category = category; } + public void subcategory(String subcategory) { m_subcategory = subcategory; } + public void timeZoneId(String timeZoneId) { m_timeZoneId = timeZoneId; } + public void tradingHours(String tradingHours) { m_tradingHours = tradingHours; } + public void liquidHours(String liquidHours) { m_liquidHours = liquidHours; } + public void evRule(String evRule) { m_evRule = evRule; } + public void evMultiplier(double evMultiplier) { m_evMultiplier = evMultiplier; } + public void mdSizeMultiplier(int mdSizeMultiplier) { m_mdSizeMultiplier = mdSizeMultiplier; } + public void secIdList(List secIdList) { m_secIdList = secIdList; } + public void aggGroup(int aggGroup) { m_aggGroup = aggGroup; } + public void underSymbol(String underSymbol) { m_underSymbol = underSymbol; } + public void underSecType(String underSecType) { m_underSecType = underSecType; } + public void marketRuleIds(String marketRuleIds) { m_marketRuleIds = marketRuleIds; } + + public void cusip(String cusip) { m_cusip = cusip; } + public void ratings(String ratings) { m_ratings = ratings; } + public void descAppend(String descAppend) { m_descAppend = descAppend; } + public void bondType(String bondType) { m_bondType = bondType; } + public void couponType(String couponType) { m_couponType = couponType; } + public void callable(boolean callable) { m_callable = callable; } + public void putable(boolean putable) { m_putable = putable; } + public void coupon(double coupon) { m_coupon = coupon; } + public void convertible(boolean convertible) { m_convertible = convertible; } + public void maturity(String maturity) { m_maturity = maturity; } + public void issueDate(String issueDate) { m_issueDate = issueDate; } + public void nextOptionDate(String nextOptionDate) { m_nextOptionDate = nextOptionDate; } + public void nextOptionType(String nextOptionType) { m_nextOptionType = nextOptionType; } + public void nextOptionPartial(boolean nextOptionPartial) { m_nextOptionPartial = nextOptionPartial; } + public void notes(String notes) { m_notes = notes; } public ContractDetails() { - m_summary = new Contract(); + m_contract = new Contract(); m_minTick = 0; - m_underConId = 0; + m_underConid = 0; m_evMultiplier = 0; } - public ContractDetails( Contract p_summary, String p_marketName, + public ContractDetails( Contract p_contract, String p_marketName, double p_minTick, String p_orderTypes, String p_validExchanges, int p_underConId, String p_longName, String p_contractMonth, String p_industry, String p_category, String p_subcategory, String p_timeZoneId, String p_tradingHours, String p_liquidHours, - String p_evRule, double p_evMultiplier) { - m_summary = p_summary; + String p_evRule, double p_evMultiplier, int p_mdSizeMultiplier, int p_aggGroup, + String p_underSymbol, String p_underSecType, String p_marketRuleIds) { + m_contract = p_contract; m_marketName = p_marketName; m_minTick = p_minTick; m_orderTypes = p_orderTypes; m_validExchanges = p_validExchanges; - m_underConId = p_underConId; + m_underConid = p_underConId; m_longName = p_longName; m_contractMonth = p_contractMonth; m_industry = p_industry; @@ -71,5 +159,64 @@ public ContractDetails( Contract p_summary, String p_marketName, m_liquidHours = p_liquidHours; m_evRule = p_evRule; m_evMultiplier = p_evMultiplier; + m_mdSizeMultiplier = p_mdSizeMultiplier; + m_aggGroup = p_aggGroup; + m_underSymbol = p_underSymbol; + m_underSecType = p_underSecType; + m_marketRuleIds = p_marketRuleIds; + } + + @Override public String toString() { + StringBuilder sb = new StringBuilder( m_contract.toString() ); + + add( sb, "marketName", m_marketName); + add( sb, "minTick", m_minTick); + add( sb, "priceMagnifier", m_priceMagnifier); + add( sb, "orderTypes", m_orderTypes); + add( sb, "validExchanges", m_validExchanges); + add( sb, "underConId", m_underConid); + add( sb, "longName", m_longName); + add( sb, "contractMonth", m_contractMonth); + add( sb, "industry", m_industry); + add( sb, "category", m_category); + add( sb, "subcategory", m_subcategory); + add( sb, "timeZoneId", m_timeZoneId); + add( sb, "tradingHours", m_tradingHours); + add( sb, "liquidHours", m_liquidHours); + add( sb, "evRule", m_evRule); + add( sb, "evMultiplier", m_evMultiplier); + add( sb, "mdSizeMultiplier", m_mdSizeMultiplier); + add( sb, "aggGroup", m_aggGroup); + add( sb, "underSymbol", m_underSymbol); + add( sb, "underSecType", m_underSecType); + add( sb, "marketRuleIds", m_marketRuleIds); + + add( sb, "cusip", m_cusip); + add( sb, "ratings", m_ratings); + add( sb, "descAppend", m_descAppend); + add( sb, "bondType", m_bondType); + add( sb, "couponType", m_couponType); + add( sb, "callable", m_callable); + add( sb, "putable", m_putable); + add( sb, "coupon", m_coupon); + add( sb, "convertible", m_convertible); + add( sb, "maturity", m_maturity); + add( sb, "issueDate", m_issueDate); + add( sb, "nextOptionDate", m_nextOptionDate); + add( sb, "nextOptionType", m_nextOptionType); + add( sb, "nextOptionPartial", m_nextOptionPartial); + add( sb, "notes", m_notes); + + return sb.toString(); + } + + public static void add(StringBuilder sb, String tag, Object val) { + if (val == null || val instanceof String && ((String)val).length() == 0) { + return; + } + sb.append( tag); + sb.append( '\t'); + sb.append( val); + sb.append( '\n'); } } diff --git a/ref/client/ContractLookuper.java b/ref/client/ContractLookuper.java new file mode 100644 index 0000000..3dcf59d --- /dev/null +++ b/ref/client/ContractLookuper.java @@ -0,0 +1,7 @@ +package com.ib.client; + +import java.util.List; + +public interface ContractLookuper { + List lookupContract(Contract contract); +} \ No newline at end of file diff --git a/ref/client/DefaultEWrapper.java b/ref/client/DefaultEWrapper.java new file mode 100644 index 0000000..894e319 --- /dev/null +++ b/ref/client/DefaultEWrapper.java @@ -0,0 +1,490 @@ +/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +class DefaultEWrapper implements EWrapper { + + @Override + public void tickPrice(int tickerId, int field, double price, + TickAttr attribs) { + // TODO Auto-generated method stub + + } + + @Override + public void tickSize(int tickerId, int field, int size) { + // TODO Auto-generated method stub + + } + + @Override + public void tickOptionComputation(int tickerId, int field, + double impliedVol, double delta, double optPrice, + double pvDividend, double gamma, double vega, double theta, + double undPrice) { + // TODO Auto-generated method stub + + } + + @Override + public void tickGeneric(int tickerId, int tickType, double value) { + // TODO Auto-generated method stub + + } + + @Override + public void tickString(int tickerId, int tickType, String value) { + // TODO Auto-generated method stub + + } + + @Override + public void tickEFP(int tickerId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate) { + // TODO Auto-generated method stub + + } + + @Override + public void orderStatus(int orderId, String status, double filled, + double remaining, double avgFillPrice, int permId, int parentId, + double lastFillPrice, int clientId, String whyHeld) { + // TODO Auto-generated method stub + + } + + @Override + public void openOrder(int orderId, Contract contract, Order order, + OrderState orderState) { + // TODO Auto-generated method stub + + } + + @Override + public void openOrderEnd() { + // TODO Auto-generated method stub + + } + + @Override + public void updateAccountValue(String key, String value, String currency, + String accountName) { + // TODO Auto-generated method stub + + } + + @Override + public void updatePortfolio(Contract contract, double position, + double marketPrice, double marketValue, double averageCost, + double unrealizedPNL, double realizedPNL, String accountName) { + // TODO Auto-generated method stub + + } + + @Override + public void updateAccountTime(String timeStamp) { + // TODO Auto-generated method stub + + } + + @Override + public void accountDownloadEnd(String accountName) { + // TODO Auto-generated method stub + + } + + @Override + public void nextValidId(int orderId) { + // TODO Auto-generated method stub + + } + + @Override + public void contractDetails(int reqId, ContractDetails contractDetails) { + // TODO Auto-generated method stub + + } + + @Override + public void bondContractDetails(int reqId, ContractDetails contractDetails) { + // TODO Auto-generated method stub + + } + + @Override + public void contractDetailsEnd(int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void execDetails(int reqId, Contract contract, Execution execution) { + // TODO Auto-generated method stub + + } + + @Override + public void execDetailsEnd(int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void updateMktDepth(int tickerId, int position, int operation, + int side, double price, int size) { + // TODO Auto-generated method stub + + } + + @Override + public void updateMktDepthL2(int tickerId, int position, + String marketMaker, int operation, int side, double price, int size) { + // TODO Auto-generated method stub + + } + + @Override + public void updateNewsBulletin(int msgId, int msgType, String message, + String origExchange) { + // TODO Auto-generated method stub + + } + + @Override + public void managedAccounts(String accountsList) { + // TODO Auto-generated method stub + + } + + @Override + public void receiveFA(int faDataType, String xml) { + // TODO Auto-generated method stub + + } + + @Override + public void historicalData(int reqId, Bar bar) { + // TODO Auto-generated method stub + + } + + @Override + public void scannerParameters(String xml) { + // TODO Auto-generated method stub + + } + + @Override + public void scannerData(int reqId, int rank, + ContractDetails contractDetails, String distance, String benchmark, + String projection, String legsStr) { + // TODO Auto-generated method stub + + } + + @Override + public void scannerDataEnd(int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void realtimeBar(int reqId, long time, double open, double high, + double low, double close, long volume, double wap, int count) { + // TODO Auto-generated method stub + + } + + @Override + public void currentTime(long time) { + // TODO Auto-generated method stub + + } + + @Override + public void fundamentalData(int reqId, String data) { + // TODO Auto-generated method stub + + } + + @Override + public void deltaNeutralValidation(int reqId, DeltaNeutralContract underComp) { + // TODO Auto-generated method stub + + } + + @Override + public void tickSnapshotEnd(int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void marketDataType(int reqId, int marketDataType) { + // TODO Auto-generated method stub + + } + + @Override + public void commissionReport(CommissionReport commissionReport) { + // TODO Auto-generated method stub + + } + + @Override + public void position(String account, Contract contract, double pos, + double avgCost) { + // TODO Auto-generated method stub + + } + + @Override + public void positionEnd() { + // TODO Auto-generated method stub + + } + + @Override + public void accountSummary(int reqId, String account, String tag, + String value, String currency) { + // TODO Auto-generated method stub + + } + + @Override + public void accountSummaryEnd(int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void verifyMessageAPI(String apiData) { + // TODO Auto-generated method stub + + } + + @Override + public void verifyCompleted(boolean isSuccessful, String errorText) { + // TODO Auto-generated method stub + + } + + @Override + public void verifyAndAuthMessageAPI(String apiData, String xyzChallenge) { + // TODO Auto-generated method stub + + } + + @Override + public void verifyAndAuthCompleted(boolean isSuccessful, String errorText) { + // TODO Auto-generated method stub + + } + + @Override + public void displayGroupList(int reqId, String groups) { + // TODO Auto-generated method stub + + } + + @Override + public void displayGroupUpdated(int reqId, String contractInfo) { + // TODO Auto-generated method stub + + } + + @Override + public void error(Exception e) { + // TODO Auto-generated method stub + + } + + @Override + public void error(String str) { + // TODO Auto-generated method stub + + } + + @Override + public void error(int id, int errorCode, String errorMsg) { + // TODO Auto-generated method stub + + } + + @Override + public void connectionClosed() { + // TODO Auto-generated method stub + + } + + @Override + public void connectAck() { + // TODO Auto-generated method stub + + } + + @Override + public void positionMulti( int reqId, String account, String modelCode, Contract contract, double pos, double avgCost) { + // TODO Auto-generated method stub + + } + + @Override + public void positionMultiEnd( int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void accountUpdateMulti( int reqId, String account, String modelCode, String key, String value, String currency) { + // TODO Auto-generated method stub + + } + + @Override + public void accountUpdateMultiEnd( int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void securityDefinitionOptionalParameter(int reqId, String exchange, int underlyingConId, String tradingClass, + String multiplier, Set expirations, Set strikes) { + // TODO Auto-generated method stub + + } + + @Override + public void securityDefinitionOptionalParameterEnd(int reqId) { + // TODO Auto-generated method stub + + } + + @Override + public void softDollarTiers(int reqId, SoftDollarTier[] tiers) { + // TODO Auto-generated method stub + + } + + @Override + public void familyCodes(FamilyCode[] familyCodes) { + // TODO Auto-generated method stub + + } + + @Override + public void historicalDataEnd(int reqId, String startDateStr, String endDateStr) { + // TODO Auto-generated method stub + + } + + @Override + public void symbolSamples(int reqId, ContractDescription[] contractDescriptions) { + // TODO Auto-generated method stub + + } + + @Override + public void mktDepthExchanges(DepthMktDataDescription[] depthMktDataDescriptions) { + // TODO Auto-generated method stub + + } + + @Override + public void tickNews(int tickerId, long timeStamp, String providerCode, String articleId, String headline, String extraData) { + // TODO Auto-generated method stub + + } + + @Override + public void smartComponents(int reqId, Map> theMap) { + // TODO Auto-generated method stub + + } + + @Override + public void tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions) { + // TODO Auto-generated method stub + + } + + + @Override + public void newsProviders(NewsProvider[] newsProviders) { + // TODO Auto-generated method stub + + } + + @Override + public void newsArticle(int requestId, int articleType, String articleText) { + // TODO Auto-generated method stub + + } + + @Override + public void historicalNews(int requestId, String time, String providerCode, String articleId, String headline) { + // TODO Auto-generated method stub + + } + + @Override + public void historicalNewsEnd(int requestId, boolean hasMore) { + // TODO Auto-generated method stub + + } + + @Override + public void headTimestamp(int reqId, String headTimestamp) { + // TODO Auto-generated method stub + + } + + @Override + public void histogramData(int reqId, List items) { + // TODO Auto-generated method stub + + } + + @Override + public void historicalDataUpdate(int reqId, Bar bar) { + // TODO Auto-generated method stub + + } + + @Override + public void pnl(int reqId, double dailyPnL, double unrealizedPnL) { + // TODO Auto-generated method stub + + } + + @Override + public void rerouteMktDataReq(int reqId, int conId, String exchange) { + // TODO Auto-generated method stub + + } + + @Override + public void rerouteMktDepthReq(int reqId, int conId, String exchange) { + // TODO Auto-generated method stub + + } + + @Override + public void marketRule(int marketRuleId, PriceIncrement[] priceIncrements) { + // TODO Auto-generated method stub + + } + + @Override + public void pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double value) { + // TODO Auto-generated method stub + + } +} diff --git a/ref/client/DeltaNeutralContract.java b/ref/client/DeltaNeutralContract.java new file mode 100644 index 0000000..d5aae3e --- /dev/null +++ b/ref/client/DeltaNeutralContract.java @@ -0,0 +1,69 @@ +/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class DeltaNeutralContract { + private int m_conid; + private double m_delta; + private double m_price; + + // Get + public int conid() { return m_conid; } + public double delta() { return m_delta; } + public double price() { return m_price; } + + // Set + public void conid(int conid) { m_conid = conid; } + public void delta(double delta) { m_delta = delta; } + public void price(double price) { m_price = price; } + + public DeltaNeutralContract() { + m_conid = 0; + m_delta = 0; + m_price = 0; + } + + public DeltaNeutralContract(int conid, double delta, double price) { + m_conid = conid; + m_delta = delta; + m_price = price; + } + + @Override + public boolean equals(Object p_other) { + if (this == p_other) { + return true; + } + + if (p_other == null || !(p_other instanceof DeltaNeutralContract)) { + return false; + } + + DeltaNeutralContract l_theOther = (DeltaNeutralContract)p_other; + + if (m_conid != l_theOther.m_conid) { + return false; + } + if (m_delta != l_theOther.m_delta) { + return false; + } + if (m_price != l_theOther.m_price) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result; + long temp; + result = m_conid; + temp = Double.doubleToLongBits(m_delta); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(m_price); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } +} diff --git a/ref/client/DepthMktDataDescription.java b/ref/client/DepthMktDataDescription.java new file mode 100644 index 0000000..de91b9b --- /dev/null +++ b/ref/client/DepthMktDataDescription.java @@ -0,0 +1,37 @@ +/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class DepthMktDataDescription { + private String m_exchange; + private String m_secType; + private String m_listingExch; + private String m_serviceDataType; + private int m_aggGroup; + + // Get + public String exchange() { return m_exchange; } + public String secType() { return m_secType; } + public String listingExch() { return m_listingExch; } + public String serviceDataType() { return m_serviceDataType; } + public int aggGroup() { return m_aggGroup; } + + // Set + public void exchange(String exchange) { m_exchange = exchange; } + public void secType(String secType) { m_secType = secType; } + public void listingExch(String listingExch) { m_listingExch = listingExch; } + public void serviceDataType(String serviceDataType) { m_serviceDataType = serviceDataType; } + public void aggGroup(int aggGroup) { m_aggGroup = aggGroup; } + + public DepthMktDataDescription() { + } + + public DepthMktDataDescription(String p_exchange, String p_secType, String listingExch, String serviceDataType, int aggGroup) { + m_exchange = p_exchange; + m_secType = p_secType; + m_listingExch = listingExch; + m_serviceDataType = serviceDataType; + m_aggGroup = aggGroup; + } +} diff --git a/ref/client/EClient.java b/ref/client/EClient.java new file mode 100644 index 0000000..c52ac29 --- /dev/null +++ b/ref/client/EClient.java @@ -0,0 +1,3644 @@ +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import com.ib.client.Types.SecType; + +public abstract class EClient { + + // Client version history + // + // 6 = Added parentId to orderStatus + // 7 = The new execDetails event returned for an order filled status and reqExecDetails + // Also market depth is available. + // 8 = Added lastFillPrice to orderStatus() event and permId to execution details + // 9 = Added 'averageCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event + // 10 = Added 'serverId' to the 'open order' & 'order status' events. + // We send back all the API open orders upon connection. + // Added new methods reqAllOpenOrders, reqAutoOpenOrders() + // Added FA support - reqExecution has filter. + // - reqAccountUpdates takes acct code. + // 11 = Added permId to openOrder event. + // 12 = requesting open order attributes ignoreRth, hidden, and discretionary + // 13 = added goodAfterTime + // 14 = always send size on bid/ask/last tick + // 15 = send allocation description string on openOrder + // 16 = can receive account name in account and portfolio updates, and fa params in openOrder + // 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data + // 18 = can receive good till date field in open order messages, and request intraday backfill + // 19 = can receive rthOnly flag in ORDER_STATUS + // 20 = expects TWS time string on connection after server version >= 20. + // 21 = can receive bond contract details. + // 22 = can receive price magnifier in version 2 contract details message + // 23 = support for scanner + // 24 = can receive volatility order parameters in open order messages + // 25 = can receive HMDS query start and end times + // 26 = can receive option vols in option market data messages + // 27 = can receive delta neutral order type and delta neutral aux price in place order version 20: API 8.85 + // 28 = can receive option model computation ticks: API 8.9 + // 29 = can receive trail stop limit price in open order and can place them: API 8.91 + // 30 = can receive extended bond contract def, new ticks, and trade count in bars + // 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders + // ; can receive RT bars + // 32 = can receive TickType.LAST_TIMESTAMP + // ; can receive "whyHeld" in order status messages + // 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages + // 34 = can receive whatIf orders / order state + // 35 = can receive contId field for Contract objects + // 36 = can receive outsideRth field for Order objects + // 37 = can receive clearingAccount and clearingIntent for Order objects + // 38 = can receive multiplier and primaryExchange in portfolio updates + // ; can receive cumQty and avgPrice in execution + // ; can receive fundamental data + // ; can receive underComp for Contract objects + // ; can receive reqId and end marker in contractDetails/bondContractDetails + // ; can receive ScaleInitComponentSize and ScaleSubsComponentSize for Order objects + // 39 = can receive underConId in contractDetails + // 40 = can receive algoStrategy/algoParams in openOrder + // 41 = can receive end marker for openOrder + // ; can receive end marker for account download + // ; can receive end marker for executions download + // 42 = can receive deltaNeutralValidation + // 43 = can receive longName(companyName) + // ; can receive listingExchange + // ; can receive RTVolume tick + // 44 = can receive end market for ticker snapshot + // 45 = can receive notHeld field in openOrder + // 46 = can receive contractMonth, industry, category, subcategory fields in contractDetails + // ; can receive timeZoneId, tradingHours, liquidHours fields in contractDetails + // 47 = can receive gamma, vega, theta, undPrice fields in TICK_OPTION_COMPUTATION + // 48 = can receive exemptCode in openOrder + // 49 = can receive hedgeType and hedgeParam in openOrder + // 50 = can receive optOutSmartRouting field in openOrder + // 51 = can receive smartComboRoutingParams in openOrder + // 52 = can receive deltaNeutralConId, deltaNeutralSettlingFirm, deltaNeutralClearingAccount and deltaNeutralClearingIntent in openOrder + // 53 = can receive orderRef in execution + // 54 = can receive scale order fields (PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset, + // InitPosition, InitFillQty and RandomPercent) in openOrder + // 55 = can receive orderComboLegs (price) in openOrder + // 56 = can receive trailingPercent in openOrder + // 57 = can receive commissionReport message + // 58 = can receive CUSIP/ISIN/etc. in contractDescription/bondContractDescription + // 59 = can receive evRule, evMultiplier in contractDescription/bondContractDescription/executionDetails + // can receive multiplier in executionDetails + // 60 = can receive deltaNeutralOpenClose, deltaNeutralShortSale, deltaNeutralShortSaleSlot and deltaNeutralDesignatedLocation in openOrder + // 61 = can receive multiplier in openOrder + // can receive tradingClass in openOrder, updatePortfolio, execDetails and position + // 62 = can receive avgCost in position message + // 63 = can receive verifyMessageAPI, verifyCompleted, displayGroupList and displayGroupUpdated messages + // 64 = can receive solicited attrib in openOrder message + // 65 = can receive verifyAndAuthMessageAPI and verifyAndAuthCompleted messages + // 66 = can receive randomize size and randomize price order fields + + protected static final int REDIRECT_COUNT_MAX = 2; + + protected static final int CLIENT_VERSION = 66; + protected static final int MIN_SERVER_VER_SUPPORTED = 38; //all supported server versions are listed below + + // FA msg data types + public static final int GROUPS = 1; + public static final int PROFILES = 2; + public static final int ALIASES = 3; + + public static String faMsgTypeName(int faDataType) { + switch (faDataType) { + case GROUPS: + return "GROUPS"; + case PROFILES: + return "PROFILES"; + case ALIASES: + return "ALIASES"; + } + return null; + } + + // outgoing msg id's + private static final int REQ_MKT_DATA = 1; + private static final int CANCEL_MKT_DATA = 2; + protected static final int PLACE_ORDER = 3; + private static final int CANCEL_ORDER = 4; + private static final int REQ_OPEN_ORDERS = 5; + private static final int REQ_ACCOUNT_DATA = 6; + private static final int REQ_EXECUTIONS = 7; + private static final int REQ_IDS = 8; + private static final int REQ_CONTRACT_DATA = 9; + private static final int REQ_MKT_DEPTH = 10; + private static final int CANCEL_MKT_DEPTH = 11; + private static final int REQ_NEWS_BULLETINS = 12; + private static final int CANCEL_NEWS_BULLETINS = 13; + private static final int SET_SERVER_LOGLEVEL = 14; + private static final int REQ_AUTO_OPEN_ORDERS = 15; + private static final int REQ_ALL_OPEN_ORDERS = 16; + private static final int REQ_MANAGED_ACCTS = 17; + private static final int REQ_FA = 18; + private static final int REPLACE_FA = 19; + private static final int REQ_HISTORICAL_DATA = 20; + private static final int EXERCISE_OPTIONS = 21; + private static final int REQ_SCANNER_SUBSCRIPTION = 22; + private static final int CANCEL_SCANNER_SUBSCRIPTION = 23; + private static final int REQ_SCANNER_PARAMETERS = 24; + private static final int CANCEL_HISTORICAL_DATA = 25; + private static final int REQ_CURRENT_TIME = 49; + private static final int REQ_REAL_TIME_BARS = 50; + private static final int CANCEL_REAL_TIME_BARS = 51; + private static final int REQ_FUNDAMENTAL_DATA = 52; + private static final int CANCEL_FUNDAMENTAL_DATA = 53; + private static final int REQ_CALC_IMPLIED_VOLAT = 54; + private static final int REQ_CALC_OPTION_PRICE = 55; + private static final int CANCEL_CALC_IMPLIED_VOLAT = 56; + private static final int CANCEL_CALC_OPTION_PRICE = 57; + private static final int REQ_GLOBAL_CANCEL = 58; + private static final int REQ_MARKET_DATA_TYPE = 59; + private static final int REQ_POSITIONS = 61; + private static final int REQ_ACCOUNT_SUMMARY = 62; + private static final int CANCEL_ACCOUNT_SUMMARY = 63; + private static final int CANCEL_POSITIONS = 64; + private static final int VERIFY_REQUEST = 65; + private static final int VERIFY_MESSAGE = 66; + private static final int QUERY_DISPLAY_GROUPS = 67; + private static final int SUBSCRIBE_TO_GROUP_EVENTS = 68; + private static final int UPDATE_DISPLAY_GROUP = 69; + private static final int UNSUBSCRIBE_FROM_GROUP_EVENTS = 70; + private static final int START_API = 71; + private static final int VERIFY_AND_AUTH_REQUEST = 72; + private static final int VERIFY_AND_AUTH_MESSAGE = 73; + private static final int REQ_POSITIONS_MULTI = 74; + private static final int CANCEL_POSITIONS_MULTI = 75; + private static final int REQ_ACCOUNT_UPDATES_MULTI = 76; + private static final int CANCEL_ACCOUNT_UPDATES_MULTI = 77; + private static final int REQ_SEC_DEF_OPT_PARAMS = 78; + private static final int REQ_SOFT_DOLLAR_TIERS = 79; + private static final int REQ_FAMILY_CODES = 80; + private static final int REQ_MATCHING_SYMBOLS = 81; + private static final int REQ_MKT_DEPTH_EXCHANGES = 82; + private static final int REQ_SMART_COMPONENTS = 83; + private static final int REQ_NEWS_ARTICLE = 84; + private static final int REQ_NEWS_PROVIDERS = 85; + private static final int REQ_HISTORICAL_NEWS = 86; + private static final int REQ_HEAD_TIMESTAMP = 87; + private static final int REQ_HISTOGRAM_DATA = 88; + private static final int CANCEL_HISTOGRAM_DATA = 89; + private static final int CANCEL_HEAD_TIMESTAMP = 90; + private static final int REQ_MARKET_RULE = 91; + private static final int REQ_PNL = 92; + private static final int CANCEL_PNL = 93; + private static final int REQ_PNL_SINGLE = 94; + private static final int CANCEL_PNL_SINGLE = 95; + + private static final int MIN_SERVER_VER_REAL_TIME_BARS = 34; + private static final int MIN_SERVER_VER_SCALE_ORDERS = 35; + private static final int MIN_SERVER_VER_SNAPSHOT_MKT_DATA = 35; + private static final int MIN_SERVER_VER_SSHORT_COMBO_LEGS = 35; + private static final int MIN_SERVER_VER_WHAT_IF_ORDERS = 36; + private static final int MIN_SERVER_VER_CONTRACT_CONID = 37; + private static final int MIN_SERVER_VER_PTA_ORDERS = 39; + private static final int MIN_SERVER_VER_FUNDAMENTAL_DATA = 40; + private static final int MIN_SERVER_VER_UNDER_COMP = 40; + private static final int MIN_SERVER_VER_CONTRACT_DATA_CHAIN = 40; + private static final int MIN_SERVER_VER_SCALE_ORDERS2 = 40; + private static final int MIN_SERVER_VER_ALGO_ORDERS = 41; + private static final int MIN_SERVER_VER_EXECUTION_DATA_CHAIN = 42; + private static final int MIN_SERVER_VER_NOT_HELD = 44; + private static final int MIN_SERVER_VER_SEC_ID_TYPE = 45; + private static final int MIN_SERVER_VER_PLACE_ORDER_CONID = 46; + private static final int MIN_SERVER_VER_REQ_MKT_DATA_CONID = 47; + private static final int MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT = 49; + private static final int MIN_SERVER_VER_REQ_CALC_OPTION_PRICE = 50; + private static final int MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT = 50; + private static final int MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE = 50; + private static final int MIN_SERVER_VER_SSHORTX_OLD = 51; + private static final int MIN_SERVER_VER_SSHORTX = 52; + private static final int MIN_SERVER_VER_REQ_GLOBAL_CANCEL = 53; + private static final int MIN_SERVER_VER_HEDGE_ORDERS = 54; + private static final int MIN_SERVER_VER_REQ_MARKET_DATA_TYPE = 55; + private static final int MIN_SERVER_VER_OPT_OUT_SMART_ROUTING = 56; + private static final int MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS = 57; + private static final int MIN_SERVER_VER_DELTA_NEUTRAL_CONID = 58; + private static final int MIN_SERVER_VER_SCALE_ORDERS3 = 60; + private static final int MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE = 61; + private static final int MIN_SERVER_VER_TRAILING_PERCENT = 62; + protected static final int MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE = 66; + private static final int MIN_SERVER_VER_ACCT_SUMMARY = 67; + protected static final int MIN_SERVER_VER_TRADING_CLASS = 68; + protected static final int MIN_SERVER_VER_SCALE_TABLE = 69; + protected static final int MIN_SERVER_VER_LINKING = 70; + protected static final int MIN_SERVER_VER_ALGO_ID = 71; + protected static final int MIN_SERVER_VER_OPTIONAL_CAPABILITIES = 72; + protected static final int MIN_SERVER_VER_ORDER_SOLICITED = 73; + protected static final int MIN_SERVER_VER_LINKING_AUTH = 74; + protected static final int MIN_SERVER_VER_PRIMARYEXCH = 75; + protected static final int MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE = 76; + protected static final int MIN_SERVER_VER_FRACTIONAL_POSITIONS = 101; + protected static final int MIN_SERVER_VER_PEGGED_TO_BENCHMARK = 102; + protected static final int MIN_SERVER_VER_MODELS_SUPPORT = 103; + protected static final int MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ = 104; + protected static final int MIN_SERVER_VER_EXT_OPERATOR = 105; + protected static final int MIN_SERVER_VER_SOFT_DOLLAR_TIER = 106; + protected static final int MIN_SERVER_VER_REQ_FAMILY_CODES = 107; + protected static final int MIN_SERVER_VER_REQ_MATCHING_SYMBOLS = 108; + protected static final int MIN_SERVER_VER_PAST_LIMIT = 109; + protected static final int MIN_SERVER_VER_MD_SIZE_MULTIPLIER = 110; + protected static final int MIN_SERVER_VER_CASH_QTY = 111; + protected static final int MIN_SERVER_VER_REQ_MKT_DEPTH_EXCHANGES = 112; + protected static final int MIN_SERVER_VER_TICK_NEWS = 113; + protected static final int MIN_SERVER_VER_REQ_SMART_COMPONENTS = 114; + protected static final int MIN_SERVER_VER_REQ_NEWS_PROVIDERS = 115; + protected static final int MIN_SERVER_VER_REQ_NEWS_ARTICLE = 116; + protected static final int MIN_SERVER_VER_REQ_HISTORICAL_NEWS = 117; + protected static final int MIN_SERVER_VER_REQ_HEAD_TIMESTAMP = 118; + protected static final int MIN_SERVER_VER_REQ_HISTOGRAM = 119; + protected static final int MIN_SERVER_VER_SERVICE_DATA_TYPE = 120; + protected static final int MIN_SERVER_VER_AGG_GROUP = 121; + protected static final int MIN_SERVER_VER_UNDERLYING_INFO = 122; + protected static final int MIN_SERVER_VER_CANCEL_HEADTIMESTAMP = 123; + protected static final int MIN_SERVER_VER_SYNT_REALTIME_BARS = 124; + protected static final int MIN_SERVER_VER_CFD_REROUTE = 125; + protected static final int MIN_SERVER_VER_MARKET_RULES = 126; + protected static final int MIN_SERVER_VER_PNL = 127; + protected static final int MIN_SERVER_VER_NEWS_QUERY_ORIGINS = 128; + protected static final int MIN_SERVER_VER_UNREALIZED_PNL = 129; + + public static final int MIN_VERSION = 100; // envelope encoding, applicable to useV100Plus mode only + public static final int MAX_VERSION = MIN_SERVER_VER_UNREALIZED_PNL; // ditto + + protected EReaderSignal m_signal; + protected EWrapper m_eWrapper; // msg handler + protected int m_serverVersion; + protected String m_TwsTime; + protected int m_clientId; + protected boolean m_extraAuth; + protected boolean m_useV100Plus = true; + private String m_optionalCapabilities; + private String m_connectOptions = ""; // iServer rails are used for Connection if this is not null + protected String m_host; + protected ETransport m_socketTransport; + + public boolean isUseV100Plus() { + return m_useV100Plus; + } + + public int serverVersion() { return m_serverVersion; } + public String getTwsConnectionTime() { return m_TwsTime; } + public EWrapper wrapper() { return m_eWrapper; } +// public EReader reader() { return m_reader; } + public abstract boolean isConnected(); + + // set + protected synchronized void setExtraAuth(boolean extraAuth) { m_extraAuth = extraAuth; } + public void optionalCapabilities(String val) { m_optionalCapabilities = val; } + + // get + public String optionalCapabilities() { return m_optionalCapabilities; } + + public EClient( EWrapper eWrapper, EReaderSignal signal) { + m_eWrapper = eWrapper; + m_signal = signal; + m_clientId = -1; + m_extraAuth = false; + m_optionalCapabilities = ""; + m_serverVersion = 0; + } + + protected void sendConnectRequest() throws IOException { + // send client version (unless logon via iserver and/or Version > 100) + if( !m_useV100Plus || m_connectOptions == null ) { + send( CLIENT_VERSION); // Do not add length prefix here, because Server does not know Client's version yet + } + else { + // Switch to GW API (Version 100+ requires length prefix) + sendV100APIHeader(); + } + } + + public void disableUseV100Plus() { + if( isConnected() ) { + m_eWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.ALREADY_CONNECTED.code(), + EClientErrors.ALREADY_CONNECTED.msg()); + return; + } + + m_connectOptions = ""; + m_useV100Plus = false; + } + + public void setConnectOptions(String options) { + if( isConnected() ) { + m_eWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.ALREADY_CONNECTED.code(), + EClientErrors.ALREADY_CONNECTED.msg()); + return; + } + + m_connectOptions = options; + } + + protected void connectionError() { + m_eWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.CONNECT_FAIL.code(), + EClientErrors.CONNECT_FAIL.msg()); + } + + protected String checkConnected(String host) { + if( isConnected()) { + m_eWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.ALREADY_CONNECTED.code(), + EClientErrors.ALREADY_CONNECTED.msg()); + return null; + } + if( IsEmpty( host) ) { + host = "127.0.0.1"; + } + return host; + } + + public abstract void eDisconnect(); + + public synchronized void startAPI() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 2; + + try { + Builder b = prepareBuffer(); + + b.send(START_API); + b.send(VERSION); + b.send(m_clientId); + + if (m_serverVersion >= MIN_SERVER_VER_OPTIONAL_CAPABILITIES) { + b.send(m_optionalCapabilities); + } + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, + EClientErrors.FAIL_SEND_STARTAPI, e.toString()); + close(); + } + } + + public synchronized void cancelScannerSubscription( int tickerId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support API scanner subscription."); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + Builder b = prepareBuffer(); + + b.send( CANCEL_SCANNER_SUBSCRIPTION); + b.send( VERSION); + b.send( tickerId); + + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANSCANNER, e.toString()); + close(); + } + } + + public synchronized void reqScannerParameters() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support API scanner subscription."); + return; + } + + final int VERSION = 1; + + try { + Builder b = prepareBuffer(); + + b.send(REQ_SCANNER_PARAMETERS); + b.send(VERSION); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, + EClientErrors.FAIL_SEND_REQSCANNERPARAMETERS, e.toString()); + close(); + } + } + + public synchronized void reqScannerSubscription( int tickerId, ScannerSubscription subscription, List scannerSubscriptionOptions) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support API scanner subscription."); + return; + } + + final int VERSION = 4; + + try { + Builder b = prepareBuffer(); + + b.send(REQ_SCANNER_SUBSCRIPTION); + b.send(VERSION); + b.send(tickerId); + b.sendMax(subscription.numberOfRows()); + b.send(subscription.instrument()); + b.send(subscription.locationCode()); + b.send(subscription.scanCode()); + b.sendMax(subscription.abovePrice()); + b.sendMax(subscription.belowPrice()); + b.sendMax(subscription.aboveVolume()); + b.sendMax(subscription.marketCapAbove()); + b.sendMax(subscription.marketCapBelow()); + b.send(subscription.moodyRatingAbove()); + b.send(subscription.moodyRatingBelow()); + b.send(subscription.spRatingAbove()); + b.send(subscription.spRatingBelow()); + b.send(subscription.maturityDateAbove()); + b.send(subscription.maturityDateBelow()); + b.sendMax(subscription.couponRateAbove()); + b.sendMax(subscription.couponRateBelow()); + b.send(subscription.excludeConvertible()); + if (m_serverVersion >= 25) { + b.sendMax(subscription.averageOptionVolumeAbove()); + b.send(subscription.scannerSettingPairs()); + } + if (m_serverVersion >= 27) { + b.send(subscription.stockTypeFilter()); + } + + // send scannerSubscriptionOptions parameter + if(m_serverVersion >= MIN_SERVER_VER_LINKING) { + StringBuilder scannerSubscriptionOptionsStr = new StringBuilder(); + int scannerSubscriptionOptionsCount = scannerSubscriptionOptions == null ? 0 : scannerSubscriptionOptions.size(); + if( scannerSubscriptionOptionsCount > 0) { + for( int i = 0; i < scannerSubscriptionOptionsCount; ++i) { + TagValue tagValue = scannerSubscriptionOptions.get(i); + scannerSubscriptionOptionsStr.append( tagValue.m_tag).append("=").append(tagValue.m_value).append(";"); + } + } + b.send( scannerSubscriptionOptionsStr.toString()); + } + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQSCANNER, e.toString()); + close(); + } + } + + public synchronized void reqMktData(int tickerId, Contract contract, + String genericTickList, boolean snapshot, boolean regulatorySnapshot, List mktDataOptions) { + if (!isConnected()) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_SNAPSHOT_MKT_DATA && snapshot) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support snapshot market data requests."); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { + if (contract.underComp() != null) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support delta-neutral orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_MKT_DATA_CONID) { + if (contract.conid() > 0) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support conId parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass())) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support tradingClass parameter in reqMarketData."); + return; + } + } + + final int VERSION = 11; + + try { + // send req mkt data msg + Builder b = prepareBuffer(); + + b.send(REQ_MKT_DATA); + b.send(VERSION); + b.send(tickerId); + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_REQ_MKT_DATA_CONID) { + b.send(contract.conid()); + } + b.send(contract.symbol()); + b.send(contract.getSecType()); + b.send(contract.lastTradeDateOrContractMonth()); + b.send(contract.strike()); + b.send(contract.getRight()); + if (m_serverVersion >= 15) { + b.send(contract.multiplier()); + } + b.send(contract.exchange()); + if (m_serverVersion >= 14) { + b.send(contract.primaryExch()); + } + b.send(contract.currency()); + if(m_serverVersion >= 2) { + b.send( contract.localSymbol()); + } + if(m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send( contract.tradingClass()); + } + if(m_serverVersion >= 8 && SecType.BAG.name().equalsIgnoreCase(contract.getSecType())) { + if ( contract.comboLegs() == null ) { + b.send( 0); + } + else { + b.send( contract.comboLegs().size()); + + ComboLeg comboLeg; + for (int i=0; i < contract.comboLegs().size(); i ++) { + comboLeg = contract.comboLegs().get(i); + b.send( comboLeg.conid()); + b.send( comboLeg.ratio()); + b.send( comboLeg.getAction()); + b.send( comboLeg.exchange()); + } + } + } + + if (m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { + if (contract.underComp() != null) { + DeltaNeutralContract underComp = contract.underComp(); + b.send( true); + b.send( underComp.conid()); + b.send( underComp.delta()); + b.send( underComp.price()); + } + else { + b.send( false); + } + } + + if (m_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. + */ + b.send( genericTickList); + } + if (m_serverVersion >= MIN_SERVER_VER_SNAPSHOT_MKT_DATA) { + b.send (snapshot); + } + + if (m_serverVersion >= MIN_SERVER_VER_REQ_SMART_COMPONENTS) { + b.send(regulatorySnapshot); + } + + // send mktDataOptions parameter + if(m_serverVersion >= MIN_SERVER_VER_LINKING) { + StringBuilder mktDataOptionsStr = new StringBuilder(); + int mktDataOptionsCount = mktDataOptions == null ? 0 : mktDataOptions.size(); + if( mktDataOptionsCount > 0) { + for( int i = 0; i < mktDataOptionsCount; ++i) { + TagValue tagValue = mktDataOptions.get(i); + mktDataOptionsStr.append(tagValue.m_tag).append("=").append(tagValue.m_value).append(";"); + } + } + b.send( mktDataOptionsStr.toString()); + } + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQMKT, e.toString()); + close(); + } + } + + public synchronized void cancelHistoricalData( int tickerId ) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support historical data query cancellation."); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + Builder b = prepareBuffer(); + + b.send( CANCEL_HISTORICAL_DATA); + b.send( VERSION); + b.send( tickerId); + + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANHISTDATA, e.toString()); + close(); + } + } + + public synchronized void cancelRealTimeBars(int tickerId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support realtime bar data query cancellation."); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + Builder b = prepareBuffer(); + + b.send( CANCEL_REAL_TIME_BARS); + b.send( VERSION); + b.send( tickerId); + + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANRTBARS, e.toString()); + close(); + } + } + + /** Note that formatData parameter affects intra-day bars only; 1-day bars always return with date in YYYYMMDD format. */ + public synchronized void reqHistoricalData( int tickerId, Contract contract, + String endDateTime, String durationStr, + String barSizeSetting, String whatToShow, + int useRTH, int formatDate, boolean keepUpToDate, List chartOptions) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 6; + + try { + if (m_serverVersion < 16) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support historical data backfill."); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass()) || (contract.conid() > 0)) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support conId and tradingClass parameters in reqHistoricalData."); + return; + } + } + + Builder b = prepareBuffer(); + + b.send(REQ_HISTORICAL_DATA); + + if (m_serverVersion < MIN_SERVER_VER_SYNT_REALTIME_BARS) { + b.send(VERSION); + } + + b.send(tickerId); + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.conid()); + } + b.send(contract.symbol()); + b.send(contract.getSecType()); + b.send(contract.lastTradeDateOrContractMonth()); + b.send(contract.strike()); + b.send(contract.getRight()); + b.send(contract.multiplier()); + b.send(contract.exchange()); + b.send(contract.primaryExch()); + b.send(contract.currency()); + b.send(contract.localSymbol()); + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + if (m_serverVersion >= 31) { + b.send(contract.includeExpired() ? 1 : 0); + } + if (m_serverVersion >= 20) { + b.send(endDateTime); + b.send(barSizeSetting); + } + b.send(durationStr); + b.send(useRTH); + b.send(whatToShow); + if (m_serverVersion > 16) { + b.send(formatDate); + } + if ( SecType.BAG.name().equalsIgnoreCase(contract.getSecType()) ) { + if (contract.comboLegs() == null) { + b.send(0); + } + else { + b.send(contract.comboLegs().size()); + + ComboLeg comboLeg; + for (int i = 0; i < contract.comboLegs().size(); i++) { + comboLeg = contract.comboLegs().get(i); + b.send(comboLeg.conid()); + b.send(comboLeg.ratio()); + b.send(comboLeg.getAction()); + b.send(comboLeg.exchange()); + } + } + } + + if (m_serverVersion >= MIN_SERVER_VER_SYNT_REALTIME_BARS) { + b.send(keepUpToDate); + } + + // send chartOptions parameter + if(m_serverVersion >= MIN_SERVER_VER_LINKING) { + StringBuilder chartOptionsStr = new StringBuilder(); + int chartOptionsCount = chartOptions == null ? 0 : chartOptions.size(); + if( chartOptionsCount > 0) { + for( int i = 0; i < chartOptionsCount; ++i) { + TagValue tagValue = chartOptions.get(i); + chartOptionsStr.append(tagValue.m_tag).append("=").append(tagValue.m_value).append( ";"); + } + } + b.send( chartOptionsStr.toString()); + } + + closeAndSend(b); + } + catch (Exception e) { + error(tickerId, EClientErrors.FAIL_SEND_REQHISTDATA, e.toString()); + close(); + } + } + + /** Note that formatData parameter affects intra-day bars only; 1-day bars always return with date in YYYYMMDD format. */ + public synchronized void reqHeadTimestamp(int tickerId, Contract contract, + String whatToShow, int useRTH, int formatDate) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + try { + if (m_serverVersion < MIN_SERVER_VER_REQ_HEAD_TIMESTAMP) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support head time stamp requests."); + return; + } + + Builder b = prepareBuffer(); + + b.send(REQ_HEAD_TIMESTAMP); + b.send(tickerId); + b.send(contract.conid()); + b.send(contract.symbol()); + b.send(contract.getSecType()); + b.send(contract.lastTradeDateOrContractMonth()); + b.send(contract.strike()); + b.send(contract.getRight()); + b.send(contract.multiplier()); + b.send(contract.exchange()); + b.send(contract.primaryExch()); + b.send(contract.currency()); + b.send(contract.localSymbol()); + b.send(contract.tradingClass()); + b.send(contract.includeExpired() ? 1 : 0); + b.send(useRTH); + b.send(whatToShow); + b.send(formatDate); + + closeAndSend(b); + } + catch (Exception e) { + error(tickerId, EClientErrors.FAIL_SEND_REQHEADTIMESTAMP, e.toString()); + close(); + } + } + + public synchronized void cancelHeadTimestamp(int tickerId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + try { + if (m_serverVersion < MIN_SERVER_VER_CANCEL_HEADTIMESTAMP) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support head time stamp requests canceling."); + return; + } + + Builder b = prepareBuffer(); + + b.send(CANCEL_HEAD_TIMESTAMP); + b.send(tickerId); + closeAndSend(b); + } + catch (Exception e) { + error(tickerId, EClientErrors.FAIL_SEND_CANHEADTIMESTAMP, e.toString()); + close(); + } + } + + + public synchronized void reqRealTimeBars(int tickerId, Contract contract, int barSize, String whatToShow, boolean useRTH, List realTimeBarsOptions) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support real time bars."); + return; + } + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass()) || (contract.conid() > 0)) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support conId and tradingClass parameters in reqRealTimeBars."); + return; + } + } + + final int VERSION = 3; + + try { + // send req mkt data msg + Builder b = prepareBuffer(); + + b.send(REQ_REAL_TIME_BARS); + b.send(VERSION); + b.send(tickerId); + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.conid()); + } + b.send(contract.symbol()); + b.send(contract.getSecType()); + b.send(contract.lastTradeDateOrContractMonth()); + b.send(contract.strike()); + b.send(contract.getRight()); + b.send(contract.multiplier()); + b.send(contract.exchange()); + b.send(contract.primaryExch()); + b.send(contract.currency()); + b.send(contract.localSymbol()); + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + b.send(barSize); // this parameter is not currently used + b.send(whatToShow); + b.send(useRTH); + + // send realTimeBarsOptions parameter + if(m_serverVersion >= MIN_SERVER_VER_LINKING) { + StringBuilder realTimeBarsOptionsStr = new StringBuilder(); + int realTimeBarsOptionsCount = realTimeBarsOptions == null ? 0 : realTimeBarsOptions.size(); + if( realTimeBarsOptionsCount > 0) { + for( int i = 0; i < realTimeBarsOptionsCount; ++i) { + TagValue tagValue = realTimeBarsOptions.get(i); + realTimeBarsOptionsStr.append(tagValue.m_tag).append("=").append(tagValue.m_value).append(";"); + } + } + b.send( realTimeBarsOptionsStr.toString()); + } + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQRTBARS, e.toString()); + close(); + } + } + + public synchronized void reqContractDetails(int reqId, Contract contract) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + // This feature is only available for versions of TWS >=4 + if( m_serverVersion < 4) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { + if (!IsEmpty(contract.getSecIdType()) || !IsEmpty(contract.secId())) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support secIdType and secId parameters."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass())) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support tradingClass parameter in reqContractDetails."); + return; + } + } + if (m_serverVersion < MIN_SERVER_VER_LINKING) { + if (!IsEmpty(contract.primaryExch())) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support primaryExchange parameter in reqContractDetails."); + return; + } + } + + final int VERSION = 8; + + try { + // send req mkt data msg + Builder b = prepareBuffer(); + + b.send( REQ_CONTRACT_DATA); + b.send( VERSION); + + if (m_serverVersion >= MIN_SERVER_VER_CONTRACT_DATA_CHAIN) { + b.send( reqId); + } + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_CONTRACT_CONID) { + b.send(contract.conid()); + } + b.send( contract.symbol()); + b.send( contract.getSecType()); + b.send( contract.lastTradeDateOrContractMonth()); + b.send( contract.strike()); + b.send( contract.getRight()); + if (m_serverVersion >= 15) { + b.send(contract.multiplier()); + } + + if (m_serverVersion >= MIN_SERVER_VER_PRIMARYEXCH) + { + b.send(contract.exchange()); + b.send(contract.primaryExch()); + } + else if (m_serverVersion >= MIN_SERVER_VER_LINKING) { + if (!IsEmpty(contract.primaryExch()) + && ("BEST".equals(contract.exchange()) || "SMART".equals(contract.exchange()))) { + b.send(contract.exchange() + ":" + contract.primaryExch()); + } else { + b.send(contract.exchange()); + } + } + + b.send( contract.currency()); + b.send( contract.localSymbol()); + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + if (m_serverVersion >= 31) { + b.send(contract.includeExpired()); + } + if (m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE) { + b.send( contract.getSecIdType()); + b.send( contract.secId()); + } + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQCONTRACT, e.toString()); + close(); + } + } + + public synchronized void reqMktDepth( int tickerId, Contract contract, int numRows, List mktDepthOptions) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + // This feature is only available for versions of TWS >=6 + if( m_serverVersion < 6) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass()) || (contract.conid() > 0)) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support conId and tradingClass parameters in reqMktDepth."); + return; + } + } + + final int VERSION = 5; + + try { + // send req mkt data msg + Builder b = prepareBuffer(); + + b.send( REQ_MKT_DEPTH); + b.send( VERSION); + b.send( tickerId); + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.conid()); + } + b.send( contract.symbol()); + b.send( contract.getSecType()); + b.send( contract.lastTradeDateOrContractMonth()); + b.send( contract.strike()); + b.send( contract.getRight()); + if (m_serverVersion >= 15) { + b.send(contract.multiplier()); + } + b.send( contract.exchange()); + b.send( contract.currency()); + b.send( contract.localSymbol()); + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + if (m_serverVersion >= 19) { + b.send( numRows); + } + + // send mktDepthOptions parameter + if(m_serverVersion >= MIN_SERVER_VER_LINKING) { + StringBuilder mktDepthOptionsStr = new StringBuilder(); + int mktDepthOptionsCount = mktDepthOptions == null ? 0 : mktDepthOptions.size(); + if( mktDepthOptionsCount > 0) { + for( int i = 0; i < mktDepthOptionsCount; ++i) { + TagValue tagValue = mktDepthOptions.get(i); + mktDepthOptionsStr.append(tagValue.m_tag).append("=").append(tagValue.m_value).append(";"); + } + } + b.send( mktDepthOptionsStr.toString()); + } + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQMKTDEPTH, e.toString()); + close(); + } + } + + public synchronized void cancelMktData( int tickerId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + Builder b = prepareBuffer(); + + b.send( CANCEL_MKT_DATA); + b.send( VERSION); + b.send( tickerId); + + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANMKT, e.toString()); + close(); + } + } + + public synchronized void cancelMktDepth( int tickerId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + // This feature is only available for versions of TWS >=6 + if( m_serverVersion < 6) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + Builder b = prepareBuffer(); + + b.send( CANCEL_MKT_DEPTH); + b.send( VERSION); + b.send( tickerId); + + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANMKTDEPTH, e.toString()); + close(); + } + } + + public synchronized void exerciseOptions( int tickerId, Contract contract, + int exerciseAction, int exerciseQuantity, + String account, int override) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 2; + + try { + if (m_serverVersion < 21) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support options exercise from the API."); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass()) || (contract.conid() > 0)) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support conId and tradingClass parameters in exerciseOptions."); + return; + } + } + + Builder b = prepareBuffer(); + + b.send(EXERCISE_OPTIONS); + b.send(VERSION); + b.send(tickerId); + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.conid()); + } + b.send(contract.symbol()); + b.send(contract.getSecType()); + b.send(contract.lastTradeDateOrContractMonth()); + b.send(contract.strike()); + b.send(contract.getRight()); + b.send(contract.multiplier()); + b.send(contract.exchange()); + b.send(contract.currency()); + b.send(contract.localSymbol()); + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + b.send(exerciseAction); + b.send(exerciseQuantity); + b.send(account); + b.send(override); + + closeAndSend(b); + } + catch (Exception e) { + error(tickerId, EClientErrors.FAIL_SEND_REQMKT, e.toString()); + close(); + } + } + + public synchronized void placeOrder( int id, Contract contract, Order order) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS) { + if (order.scaleInitLevelSize() != Integer.MAX_VALUE || + order.scalePriceIncrement() != Double.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support Scale orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SSHORT_COMBO_LEGS) { + if (!contract.comboLegs().isEmpty()) { + for( ComboLeg comboLeg : contract.comboLegs() ) { + if (comboLeg.shortSaleSlot() != 0 || + !IsEmpty(comboLeg.designatedLocation())) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support SSHORT flag for combo legs."); + return; + } + } + } + } + + if (m_serverVersion < MIN_SERVER_VER_WHAT_IF_ORDERS) { + if (order.whatIf()) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support what-if orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { + if (contract.underComp() != null) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support delta-neutral orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS2) { + if (order.scaleSubsLevelSize() != Integer.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support Subsequent Level Size for Scale orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_ALGO_ORDERS) { + if (!IsEmpty(order.getAlgoStrategy())) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support algo orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_NOT_HELD) { + if (order.notHeld()) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support notHeld parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { + if (!IsEmpty(contract.getSecIdType()) || !IsEmpty(contract.secId())) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support secIdType and secId parameters."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_PLACE_ORDER_CONID) { + if (contract.conid() > 0) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support conId parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { + if (order.exemptCode() != -1) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support exemptCode parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { + if (!contract.comboLegs().isEmpty()) { + for( ComboLeg comboLeg : contract.comboLegs() ) { + if (comboLeg.exemptCode() != -1) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support exemptCode parameter."); + return; + } + } + } + } + + if (m_serverVersion < MIN_SERVER_VER_HEDGE_ORDERS) { + if (!IsEmpty(order.getHedgeType())) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support hedge orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) { + if (order.optOutSmartRouting()) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support optOutSmartRouting parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_DELTA_NEUTRAL_CONID) { + if (order.deltaNeutralConId() > 0 + || !IsEmpty(order.deltaNeutralSettlingFirm()) + || !IsEmpty(order.deltaNeutralClearingAccount()) + || !IsEmpty(order.deltaNeutralClearingIntent()) + ) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent"); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE) { + if (!IsEmpty(order.deltaNeutralOpenClose()) + || order.deltaNeutralShortSale() + || order.deltaNeutralShortSaleSlot() > 0 + || !IsEmpty(order.deltaNeutralDesignatedLocation()) + ) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support deltaNeutral parameters: OpenClose, ShortSale, ShortSaleSlot, DesignatedLocation"); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS3) { + if (order.scalePriceIncrement() > 0 && order.scalePriceIncrement() != Double.MAX_VALUE) { + if (order.scalePriceAdjustValue() != Double.MAX_VALUE || + order.scalePriceAdjustInterval() != Integer.MAX_VALUE || + order.scaleProfitOffset() != Double.MAX_VALUE || + order.scaleAutoReset() || + order.scaleInitPosition() != Integer.MAX_VALUE || + order.scaleInitFillQty() != Integer.MAX_VALUE || + order.scaleRandomPercent()) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support Scale order parameters: PriceAdjustValue, PriceAdjustInterval, " + + "ProfitOffset, AutoReset, InitPosition, InitFillQty and RandomPercent"); + return; + } + } + } + + if (m_serverVersion < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && SecType.BAG.name().equalsIgnoreCase(contract.getSecType())) { + if (!order.orderComboLegs().isEmpty()) { + for( OrderComboLeg orderComboLeg : order.orderComboLegs() ) { + if (orderComboLeg.price() != Double.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support per-leg prices for order combo legs."); + return; + } + } + } + } + + if (m_serverVersion < MIN_SERVER_VER_TRAILING_PERCENT) { + if (order.trailingPercent() != Double.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support trailing percent parameter"); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass())) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support tradingClass parameters in placeOrder."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_ALGO_ID && !IsEmpty(order.algoId()) ) { + error(id, EClientErrors.UPDATE_TWS, " It does not support algoId parameter"); + } + + if (m_serverVersion < MIN_SERVER_VER_SCALE_TABLE) { + if (!IsEmpty(order.scaleTable()) || !IsEmpty(order.activeStartTime()) || !IsEmpty(order.activeStopTime())) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support scaleTable, activeStartTime and activeStopTime parameters."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_ORDER_SOLICITED) { + if (order.solicited()) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support order solicited parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_MODELS_SUPPORT) { + if (!IsEmpty(order.modelCode())) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support model code parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_EXT_OPERATOR && !IsEmpty(order.extOperator()) ) { + error(id, EClientErrors.UPDATE_TWS, " It does not support ext operator"); + } + + if (m_serverVersion < MIN_SERVER_VER_SOFT_DOLLAR_TIER && + (!IsEmpty(order.softDollarTier().name()) || !IsEmpty(order.softDollarTier().value()))) { + error(id, EClientErrors.UPDATE_TWS, " It does not support soft dollar tier"); + } + + + if (m_serverVersion < MIN_SERVER_VER_CASH_QTY) { + if (order.cashQty() != Double.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support cash quantity parameter"); + return; + } + } + + int VERSION = (m_serverVersion < MIN_SERVER_VER_NOT_HELD) ? 27 : 45; + + // send place order msg + try { + final Builder b = prepareBuffer(); + + b.send( PLACE_ORDER); + b.send( VERSION); + b.send( id); + + // send contract fields + if( m_serverVersion >= MIN_SERVER_VER_PLACE_ORDER_CONID) { + b.send(contract.conid()); + } + b.send( contract.symbol()); + b.send( contract.getSecType()); + b.send( contract.lastTradeDateOrContractMonth()); + b.send( contract.strike()); + b.send( contract.getRight()); + if (m_serverVersion >= 15) { + b.send(contract.multiplier()); + } + b.send( contract.exchange()); + if( m_serverVersion >= 14) { + b.send(contract.primaryExch()); + } + b.send( contract.currency()); + if( m_serverVersion >= 2) { + b.send (contract.localSymbol()); + } + if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + if( m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE){ + b.send( contract.getSecIdType()); + b.send( contract.secId()); + } + + // send main order fields + b.send( order.getAction()); + + if (m_serverVersion >= MIN_SERVER_VER_FRACTIONAL_POSITIONS) + b.send(order.totalQuantity()); + else + b.send((int) order.totalQuantity()); + + b.send( order.getOrderType()); + if (m_serverVersion < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE) { + b.send( order.lmtPrice() == Double.MAX_VALUE ? 0 : order.lmtPrice()); + } + else { + b.sendMax( order.lmtPrice()); + } + if (m_serverVersion < MIN_SERVER_VER_TRAILING_PERCENT) { + b.send( order.auxPrice() == Double.MAX_VALUE ? 0 : order.auxPrice()); + } + else { + b.sendMax( order.auxPrice()); + } + + // send extended order fields + b.send( order.getTif()); + b.send( order.ocaGroup()); + b.send( order.account()); + b.send( order.openClose()); + b.send( order.origin()); + b.send( order.orderRef()); + b.send( order.transmit()); + if( m_serverVersion >= 4 ) { + b.send (order.parentId()); + } + + if( m_serverVersion >= 5 ) { + b.send (order.blockOrder()); + b.send (order.sweepToFill()); + b.send (order.displaySize()); + b.send (order.getTriggerMethod()); + if (m_serverVersion < 38) { + // will never happen + b.send(/* order.m_ignoreRth */ false); + } + else { + b.send (order.outsideRth()); + } + } + + if(m_serverVersion >= 7 ) { + b.send(order.hidden()); + } + + // Send combo legs for BAG requests + if(m_serverVersion >= 8 && SecType.BAG.name().equalsIgnoreCase(contract.getSecType())) { + if ( contract.comboLegs() == null ) { + b.send( 0); + } + else { + b.send( contract.comboLegs().size()); + + for( ComboLeg comboLeg : contract.comboLegs() ) { + b.send( comboLeg.conid()); + b.send( comboLeg.ratio()); + b.send( comboLeg.getAction()); + b.send( comboLeg.exchange()); + b.send( comboLeg.getOpenClose()); + + if (m_serverVersion >= MIN_SERVER_VER_SSHORT_COMBO_LEGS) { + b.send( comboLeg.shortSaleSlot()); + b.send( comboLeg.designatedLocation()); + } + if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { + b.send( comboLeg.exemptCode()); + } + } + } + } + + // Send order combo legs for BAG requests + if(m_serverVersion >= MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && SecType.BAG.name().equalsIgnoreCase(contract.getSecType())) { + if ( order.orderComboLegs() == null ) { + b.send( 0); + } + else { + b.send( order.orderComboLegs().size()); + + for( OrderComboLeg orderComboLeg : order.orderComboLegs() ) { + b.sendMax( orderComboLeg.price()); + } + } + } + + if(m_serverVersion >= MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS && SecType.BAG.name().equalsIgnoreCase(contract.getSecType())) { + List smartComboRoutingParams = order.smartComboRoutingParams(); + int smartComboRoutingParamsCount = smartComboRoutingParams == null ? 0 : smartComboRoutingParams.size(); + b.send( smartComboRoutingParamsCount); + if( smartComboRoutingParamsCount > 0) { + for( TagValue tagValue : smartComboRoutingParams ) { + b.send( tagValue.m_tag); + b.send( tagValue.m_value); + } + } + } + + if ( m_serverVersion >= 9 ) { + // send deprecated sharesAllocation field + b.send( ""); + } + + if ( m_serverVersion >= 10 ) { + b.send( order.discretionaryAmt()); + } + + if ( m_serverVersion >= 11 ) { + b.send( order.goodAfterTime()); + } + + if ( m_serverVersion >= 12 ) { + b.send( order.goodTillDate()); + } + + if ( m_serverVersion >= 13 ) { + b.send( order.faGroup()); + b.send( order.getFaMethod()); + b.send( order.faPercentage()); + b.send( order.faProfile()); + } + + if ( m_serverVersion >= MIN_SERVER_VER_MODELS_SUPPORT ) { + b.send( order.modelCode()); + } + + if (m_serverVersion >= 18) { // institutional short sale slot fields. + b.send( order.shortSaleSlot()); // 0 only for retail, 1 or 2 only for institution. + b.send( order.designatedLocation()); // only populate when order.m_shortSaleSlot = 2. + } + if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { + b.send( order.exemptCode()); + } + if (m_serverVersion >= 19) { + b.send( order.getOcaType()); + if (m_serverVersion < 38) { + // will never happen + b.send( /* order.m_rthOnly */ false); + } + b.send( order.getRule80A()); + b.send( order.settlingFirm()); + b.send( order.allOrNone()); + b.sendMax( order.minQty()); + b.sendMax( order.percentOffset()); + b.send( order.eTradeOnly()); + b.send( order.firmQuoteOnly()); + b.sendMax( order.nbboPriceCap()); + b.sendMax( order.auctionStrategy()); + b.sendMax( order.startingPrice()); + b.sendMax( order.stockRefPrice()); + b.sendMax( order.delta()); + // Volatility orders had specific watermark price attribs in server version 26 + double lower = (m_serverVersion == 26 && order.getOrderType().equals("VOL")) + ? Double.MAX_VALUE + : order.stockRangeLower(); + double upper = (m_serverVersion == 26 && order.getOrderType().equals("VOL")) + ? Double.MAX_VALUE + : order.stockRangeUpper(); + b.sendMax( lower); + b.sendMax( upper); + } + + if (m_serverVersion >= 22) { + b.send( order.overridePercentageConstraints()); + } + + if (m_serverVersion >= 26) { // Volatility orders + b.sendMax( order.volatility()); + b.send(order.getVolatilityType()); + if (m_serverVersion < 28) { + b.send( order.getDeltaNeutralOrderType().equalsIgnoreCase("MKT")); + } else { + b.send( order.getDeltaNeutralOrderType()); + b.sendMax( order.deltaNeutralAuxPrice()); + + if (m_serverVersion >= MIN_SERVER_VER_DELTA_NEUTRAL_CONID && !IsEmpty(order.getDeltaNeutralOrderType())){ + b.send( order.deltaNeutralConId()); + b.send( order.deltaNeutralSettlingFirm()); + b.send( order.deltaNeutralClearingAccount()); + b.send( order.deltaNeutralClearingIntent()); + } + + if (m_serverVersion >= MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE && !IsEmpty(order.getDeltaNeutralOrderType())){ + b.send( order.deltaNeutralOpenClose()); + b.send( order.deltaNeutralShortSale()); + b.send( order.deltaNeutralShortSaleSlot()); + b.send( order.deltaNeutralDesignatedLocation()); + } + } + b.send( order.continuousUpdate()); + if (m_serverVersion == 26) { + // Volatility orders had specific watermark price attribs in server version 26 + double lower = order.getOrderType().equals("VOL") ? order.stockRangeLower() : Double.MAX_VALUE; + double upper = order.getOrderType().equals("VOL") ? order.stockRangeUpper() : Double.MAX_VALUE; + b.sendMax( lower); + b.sendMax( upper); + } + b.send(order.getReferencePriceType()); + } + + if (m_serverVersion >= 30) { // TRAIL_STOP_LIMIT stop price + b.sendMax( order.trailStopPrice()); + } + + if( m_serverVersion >= MIN_SERVER_VER_TRAILING_PERCENT){ + b.sendMax( order.trailingPercent()); + } + + if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS) { + if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS2) { + b.sendMax (order.scaleInitLevelSize()); + b.sendMax (order.scaleSubsLevelSize()); + } + else { + b.send (""); + b.sendMax (order.scaleInitLevelSize()); + + } + b.sendMax (order.scalePriceIncrement()); + } + + if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS3 && order.scalePriceIncrement() > 0.0 && order.scalePriceIncrement() != Double.MAX_VALUE) { + b.sendMax (order.scalePriceAdjustValue()); + b.sendMax (order.scalePriceAdjustInterval()); + b.sendMax (order.scaleProfitOffset()); + b.send (order.scaleAutoReset()); + b.sendMax (order.scaleInitPosition()); + b.sendMax (order.scaleInitFillQty()); + b.send (order.scaleRandomPercent()); + } + + if (m_serverVersion >= MIN_SERVER_VER_SCALE_TABLE) { + b.send (order.scaleTable()); + b.send (order.activeStartTime()); + b.send (order.activeStopTime()); + } + + if (m_serverVersion >= MIN_SERVER_VER_HEDGE_ORDERS) { + b.send (order.getHedgeType()); + if (!IsEmpty(order.getHedgeType())) { + b.send (order.hedgeParam()); + } + } + + if (m_serverVersion >= MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) { + b.send (order.optOutSmartRouting()); + } + + if (m_serverVersion >= MIN_SERVER_VER_PTA_ORDERS) { + b.send (order.clearingAccount()); + b.send (order.clearingIntent()); + } + + if (m_serverVersion >= MIN_SERVER_VER_NOT_HELD) { + b.send (order.notHeld()); + } + + if (m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { + if (contract.underComp() != null) { + DeltaNeutralContract underComp = contract.underComp(); + b.send( true); + b.send( underComp.conid()); + b.send( underComp.delta()); + b.send( underComp.price()); + } + else { + b.send( false); + } + } + + if (m_serverVersion >= MIN_SERVER_VER_ALGO_ORDERS) { + b.send( order.getAlgoStrategy()); + if( !IsEmpty(order.getAlgoStrategy())) { + List algoParams = order.algoParams(); + int algoParamsCount = algoParams.size(); + b.send( algoParamsCount); + for( TagValue tagValue : algoParams ) { + b.send( tagValue.m_tag); + b.send( tagValue.m_value); + } + } + } + + if (m_serverVersion >= MIN_SERVER_VER_ALGO_ID) { + b.send(order.algoId()); + } + + if (m_serverVersion >= MIN_SERVER_VER_WHAT_IF_ORDERS) { + b.send (order.whatIf()); + } + + // send orderMiscOptions parameter + if(m_serverVersion >= MIN_SERVER_VER_LINKING) { + StringBuilder orderMiscOptionsStr = new StringBuilder(); + List orderMiscOptions = order.orderMiscOptions(); + int orderMiscOptionsCount = orderMiscOptions == null ? 0 : orderMiscOptions.size(); + if( orderMiscOptionsCount > 0) { + for( TagValue tagValue : orderMiscOptions ) { + orderMiscOptionsStr.append(tagValue.m_tag).append("=").append(tagValue.m_value).append(";"); + } + } + b.send( orderMiscOptionsStr.toString()); + } + + if (m_serverVersion >= MIN_SERVER_VER_ORDER_SOLICITED) { + b.send(order.solicited()); + } + + if (m_serverVersion >= MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE) { + b.send(order.randomizeSize()); + b.send(order.randomizePrice()); + } + + if (m_serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK) { + if (order.orderType() == OrderType.PEG_BENCH) { + b.send(order.referenceContractId()); + b.send(order.isPeggedChangeAmountDecrease()); + b.send(order.peggedChangeAmount()); + b.send(order.referenceChangeAmount()); + b.send(order.referenceExchangeId()); + } + + b.send(order.conditions().size()); + + if (order.conditions().size() > 0) { + for (OrderCondition item : order.conditions()) { + b.send(item.type().val()); + item.writeTo(b); + } + + b.send(order.conditionsIgnoreRth()); + b.send(order.conditionsCancelOrder()); + } + + b.send(order.adjustedOrderType()); + b.send(order.triggerPrice()); + b.send(order.lmtPriceOffset()); + b.send(order.adjustedStopPrice()); + b.send(order.adjustedStopLimitPrice()); + b.send(order.adjustedTrailingAmount()); + b.send(order.adjustableTrailingUnit()); + } + + if (m_serverVersion >= MIN_SERVER_VER_EXT_OPERATOR) { + b.send(order.extOperator()); + } + + if (m_serverVersion >= MIN_SERVER_VER_SOFT_DOLLAR_TIER) { + SoftDollarTier tier = order.softDollarTier(); + + b.send(tier.name()); + b.send(tier.value()); + } + + if (m_serverVersion >= MIN_SERVER_VER_CASH_QTY) { + b.sendMax(order.cashQty()); + } + + closeAndSend(b); + } + catch( Exception e) { + error( id, EClientErrors.FAIL_SEND_ORDER, e.toString()); + close(); + } + } + + public synchronized void reqAccountUpdates(boolean subscribe, String acctCode) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 2; + + // send account data msg + try { + Builder b = prepareBuffer(); + + b.send( REQ_ACCOUNT_DATA ); + b.send( VERSION); + b.send( subscribe); + + // Send the account code. This will only be used for FA clients + if ( m_serverVersion >= 9 ) { + b.send( acctCode); + } + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_ACCT, e.toString()); + close(); + } + } + + public synchronized void reqExecutions(int reqId, ExecutionFilter filter) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 3; + + // send executions msg + try { + Builder b = prepareBuffer(); + + b.send( REQ_EXECUTIONS); + b.send( VERSION); + + if (m_serverVersion >= MIN_SERVER_VER_EXECUTION_DATA_CHAIN) { + b.send( reqId); + } + + // Send the execution rpt filter data + if ( m_serverVersion >= 9 ) { + b.send( filter.clientId()); + b.send( filter.acctCode()); + + // Note that the valid format for m_time is "yyyymmdd-hh:mm:ss" + b.send( filter.time()); + b.send( filter.symbol()); + b.send( filter.secType()); + b.send( filter.exchange()); + b.send( filter.side()); + } + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_EXEC, e.toString()); + close(); + } + } + + public synchronized void cancelOrder( int id) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send cancel order msg + try { + Builder b = prepareBuffer(); + + b.send( CANCEL_ORDER); + b.send( VERSION); + b.send( id); + + closeAndSend(b); + } + catch( Exception e) { + error( id, EClientErrors.FAIL_SEND_CORDER, e.toString()); + close(); + } + } + + public synchronized void reqOpenOrders() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send open orders msg + try { + Builder b = prepareBuffer(); + + b.send( REQ_OPEN_ORDERS); + b.send( VERSION); + + closeAndSend(b); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, e.toString()); + close(); + } + } + + public synchronized void reqIds( int numIds) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + try { + Builder b = prepareBuffer(); + + b.send( REQ_IDS); + b.send( VERSION); + b.send( numIds); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, e.toString()); + close(); + } + } + + public synchronized void reqNewsBulletins( boolean allMsgs) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + try { + Builder b = prepareBuffer(); + + b.send( REQ_NEWS_BULLETINS); + b.send( VERSION); + b.send( allMsgs); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, e.toString()); + close(); + } + } + + public synchronized void cancelNewsBulletins() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send cancel news bulletins msg + try { + Builder b = prepareBuffer(); + + b.send( CANCEL_NEWS_BULLETINS); + b.send( VERSION); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, e.toString()); + close(); + } + } + + public synchronized void setServerLogLevel(int logLevel) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send the set server logging level message + try { + Builder b = prepareBuffer(); + + b.send( SET_SERVER_LOGLEVEL); + b.send( VERSION); + b.send( logLevel); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_SERVER_LOG_LEVEL, e.toString()); + close(); + } + } + + public synchronized void reqAutoOpenOrders(boolean bAutoBind) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send req open orders msg + try { + Builder b = prepareBuffer(); + + b.send( REQ_AUTO_OPEN_ORDERS); + b.send( VERSION); + b.send( bAutoBind); + + closeAndSend(b); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, e.toString()); + close(); + } + } + + public synchronized void reqAllOpenOrders() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send req all open orders msg + try { + Builder b = prepareBuffer(); + + b.send( REQ_ALL_OPEN_ORDERS); + b.send( VERSION); + + closeAndSend(b); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, e.toString()); + close(); + } + } + + public synchronized void reqManagedAccts() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + final int VERSION = 1; + + // send req FA managed accounts msg + try { + Builder b = prepareBuffer(); + + b.send( REQ_MANAGED_ACCTS); + b.send( VERSION); + + closeAndSend(b); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, e.toString()); + close(); + } + } + + public synchronized void requestFA( int faDataType ) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + // This feature is only available for versions of TWS >= 13 + if( m_serverVersion < 13) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + final int VERSION = 1; + + try { + Builder b = prepareBuffer(); + + b.send( REQ_FA ); + b.send( VERSION); + b.send( faDataType); + + closeAndSend(b); + } + catch( Exception e) { + error( faDataType, EClientErrors.FAIL_SEND_FA_REQUEST, e.toString()); + close(); + } + } + + public synchronized void replaceFA( int faDataType, String xml ) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + // This feature is only available for versions of TWS >= 13 + if( m_serverVersion < 13) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + final int VERSION = 1; + + try { + Builder b = prepareBuffer(); + + b.send( REPLACE_FA ); + b.send( VERSION); + b.send( faDataType); + b.send( xml); + + closeAndSend(b); + } + catch( Exception e) { + error( faDataType, EClientErrors.FAIL_SEND_FA_REPLACE, e.toString()); + close(); + } + } + + public synchronized void reqCurrentTime() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + // This feature is only available for versions of TWS >= 33 + if( m_serverVersion < 33) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support current time requests."); + return; + } + + final int VERSION = 1; + + try { + Builder b = prepareBuffer(); + + b.send( REQ_CURRENT_TIME ); + b.send( VERSION); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQCURRTIME, e.toString()); + close(); + } + } + + public synchronized void reqFundamentalData(int reqId, Contract contract, String reportType) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { + error( reqId, EClientErrors.UPDATE_TWS, + " It does not support fundamental data requests."); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if( contract.conid() > 0) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support conId parameter in reqFundamentalData."); + return; + } + } + + final int VERSION = 2; + + try { + // send req fund data msg + Builder b = prepareBuffer(); + + b.send( REQ_FUNDAMENTAL_DATA); + b.send( VERSION); + b.send( reqId); + + // send contract fields + if( m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.conid()); + } + b.send( contract.symbol()); + b.send( contract.getSecType()); + b.send( contract.exchange()); + b.send( contract.primaryExch()); + b.send( contract.currency()); + b.send( contract.localSymbol()); + + b.send( reportType); + + closeAndSend(b); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_REQFUNDDATA, e.toString()); + close(); + } + } + + public synchronized void cancelFundamentalData(int reqId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { + error( reqId, EClientErrors.UPDATE_TWS, + " It does not support fundamental data requests."); + return; + } + + final int VERSION = 1; + + try { + // send cancel fundamental data msg + Builder b = prepareBuffer(); + + b.send( CANCEL_FUNDAMENTAL_DATA); + b.send( VERSION); + b.send( reqId); + + closeAndSend(b); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_CANFUNDDATA, e.toString()); + close(); + } + } + + public synchronized void calculateImpliedVolatility(int reqId, Contract contract, + double optionPrice, double underPrice) { + + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate implied volatility requests."); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass())) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support tradingClass parameter in calculateImpliedVolatility."); + return; + } + } + + final int VERSION = 2; + + try { + // send calculate implied volatility msg + Builder b = prepareBuffer(); + + b.send( REQ_CALC_IMPLIED_VOLAT); + b.send( VERSION); + b.send( reqId); + + // send contract fields + b.send( contract.conid()); + b.send( contract.symbol()); + b.send( contract.getSecType()); + b.send( contract.lastTradeDateOrContractMonth()); + b.send( contract.strike()); + b.send( contract.getRight()); + b.send( contract.multiplier()); + b.send( contract.exchange()); + b.send( contract.primaryExch()); + b.send( contract.currency()); + b.send( contract.localSymbol()); + if( m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + + b.send( optionPrice); + b.send( underPrice); + + closeAndSend(b); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_REQCALCIMPLIEDVOLAT, e.toString()); + close(); + } + } + + public synchronized void cancelCalculateImpliedVolatility(int reqId) { + + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate implied volatility cancellation."); + return; + } + + final int VERSION = 1; + + try { + // send cancel calculate implied volatility msg + Builder b = prepareBuffer(); + + b.send( CANCEL_CALC_IMPLIED_VOLAT); + b.send( VERSION); + b.send( reqId); + + closeAndSend(b); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_CANCALCIMPLIEDVOLAT, e.toString()); + close(); + } + } + + public synchronized void calculateOptionPrice(int reqId, Contract contract, + double volatility, double underPrice) { + + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_OPTION_PRICE) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate option price requests."); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { + if (!IsEmpty(contract.tradingClass())) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support tradingClass parameter in calculateOptionPrice."); + return; + } + } + + final int VERSION = 2; + + try { + // send calculate option price msg + Builder b = prepareBuffer(); + + b.send( REQ_CALC_OPTION_PRICE); + b.send( VERSION); + b.send( reqId); + + // send contract fields + b.send( contract.conid()); + b.send( contract.symbol()); + b.send( contract.getSecType()); + b.send( contract.lastTradeDateOrContractMonth()); + b.send( contract.strike()); + b.send( contract.getRight()); + b.send( contract.multiplier()); + b.send( contract.exchange()); + b.send( contract.primaryExch()); + b.send( contract.currency()); + b.send( contract.localSymbol()); + if( m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { + b.send(contract.tradingClass()); + } + + b.send( volatility); + b.send( underPrice); + + closeAndSend(b); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_REQCALCOPTIONPRICE, e.toString()); + close(); + } + } + + public synchronized void cancelCalculateOptionPrice(int reqId) { + + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate option price cancellation."); + return; + } + + final int VERSION = 1; + + try { + // send cancel calculate option price msg + Builder b = prepareBuffer(); + + b.send( CANCEL_CALC_OPTION_PRICE); + b.send( VERSION); + b.send( reqId); + + closeAndSend(b); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_CANCALCOPTIONPRICE, e.toString()); + close(); + } + } + + public synchronized void reqGlobalCancel() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_GLOBAL_CANCEL) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support globalCancel requests."); + return; + } + + final int VERSION = 1; + + // send request global cancel msg + try { + Builder b = prepareBuffer(); + + b.send( REQ_GLOBAL_CANCEL); + b.send( VERSION); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQGLOBALCANCEL, e.toString()); + close(); + } + } + + public synchronized void reqMarketDataType(int marketDataType) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_MARKET_DATA_TYPE) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support marketDataType requests."); + return; + } + + final int VERSION = 1; + + // send the reqMarketDataType message + try { + Builder b = prepareBuffer(); + + b.send( REQ_MARKET_DATA_TYPE); + b.send( VERSION); + b.send( marketDataType); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQMARKETDATATYPE, e.toString()); + close(); + } + } + + public synchronized void reqPositions() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support position requests."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( REQ_POSITIONS); + b.send( VERSION); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQPOSITIONS, e.toString()); + } + } + + + public synchronized void reqSecDefOptParams(int reqId, String underlyingSymbol, String futFopExchange, String underlyingSecType, int underlyingConId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support security definition option requests."); + return; + } + + Builder b = prepareBuffer(); + + b.send(REQ_SEC_DEF_OPT_PARAMS); + b.send(reqId); + b.send(underlyingSymbol); + b.send(futFopExchange); + b.send(underlyingSecType); + b.send(underlyingConId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQSECDEFOPTPARAMS, e.toString()); + } + } + + public synchronized void reqSoftDollarTiers(int reqId) { + if (!isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_SOFT_DOLLAR_TIER) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support soft dollar tier requests."); + return; + } + + Builder b = prepareBuffer(); + + b.send(REQ_SOFT_DOLLAR_TIERS); + b.send(reqId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQSOFTDOLLARTIERS, e.toString()); + } + } + + public synchronized void cancelPositions() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support position cancellation."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( CANCEL_POSITIONS); + b.send( VERSION); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CANPOSITIONS, e.toString()); + } + } + + public synchronized void reqPositionsMulti( int reqId, String account, String modelCode) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_MODELS_SUPPORT) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support positions multi request."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( REQ_POSITIONS_MULTI); + b.send( VERSION); + b.send( reqId); + b.send( account); + b.send( modelCode); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQPOSITIONSMULTI, e.toString()); + } + } + + public synchronized void cancelPositionsMulti( int reqId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_MODELS_SUPPORT) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support positions multi cancellation."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( CANCEL_POSITIONS_MULTI); + b.send( VERSION); + b.send( reqId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CANPOSITIONSMULTI, e.toString()); + } + } + + public synchronized void cancelAccountUpdatesMulti( int reqId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_MODELS_SUPPORT) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support account updates multi cancellation."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( CANCEL_ACCOUNT_UPDATES_MULTI); + b.send( VERSION); + b.send( reqId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CANACCOUNTUPDATESMULTI, e.toString()); + } + } + + public synchronized void reqAccountUpdatesMulti( int reqId, String account, String modelCode, boolean ledgerAndNLV) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_MODELS_SUPPORT) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support account updates multi requests."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( REQ_ACCOUNT_UPDATES_MULTI); + b.send( VERSION); + b.send( reqId); + b.send( account); + b.send( modelCode); + b.send( ledgerAndNLV); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQACCOUNTUPDATESMULTI, e.toString()); + } + } + + public synchronized void reqAccountSummary( int reqId, String group, String tags) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support account summary requests."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( REQ_ACCOUNT_SUMMARY); + b.send( VERSION); + b.send( reqId); + b.send( group); + b.send( tags); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQACCOUNTDATA, e.toString()); + } + } + + public synchronized void cancelAccountSummary( int reqId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support account summary cancellation."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( CANCEL_ACCOUNT_SUMMARY); + b.send( VERSION); + b.send( reqId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CANACCOUNTDATA, e.toString()); + } + } + public synchronized void verifyRequest( String apiName, String apiVersion) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_LINKING) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support verification request."); + return; + } + + if (!m_extraAuth) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_VERIFYMESSAGE, + " Intent to authenticate needs to be expressed during initial connect request."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + b.send( VERIFY_REQUEST); + b.send( VERSION); + b.send( apiName); + b.send( apiVersion); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_VERIFYREQUEST, e.toString()); + } + } + + public synchronized void verifyMessage( String apiData) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_LINKING) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support verification message sending."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + b.send( VERIFY_MESSAGE); + b.send( VERSION); + b.send( apiData); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_VERIFYMESSAGE, e.toString()); + } + } + + public synchronized void verifyAndAuthRequest( String apiName, String apiVersion, String opaqueIsvKey) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_LINKING_AUTH) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support verification request."); + return; + } + + if( !m_extraAuth) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_VERIFYANDAUTHREQUEST, + " Intent to authenticate needs to be expressed during initial connect request."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + b.send( VERIFY_AND_AUTH_REQUEST); + b.send( VERSION); + b.send( apiName); + b.send( apiVersion); + b.send( opaqueIsvKey); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_VERIFYANDAUTHREQUEST, e.toString()); + } + } + + public synchronized void verifyAndAuthMessage( String apiData, String xyzResponse) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_LINKING_AUTH) { + error( EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support verification message sending."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + b.send( VERIFY_AND_AUTH_MESSAGE); + b.send( VERSION); + b.send( apiData); + b.send( xyzResponse); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_VERIFYANDAUTHMESSAGE, e.toString()); + } + } + + public synchronized void queryDisplayGroups( int reqId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_LINKING) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support queryDisplayGroups request."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( QUERY_DISPLAY_GROUPS); + b.send( VERSION); + b.send( reqId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_QUERYDISPLAYGROUPS, e.toString()); + } + } + + public synchronized void subscribeToGroupEvents( int reqId, int groupId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_LINKING) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support subscribeToGroupEvents request."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( SUBSCRIBE_TO_GROUP_EVENTS); + b.send( VERSION); + b.send( reqId); + b.send( groupId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_SUBSCRIBETOGROUPEVENTS, e.toString()); + } + } + + public synchronized void updateDisplayGroup( int reqId, String contractInfo) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_LINKING) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support updateDisplayGroup request."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( UPDATE_DISPLAY_GROUP); + b.send( VERSION); + b.send( reqId); + b.send( contractInfo); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_UPDATEDISPLAYGROUP, e.toString()); + } + } + + public synchronized void unsubscribeFromGroupEvents( int reqId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_LINKING) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support unsubscribeFromGroupEvents request."); + return; + } + + final int VERSION = 1; + + Builder b = prepareBuffer(); + + b.send( UNSUBSCRIBE_FROM_GROUP_EVENTS); + b.send( VERSION); + b.send( reqId); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS, e.toString()); + } + } + + public synchronized void reqMatchingSymbols( int reqId, String pattern) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_MATCHING_SYMBOLS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support matching symbols request."); + return; + } + + Builder b = prepareBuffer(); + + b.send( REQ_MATCHING_SYMBOLS); + b.send( reqId); + b.send( pattern); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQMATCHINGSYMBOLS, e.toString()); + } + } + + public synchronized void reqFamilyCodes() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_FAMILY_CODES) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support family codes request."); + return; + } + + Builder b = prepareBuffer(); + + b.send( REQ_FAMILY_CODES); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQFAMILYCODES, e.toString()); + } + } + + public synchronized void reqMktDepthExchanges() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_MKT_DEPTH_EXCHANGES) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support market depth exchanges request."); + return; + } + + Builder b = prepareBuffer(); + + b.send( REQ_MKT_DEPTH_EXCHANGES); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQMKTDEPTHEXCHANGES, e.toString()); + } + } + + public synchronized void reqSmartComponents(int reqId, String bboExchange) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_SMART_COMPONENTS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support smart components request."); + return; + } + + Builder b = prepareBuffer(); + + b.send(REQ_SMART_COMPONENTS); + b.send(reqId); + b.send(bboExchange); + + try { + + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQSMARTCOMPONENTS, e.toString()); + } + } + + public synchronized void reqNewsProviders() { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_NEWS_PROVIDERS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support news providers request."); + return; + } + + Builder b = prepareBuffer(); + + b.send( REQ_NEWS_PROVIDERS); + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQNEWSPROVIDERS, e.toString()); + } + } + + public synchronized void reqNewsArticle(int requestId, String providerCode, String articleId, List newsArticleOptions) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_NEWS_ARTICLE) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support news article request."); + return; + } + + Builder b = prepareBuffer(); + + b.send( REQ_NEWS_ARTICLE); + b.send( requestId); + b.send( providerCode); + b.send( articleId); + + // send newsArticleOptions parameter + if (m_serverVersion >= MIN_SERVER_VER_NEWS_QUERY_ORIGINS) { + StringBuilder newsArticleOptionsStr = new StringBuilder(); + int newsArticleOptionsCount = newsArticleOptions == null ? 0 : newsArticleOptions.size(); + if( newsArticleOptionsCount > 0) { + for( int i = 0; i < newsArticleOptionsCount; ++i) { + TagValue tagValue = newsArticleOptions.get(i); + newsArticleOptionsStr.append(tagValue.m_tag).append("=").append(tagValue.m_value).append(";"); + } + } + b.send( newsArticleOptionsStr.toString()); + } + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQNEWSARTICLE, e.toString()); + } + } + + public synchronized void reqHistoricalNews( int requestId, int conId, String providerCodes, + String startDateTime, String endDateTime, int totalResults, List historicalNewsOptions) { + + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_HISTORICAL_NEWS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support historical news request."); + return; + } + + Builder b = prepareBuffer(); + + b.send( REQ_HISTORICAL_NEWS); + b.send( requestId); + b.send( conId); + b.send( providerCodes); + b.send( startDateTime); + b.send( endDateTime); + b.send( totalResults); + + // send historicalNewsOptions parameter + if (m_serverVersion >= MIN_SERVER_VER_NEWS_QUERY_ORIGINS) { + StringBuilder historicalNewsOptionsStr = new StringBuilder(); + int historicalNewsOptionsCount = historicalNewsOptions == null ? 0 : historicalNewsOptions.size(); + if( historicalNewsOptionsCount > 0) { + for( int i = 0; i < historicalNewsOptionsCount; ++i) { + TagValue tagValue = historicalNewsOptions.get(i); + historicalNewsOptionsStr.append(tagValue.m_tag).append("=").append(tagValue.m_value).append(";"); + } + } + b.send( historicalNewsOptionsStr.toString()); + } + + try { + closeAndSend(b); + } + catch (IOException e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQHISTORICALNEWS, e.toString()); + } + } + + public synchronized void reqHistogramData(int tickerId, Contract contract, + boolean useRTH, String timePeriod) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + try { + if (m_serverVersion < MIN_SERVER_VER_REQ_HISTOGRAM) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support histogram requests."); + return; + } + + Builder b = prepareBuffer(); + + b.send(REQ_HISTOGRAM_DATA); + b.send(tickerId); + b.send(contract.conid()); + b.send(contract.symbol()); + b.send(contract.getSecType()); + b.send(contract.lastTradeDateOrContractMonth()); + b.send(contract.strike()); + b.send(contract.getRight()); + b.send(contract.multiplier()); + b.send(contract.exchange()); + b.send(contract.primaryExch()); + b.send(contract.currency()); + b.send(contract.localSymbol()); + b.send(contract.tradingClass()); + b.send(contract.includeExpired() ? 1 : 0); + b.send(useRTH ? 1 : 0); + b.send(timePeriod); + + closeAndSend(b); + } + catch (Exception e) { + error(tickerId, EClientErrors.FAIL_SEND_REQHISTDATA, e.toString()); + close(); + } + } + + public synchronized void cancelHistogramData( int tickerId ) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_HISTOGRAM) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support head time stamp requests."); + return; + } + + // send cancel mkt data msg + try { + Builder b = prepareBuffer(); + + b.send(CANCEL_HISTOGRAM_DATA); + b.send(tickerId); + + closeAndSend(b); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANHISTDATA, e.toString()); + close(); + } + } + + public synchronized void reqMarketRule( int marketRuleId) { + // not connected? + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_MARKET_RULES) { + error( EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support market rule requests."); + return; + } + + // send request market rule msg + try { + Builder b = prepareBuffer(); + + b.send(REQ_MARKET_RULE); + b.send(marketRuleId); + + closeAndSend(b); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQMARKETRULE, e.toString()); + close(); + } + } + + public synchronized void reqPnL(int reqId, String account, String modelCode) { + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_PNL) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support PnL requests."); + return; + } + + try { + Builder b = prepareBuffer(); + + b.send(REQ_PNL); + b.send(reqId); + b.send(account); + b.send(modelCode); + + closeAndSend(b); + } catch(Exception e) { + error(reqId, EClientErrors.FAIL_SEND_REQPNL, e.toString()); + close(); + } + } + + public synchronized void cancelPnL(int reqId) { + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_PNL) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support PnL requests."); + return; + } + + try { + Builder b = prepareBuffer(); + + b.send(CANCEL_PNL); + b.send(reqId); + + closeAndSend(b); + } catch(Exception e) { + error(reqId, EClientErrors.FAIL_SEND_CANPNL, e.toString()); + close(); + } + } + + public synchronized void reqPnLSingle(int reqId, String account, String modelCode, int conId) { + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_PNL) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support PnL requests."); + return; + } + + try { + Builder b = prepareBuffer(); + + b.send(REQ_PNL_SINGLE); + b.send(reqId); + b.send(account); + b.send(modelCode); + b.send(conId); + + closeAndSend(b); + } catch(Exception e) { + error(reqId, EClientErrors.FAIL_SEND_REQPNL_SINGLE, e.toString()); + close(); + } + } + + public synchronized void cancelPnLSingle(int reqId) { + if( !isConnected()) { + notConnected(); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_PNL) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support PnL requests."); + return; + } + + try { + Builder b = prepareBuffer(); + + b.send(CANCEL_PNL_SINGLE); + b.send(reqId); + + closeAndSend(b); + } catch(Exception e) { + error(reqId, EClientErrors.FAIL_SEND_CANPNL_SINGLE, e.toString()); + close(); + } + } + + /** + * @deprecated This method is never called. + */ + @Deprecated + protected synchronized void error( String err) { + m_eWrapper.error( err); + } + + protected synchronized void error( int id, int errorCode, String errorMsg) { + m_eWrapper.error( id, errorCode, errorMsg); + } + + protected void close() { + eDisconnect(); + wrapper().connectionClosed(); + } + + protected void error(int id, EClientErrors.CodeMsgPair pair, String tail) { + error(id, pair.code(), pair.msg() + tail); + } + + protected abstract Builder prepareBuffer(); + + protected abstract void closeAndSend(Builder buf) throws IOException; + + private void sendV100APIHeader() throws IOException { + try (Builder builder = new Builder(1024)) { + builder.send("API\0".getBytes(StandardCharsets.UTF_8)); + + String out = buildVersionString(MIN_VERSION, MAX_VERSION); + + if (!IsEmpty(m_connectOptions)) { + out += " " + m_connectOptions; + } + + int lengthPos = builder.allocateLengthHeader(); + builder.send(out.getBytes(StandardCharsets.UTF_8)); + builder.updateLength(lengthPos); + + sendMsg(new EMessage(builder)); + } + } + + private String buildVersionString(int minVersion, int maxVersion) { + return "v" + ((minVersion < maxVersion) + ? minVersion + ".." + maxVersion : minVersion); + } + + protected void sendMsg(EMessage msg) throws IOException { + m_socketTransport.send(msg); + } + + private static boolean IsEmpty(String str) { + return Util.StringIsEmpty(str); + } + + protected void notConnected() { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + } + + public String connectedHost() { return m_host; } // Host that was connected/redirected + protected void send( int val) throws IOException { + send( String.valueOf( val) ); + } + // Sends String without length prefix (pre-V100 style) + protected void send( String str) throws IOException { + // Write string to data buffer + try (Builder builder = new Builder( 1024 )) { + builder.send(str); + sendMsg(new EMessage(builder)); + } + } +} diff --git a/ref/client/EClientErrors.java b/ref/client/EClientErrors.java index aefb9ee..93171cd 100644 --- a/ref/client/EClientErrors.java +++ b/ref/client/EClientErrors.java @@ -6,12 +6,18 @@ public class EClientErrors { public static final int NO_VALID_ID = -1; - public static final CodeMsgPair NOT_CONNECTED = new CodeMsgPair(504, "Not connected"); - public static final CodeMsgPair UPDATE_TWS = new CodeMsgPair(503, "The TWS is out of date and must be upgraded."); static final CodeMsgPair ALREADY_CONNECTED = new CodeMsgPair(501, "Already connected."); - static final CodeMsgPair CONNECT_FAIL = new CodeMsgPair(502, "Couldn't connect to TWS. Confirm that \"Enable ActiveX and Socket Clients\" is enabled on the TWS \"Configure->API\" menu."); - static final CodeMsgPair FAIL_SEND = new CodeMsgPair(509, "Failed to send message - "); // generic message; all future messages should use this + static final CodeMsgPair CONNECT_FAIL = new CodeMsgPair(502, "Couldn't connect to TWS. Confirm that \"Enable ActiveX and Socket Clients\" " + + "is enabled and connection port is the same as \"Socket Port\" on the TWS \"Edit->Global Configuration...->API->Settings\" menu. " + + "Live Trading ports: TWS: 7496; IB Gateway: 4001. Simulated Trading ports for new installations of version 954.1 or newer: " + + "TWS: 7497; IB Gateway: 4002"); + public static final CodeMsgPair UPDATE_TWS = new CodeMsgPair(503, "The TWS is out of date and must be upgraded."); + public static final CodeMsgPair NOT_CONNECTED = new CodeMsgPair(504, "Not connected"); static final CodeMsgPair UNKNOWN_ID = new CodeMsgPair(505, "Fatal Error: Unknown message id."); + static final CodeMsgPair UNSUPPORTED_VERSION = new CodeMsgPair(506, "Unsupported Version"); + static final CodeMsgPair BAD_LENGTH = new CodeMsgPair(507, "Bad Message Length"); + static final CodeMsgPair BAD_MESSAGE = new CodeMsgPair(508, "Bad Message"); + static final CodeMsgPair FAIL_SEND = new CodeMsgPair(509, "Failed to send message - "); // generic message; all future messages should use this static final CodeMsgPair FAIL_SEND_REQMKT = new CodeMsgPair(510, "Request Market Data Sending Error - "); static final CodeMsgPair FAIL_SEND_CANMKT = new CodeMsgPair(511, "Cancel Market Data Sending Error - "); static final CodeMsgPair FAIL_SEND_ORDER = new CodeMsgPair(512, "Order Sending Error - "); @@ -46,6 +52,35 @@ public class EClientErrors { static final CodeMsgPair FAIL_SEND_CANPOSITIONS = new CodeMsgPair(541, "Cancel Positions Sending Error - "); static final CodeMsgPair FAIL_SEND_REQACCOUNTDATA = new CodeMsgPair(542, "Request Account Data Sending Error - "); static final CodeMsgPair FAIL_SEND_CANACCOUNTDATA = new CodeMsgPair(543, "Cancel Account Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_VERIFYREQUEST = new CodeMsgPair(544, "Verify Request Sending Error - "); + static final CodeMsgPair FAIL_SEND_VERIFYMESSAGE = new CodeMsgPair(545, "Verify Message Sending Error - "); + static final CodeMsgPair FAIL_SEND_QUERYDISPLAYGROUPS = new CodeMsgPair(546, "Query Display Groups Sending Error - "); + static final CodeMsgPair FAIL_SEND_SUBSCRIBETOGROUPEVENTS = new CodeMsgPair(547, "Subscribe To Group Events Sending Error - "); + static final CodeMsgPair FAIL_SEND_UPDATEDISPLAYGROUP = new CodeMsgPair(548, "Update Display Group Sending Error - "); + static final CodeMsgPair FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS = new CodeMsgPair(549, "Unsubscribe From Group Events Sending Error - "); + static final CodeMsgPair FAIL_SEND_STARTAPI = new CodeMsgPair(550, "Start API Sending Error - "); + static final CodeMsgPair FAIL_SEND_VERIFYANDAUTHREQUEST = new CodeMsgPair(551, "Verify And Auth Request Sending Error - "); + static final CodeMsgPair FAIL_SEND_VERIFYANDAUTHMESSAGE = new CodeMsgPair(552, "Verify And Auth Message Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQPOSITIONSMULTI = new CodeMsgPair(553, "Request Positions Multi Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANPOSITIONSMULTI = new CodeMsgPair(554, "Cancel Positions Multi Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQACCOUNTUPDATESMULTI = new CodeMsgPair(555, "Request Account Updates Multi Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANACCOUNTUPDATESMULTI = new CodeMsgPair(556, "Cancel Account Updates Multi Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQSECDEFOPTPARAMS = new CodeMsgPair(557, "Request Security Definition Option Params Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQSOFTDOLLARTIERS = new CodeMsgPair(558, "Request Soft Dollar Tiers Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQFAMILYCODES = new CodeMsgPair(559, "Request Family Codes Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQMATCHINGSYMBOLS = new CodeMsgPair(560, "Request Matching Symbols Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQMKTDEPTHEXCHANGES = new CodeMsgPair(561, "Request Market Depth Exchanges Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQSMARTCOMPONENTS = new CodeMsgPair(562, "Request Smart Components Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQNEWSPROVIDERS = new CodeMsgPair(563, "Request News Providers Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQNEWSARTICLE = new CodeMsgPair(564, "Request News Article Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQHISTORICALNEWS = new CodeMsgPair(565, "Request Historical News Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQHEADTIMESTAMP = new CodeMsgPair(566, "Request Head Time Stamp Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANHEADTIMESTAMP = new CodeMsgPair(567, "Cancel Head Time Stamp Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQMARKETRULE = new CodeMsgPair(568, "Request Market Rule Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQPNL = new CodeMsgPair(566, "Request PnL Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANPNL = new CodeMsgPair(567, "Cancel PnL Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQPNL_SINGLE = new CodeMsgPair(568, "Request PnL Single Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANPNL_SINGLE = new CodeMsgPair(569, "Cancel PnL Single Sending Error - "); public EClientErrors() { } diff --git a/ref/client/EClientMsgSink.java b/ref/client/EClientMsgSink.java new file mode 100644 index 0000000..35fde1c --- /dev/null +++ b/ref/client/EClientMsgSink.java @@ -0,0 +1,6 @@ +package com.ib.client; + +interface EClientMsgSink { + void serverVersion(int version, String time); + void redirect(String host); +} diff --git a/ref/client/EClientSocket.java b/ref/client/EClientSocket.java index 40d12b8..ecc788c 100644 --- a/ref/client/EClientSocket.java +++ b/ref/client/EClientSocket.java @@ -1,2338 +1,237 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - package com.ib.client; import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FilterOutputStream; +import java.io.FilterInputStream; import java.io.IOException; import java.net.Socket; -public class EClientSocket { - - // Client version history - // - // 6 = Added parentId to orderStatus - // 7 = The new execDetails event returned for an order filled status and reqExecDetails - // Also market depth is available. - // 8 = Added lastFillPrice to orderStatus() event and permId to execution details - // 9 = Added 'averageCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event - // 10 = Added 'serverId' to the 'open order' & 'order status' events. - // We send back all the API open orders upon connection. - // Added new methods reqAllOpenOrders, reqAutoOpenOrders() - // Added FA support - reqExecution has filter. - // - reqAccountUpdates takes acct code. - // 11 = Added permId to openOrder event. - // 12 = requsting open order attributes ignoreRth, hidden, and discretionary - // 13 = added goodAfterTime - // 14 = always send size on bid/ask/last tick - // 15 = send allocation description string on openOrder - // 16 = can receive account name in account and portfolio updates, and fa params in openOrder - // 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data - // 18 = can receive good till date field in open order messages, and request intraday backfill - // 19 = can receive rthOnly flag in ORDER_STATUS - // 20 = expects TWS time string on connection after server version >= 20. - // 21 = can receive bond contract details. - // 22 = can receive price magnifier in version 2 contract details message - // 23 = support for scanner - // 24 = can receive volatility order parameters in open order messages - // 25 = can receive HMDS query start and end times - // 26 = can receive option vols in option market data messages - // 27 = can receive delta neutral order type and delta neutral aux price in place order version 20: API 8.85 - // 28 = can receive option model computation ticks: API 8.9 - // 29 = can receive trail stop limit price in open order and can place them: API 8.91 - // 30 = can receive extended bond contract def, new ticks, and trade count in bars - // 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders - // ; can receive RT bars - // 32 = can receive TickType.LAST_TIMESTAMP - // ; can receive "whyHeld" in order status messages - // 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages - // 34 = can receive whatIf orders / order state - // 35 = can receive contId field for Contract objects - // 36 = can receive outsideRth field for Order objects - // 37 = can receive clearingAccount and clearingIntent for Order objects - // 38 = can receive multiplier and primaryExchange in portfolio updates - // ; can receive cumQty and avgPrice in execution - // ; can receive fundamental data - // ; can receive underComp for Contract objects - // ; can receive reqId and end marker in contractDetails/bondContractDetails - // ; can receive ScaleInitComponentSize and ScaleSubsComponentSize for Order objects - // 39 = can receive underConId in contractDetails - // 40 = can receive algoStrategy/algoParams in openOrder - // 41 = can receive end marker for openOrder - // ; can receive end marker for account download - // ; can receive end marker for executions download - // 42 = can receive deltaNeutralValidation - // 43 = can receive longName(companyName) - // ; can receive listingExchange - // ; can receive RTVolume tick - // 44 = can receive end market for ticker snapshot - // 45 = can receive notHeld field in openOrder - // 46 = can receive contractMonth, industry, category, subcategory fields in contractDetails - // ; can receive timeZoneId, tradingHours, liquidHours fields in contractDetails - // 47 = can receive gamma, vega, theta, undPrice fields in TICK_OPTION_COMPUTATION - // 48 = can receive exemptCode in openOrder - // 49 = can receive hedgeType and hedgeParam in openOrder - // 50 = can receive optOutSmartRouting field in openOrder - // 51 = can receive smartComboRoutingParams in openOrder - // 52 = can receive deltaNeutralConId, deltaNeutralSettlingFirm, deltaNeutralClearingAccount and deltaNeutralClearingIntent in openOrder - // 53 = can receive orderRef in execution - // 54 = can receive scale order fields (PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset, - // InitPosition, InitFillQty and RandomPercent) in openOrder - // 55 = can receive orderComboLegs (price) in openOrder - // 56 = can receive trailingPercent in openOrder - // 57 = can receive commissionReport message - // 58 = can receive CUSIP/ISIN/etc. in contractDescription/bondContractDescription - // 59 = can receive evRule, evMultiplier in contractDescription/bondContractDescription/executionDetails - // can receive multiplier in executionDetails - // 60 = can receive deltaNeutralOpenClose, deltaNeutralShortSale, deltaNeutralShortSaleSlot and deltaNeutralDesignatedLocation in openOrder - // 61 = can receive multiplier in openOrder - // can receive tradingClass in openOrder, updatePortfolio, execDetails and position - // 62 = can receive avgCost in position message - - private static final int CLIENT_VERSION = 62; - private static final int SERVER_VERSION = 38; - private static final byte[] EOL = {0}; - private static final String BAG_SEC_TYPE = "BAG"; - - // FA msg data types - public static final int GROUPS = 1; - public static final int PROFILES = 2; - public static final int ALIASES = 3; - - public static String faMsgTypeName(int faDataType) { - switch (faDataType) { - case GROUPS: - return "GROUPS"; - case PROFILES: - return "PROFILES"; - case ALIASES: - return "ALIASES"; - } - return null; - } - - // outgoing msg id's - private static final int REQ_MKT_DATA = 1; - private static final int CANCEL_MKT_DATA = 2; - protected static final int PLACE_ORDER = 3; - private static final int CANCEL_ORDER = 4; - private static final int REQ_OPEN_ORDERS = 5; - private static final int REQ_ACCOUNT_DATA = 6; - private static final int REQ_EXECUTIONS = 7; - private static final int REQ_IDS = 8; - private static final int REQ_CONTRACT_DATA = 9; - private static final int REQ_MKT_DEPTH = 10; - private static final int CANCEL_MKT_DEPTH = 11; - private static final int REQ_NEWS_BULLETINS = 12; - private static final int CANCEL_NEWS_BULLETINS = 13; - private static final int SET_SERVER_LOGLEVEL = 14; - private static final int REQ_AUTO_OPEN_ORDERS = 15; - private static final int REQ_ALL_OPEN_ORDERS = 16; - private static final int REQ_MANAGED_ACCTS = 17; - private static final int REQ_FA = 18; - private static final int REPLACE_FA = 19; - private static final int REQ_HISTORICAL_DATA = 20; - private static final int EXERCISE_OPTIONS = 21; - private static final int REQ_SCANNER_SUBSCRIPTION = 22; - private static final int CANCEL_SCANNER_SUBSCRIPTION = 23; - private static final int REQ_SCANNER_PARAMETERS = 24; - private static final int CANCEL_HISTORICAL_DATA = 25; - private static final int REQ_CURRENT_TIME = 49; - private static final int REQ_REAL_TIME_BARS = 50; - private static final int CANCEL_REAL_TIME_BARS = 51; - private static final int REQ_FUNDAMENTAL_DATA = 52; - private static final int CANCEL_FUNDAMENTAL_DATA = 53; - private static final int REQ_CALC_IMPLIED_VOLAT = 54; - private static final int REQ_CALC_OPTION_PRICE = 55; - private static final int CANCEL_CALC_IMPLIED_VOLAT = 56; - private static final int CANCEL_CALC_OPTION_PRICE = 57; - private static final int REQ_GLOBAL_CANCEL = 58; - private static final int REQ_MARKET_DATA_TYPE = 59; - private static final int REQ_POSITIONS = 61; - private static final int REQ_ACCOUNT_SUMMARY = 62; - private static final int CANCEL_ACCOUNT_SUMMARY = 63; - private static final int CANCEL_POSITIONS = 64; - - private static final int MIN_SERVER_VER_REAL_TIME_BARS = 34; - private static final int MIN_SERVER_VER_SCALE_ORDERS = 35; - private static final int MIN_SERVER_VER_SNAPSHOT_MKT_DATA = 35; - private static final int MIN_SERVER_VER_SSHORT_COMBO_LEGS = 35; - private static final int MIN_SERVER_VER_WHAT_IF_ORDERS = 36; - private static final int MIN_SERVER_VER_CONTRACT_CONID = 37; - private static final int MIN_SERVER_VER_PTA_ORDERS = 39; - private static final int MIN_SERVER_VER_FUNDAMENTAL_DATA = 40; - private static final int MIN_SERVER_VER_UNDER_COMP = 40; - private static final int MIN_SERVER_VER_CONTRACT_DATA_CHAIN = 40; - private static final int MIN_SERVER_VER_SCALE_ORDERS2 = 40; - private static final int MIN_SERVER_VER_ALGO_ORDERS = 41; - private static final int MIN_SERVER_VER_EXECUTION_DATA_CHAIN = 42; - private static final int MIN_SERVER_VER_NOT_HELD = 44; - private static final int MIN_SERVER_VER_SEC_ID_TYPE = 45; - private static final int MIN_SERVER_VER_PLACE_ORDER_CONID = 46; - private static final int MIN_SERVER_VER_REQ_MKT_DATA_CONID = 47; - private static final int MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT = 49; - private static final int MIN_SERVER_VER_REQ_CALC_OPTION_PRICE = 50; - private static final int MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT = 50; - private static final int MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE = 50; - private static final int MIN_SERVER_VER_SSHORTX_OLD = 51; - private static final int MIN_SERVER_VER_SSHORTX = 52; - private static final int MIN_SERVER_VER_REQ_GLOBAL_CANCEL = 53; - private static final int MIN_SERVER_VER_HEDGE_ORDERS = 54; - private static final int MIN_SERVER_VER_REQ_MARKET_DATA_TYPE = 55; - private static final int MIN_SERVER_VER_OPT_OUT_SMART_ROUTING = 56; - private static final int MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS = 57; - private static final int MIN_SERVER_VER_DELTA_NEUTRAL_CONID = 58; - private static final int MIN_SERVER_VER_SCALE_ORDERS3 = 60; - private static final int MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE = 61; - private static final int MIN_SERVER_VER_TRAILING_PERCENT = 62; - protected static final int MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE = 66; - private static final int MIN_SERVER_VER_ACCT_SUMMARY = 67; - protected static final int MIN_SERVER_VER_TRADING_CLASS = 68; - protected static final int MIN_SERVER_VER_SCALE_TABLE = 69; - - private AnyWrapper m_anyWrapper; // msg handler - protected DataOutputStream m_dos; // the socket output stream - private boolean m_connected; // true if we are connected - private EReader m_reader; // thread which reads msgs from socket - protected int m_serverVersion; - private String m_TwsTime; - - public int serverVersion() { return m_serverVersion; } - public String TwsConnectionTime() { return m_TwsTime; } - public AnyWrapper wrapper() { return m_anyWrapper; } - public EReader reader() { return m_reader; } - public boolean isConnected() { return m_connected; } - - - public EClientSocket( AnyWrapper anyWrapper) { - m_anyWrapper = anyWrapper; - } - - public synchronized void eConnect( String host, int port, int clientId) { - // already connected? - host = checkConnected(host); - if(host == null){ - return; - } - try{ - Socket socket = new Socket( host, port); - eConnect(socket, clientId); - } - catch( Exception e) { - eDisconnect(); - connectionError(); - } - } - - protected void connectionError() { - m_anyWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.CONNECT_FAIL.code(), - EClientErrors.CONNECT_FAIL.msg()); - m_reader = null; - } - - protected String checkConnected(String host) { - if( m_connected) { - m_anyWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.ALREADY_CONNECTED.code(), - EClientErrors.ALREADY_CONNECTED.msg()); - return null; - } - if( isNull( host) ) { - host = "127.0.0.1"; - } - return host; - } - - public EReader createReader(EClientSocket socket, DataInputStream dis) { - return new EReader(socket, dis); - } - - public synchronized void eConnect(Socket socket, int clientId) throws IOException { - - // create io streams - m_dos = new DataOutputStream( socket.getOutputStream() ); - - // set client version - send( CLIENT_VERSION); - - // start reader thread - m_reader = createReader(this, new DataInputStream( - socket.getInputStream())); - - // check server version - m_serverVersion = m_reader.readInt(); - System.out.println("Server Version:" + m_serverVersion); - if ( m_serverVersion >= 20 ){ - m_TwsTime = m_reader.readStr(); - System.out.println("TWS Time at connection:" + m_TwsTime); - } - if( m_serverVersion < SERVER_VERSION) { - eDisconnect(); - m_anyWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), EClientErrors.UPDATE_TWS.msg()); - return; - } - - // Send the client id - if ( m_serverVersion >= 3 ){ - send( clientId); - } - - m_reader.start(); - - // set connected flag - m_connected = true; - } - +public class EClientSocket extends EClient implements EClientMsgSink { + + protected int m_redirectCount = 0; + protected int m_defaultPort; + private boolean m_allowRedirect; + protected DataInputStream m_dis; + private boolean m_asyncEConnect = false; + private boolean m_connected = false; + private Socket m_socket; + + public void setAsyncEConnect(boolean asyncEConnect) { + this.m_asyncEConnect = asyncEConnect; + } + + public boolean isAsyncEConnect() { + return m_asyncEConnect; + } + + public EClientSocket(EWrapper eWrapper, EReaderSignal signal) { + super(eWrapper, signal); + } + + @Override + protected Builder prepareBuffer() { + Builder buf = new Builder( 1024 ); + if( m_useV100Plus ) { + buf.allocateLengthHeader(); + } + return buf; + } + + @Override + protected void closeAndSend(Builder buf) throws IOException { + if( m_useV100Plus ) { + buf.updateLength( 0 ); // New buffer means length header position is always zero + } + + EMessage msg = new EMessage(buf); + + sendMsg(msg); + } + + protected synchronized void eConnect(Socket socket) throws IOException { + // create io streams + m_socketTransport = new ESocket(socket); + m_dis = new DataInputStream(socket.getInputStream()); + m_defaultPort = socket.getPort(); + m_socket = socket; + + sendConnectRequest(); + + // start reader thread + EReader reader = new EReader(this, m_signal); + + if (!m_asyncEConnect) { + reader.putMessageToQueue(); + + while (m_serverVersion == 0) { + m_signal.waitForSignal(); + reader.processMsgs(); + } + } + } + + public synchronized void eConnect(Socket socket, int clientId) throws IOException { + m_clientId = clientId; + m_redirectCount = 0; + eConnect(socket); + } + + public synchronized void eConnect( String host, int port, int clientId) { + eConnect(host, port, clientId, false); + } + + public synchronized void eConnect( String host, int port, int clientId, boolean extraAuth) { + // already connected? + m_host = checkConnected(host); + + m_clientId = clientId; + m_extraAuth = extraAuth; + m_redirectCount = 0; + + if(m_host == null){ + return; + } + try{ + Socket socket = new Socket( m_host, port); + eConnect(socket); + } + catch( Exception e) { + eDisconnect(); + connectionError(); + } + } + + public boolean allowRedirect() { + return m_allowRedirect; + } + + public void allowRedirect(boolean val) { + m_allowRedirect = val; + } + + @Override + public synchronized void redirect(String newAddress) { + if( m_useV100Plus ) { + if (!m_allowRedirect) { + m_eWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.CONNECT_FAIL.code(), EClientErrors.CONNECT_FAIL.msg()); + return; + } + + ++m_redirectCount; + + if ( m_redirectCount > REDIRECT_COUNT_MAX ) { + eDisconnect(); + m_eWrapper.error( "Redirect count exceeded" ); + return; + } + + eDisconnect( false ); + + try { + performRedirect( newAddress, m_defaultPort ); + } catch (IOException e) { + m_eWrapper.error(e); + } + } + } + + @Override + public synchronized void serverVersion(int version, String time) { + m_serverVersion = version; + m_TwsTime = time; + + if( m_useV100Plus && (m_serverVersion < MIN_VERSION || m_serverVersion > MAX_VERSION) ) { + eDisconnect(); + m_eWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.UNSUPPORTED_VERSION.code(), EClientErrors.UNSUPPORTED_VERSION.msg()); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_SUPPORTED) { + eDisconnect(); + m_eWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), EClientErrors.UPDATE_TWS.msg()); + return; + } + + if ( m_serverVersion < MIN_SERVER_VER_LINKING) { + try { + send( m_clientId); + } catch (IOException e) { + m_eWrapper.error(e); + } + } + + + // set connected flag + m_connected = true; + + if (!m_asyncEConnect) + startAPI(); + } + + protected synchronized void performRedirect( String address, int defaultPort ) throws IOException { + System.out.println("Server Redirect: " + address); + + // Get host:port from address string and reconnect (note: port is optional) + String[] array = address.split(":"); + m_host = array[0]; // reset connected host + int newPort; + try { + newPort = ( array.length > 1 ) ? Integer.parseInt(array[1]) : defaultPort; + } + catch ( NumberFormatException e ) { + System.out.println( "Warning: redirect port is invalid, using default port"); + newPort = defaultPort; + } + eConnect( new Socket( m_host, newPort ) ); + } + + @Override public synchronized void eDisconnect() { - // not connected? - if( m_dos == null) { - return; - } - - m_connected = false; - m_serverVersion = 0; - m_TwsTime = ""; - - FilterOutputStream dos = m_dos; - m_dos = null; - - EReader reader = m_reader; - m_reader = null; - - try { - // stop reader thread; reader thread will close input stream - if( reader != null) { - reader.interrupt(); - } - } - catch( Exception e) { - } - - try { - // close output stream - if( dos != null) { - dos.close(); - } - } - catch( Exception e) { - } - } - - public synchronized void cancelScannerSubscription( int tickerId) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < 24) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support API scanner subscription."); - return; - } - - final int VERSION = 1; - - // send cancel mkt data msg - try { - send( CANCEL_SCANNER_SUBSCRIPTION); - send( VERSION); - send( tickerId); - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_CANSCANNER, "" + e); - close(); - } - } - - public synchronized void reqScannerParameters() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < 24) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support API scanner subscription."); - return; - } - - final int VERSION = 1; - - try { - send(REQ_SCANNER_PARAMETERS); - send(VERSION); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, - EClientErrors.FAIL_SEND_REQSCANNERPARAMETERS, "" + e); - close(); - } - } - - public synchronized void reqScannerSubscription( int tickerId, ScannerSubscription subscription) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < 24) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support API scanner subscription."); - return; - } - - final int VERSION = 3; - - try { - send(REQ_SCANNER_SUBSCRIPTION); - send(VERSION); - send(tickerId); - sendMax(subscription.numberOfRows()); - send(subscription.instrument()); - send(subscription.locationCode()); - send(subscription.scanCode()); - sendMax(subscription.abovePrice()); - sendMax(subscription.belowPrice()); - sendMax(subscription.aboveVolume()); - sendMax(subscription.marketCapAbove()); - sendMax(subscription.marketCapBelow()); - send(subscription.moodyRatingAbove()); - send(subscription.moodyRatingBelow()); - send(subscription.spRatingAbove()); - send(subscription.spRatingBelow()); - send(subscription.maturityDateAbove()); - send(subscription.maturityDateBelow()); - sendMax(subscription.couponRateAbove()); - sendMax(subscription.couponRateBelow()); - send(subscription.excludeConvertible()); - if (m_serverVersion >= 25) { - sendMax(subscription.averageOptionVolumeAbove()); - send(subscription.scannerSettingPairs()); - } - if (m_serverVersion >= 27) { - send(subscription.stockTypeFilter()); - } - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_REQSCANNER, "" + e); - close(); - } - } - - public synchronized void reqMktData(int tickerId, Contract contract, - String genericTickList, boolean snapshot) { - if (!m_connected) { - error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_SNAPSHOT_MKT_DATA && snapshot) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support snapshot market data requests."); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { - if (contract.m_underComp != null) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support delta-neutral orders."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_REQ_MKT_DATA_CONID) { - if (contract.m_conId > 0) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support conId parameter."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass)) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support tradingClass parameter in reqMarketData."); - return; - } - } - - final int VERSION = 10; - - try { - // send req mkt data msg - send(REQ_MKT_DATA); - send(VERSION); - send(tickerId); - - // send contract fields - if (m_serverVersion >= MIN_SERVER_VER_REQ_MKT_DATA_CONID) { - send(contract.m_conId); - } - send(contract.m_symbol); - send(contract.m_secType); - send(contract.m_expiry); - send(contract.m_strike); - send(contract.m_right); - if (m_serverVersion >= 15) { - send(contract.m_multiplier); - } - send(contract.m_exchange); - if (m_serverVersion >= 14) { - send(contract.m_primaryExch); - } - send(contract.m_currency); - if(m_serverVersion >= 2) { - send( contract.m_localSymbol); - } - if(m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send( contract.m_tradingClass); - } - if(m_serverVersion >= 8 && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { - if ( contract.m_comboLegs == null ) { - send( 0); - } - else { - send( contract.m_comboLegs.size()); - - ComboLeg comboLeg; - for (int i=0; i < contract.m_comboLegs.size(); i ++) { - comboLeg = contract.m_comboLegs.get(i); - send( comboLeg.m_conId); - send( comboLeg.m_ratio); - send( comboLeg.m_action); - send( comboLeg.m_exchange); - } - } - } - - if (m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { - if (contract.m_underComp != null) { - UnderComp underComp = contract.m_underComp; - send( true); - send( underComp.m_conId); - send( underComp.m_delta); - send( underComp.m_price); - } - else { - send( false); - } - } - - if (m_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. - */ - send( genericTickList); - } - if (m_serverVersion >= MIN_SERVER_VER_SNAPSHOT_MKT_DATA) { - send (snapshot); - } - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_REQMKT, "" + e); - close(); - } - } - - public synchronized void cancelHistoricalData( int tickerId ) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < 24) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support historical data query cancellation."); - return; - } - - final int VERSION = 1; - - // send cancel mkt data msg - try { - send( CANCEL_HISTORICAL_DATA); - send( VERSION); - send( tickerId); - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_CANHISTDATA, "" + e); - close(); - } - } - - public void cancelRealTimeBars(int tickerId) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support realtime bar data query cancellation."); - return; - } - - final int VERSION = 1; - - // send cancel mkt data msg - try { - send( CANCEL_REAL_TIME_BARS); - send( VERSION); - send( tickerId); - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_CANRTBARS, "" + e); - close(); - } - } - - /** Note that formatData parameter affects intra-day bars only; 1-day bars always return with date in YYYYMMDD format. */ - public synchronized void reqHistoricalData( int tickerId, Contract contract, - String endDateTime, String durationStr, - String barSizeSetting, String whatToShow, - int useRTH, int formatDate) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 5; - - try { - if (m_serverVersion < 16) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support historical data backfill."); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass) || (contract.m_conId > 0)) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support conId and tradingClass parameters in reqHistroricalData."); - return; - } - } - - send(REQ_HISTORICAL_DATA); - send(VERSION); - send(tickerId); - - // send contract fields - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_conId); - } - send(contract.m_symbol); - send(contract.m_secType); - send(contract.m_expiry); - send(contract.m_strike); - send(contract.m_right); - send(contract.m_multiplier); - send(contract.m_exchange); - send(contract.m_primaryExch); - send(contract.m_currency); - send(contract.m_localSymbol); - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - if (m_serverVersion >= 31) { - send(contract.m_includeExpired ? 1 : 0); - } - if (m_serverVersion >= 20) { - send(endDateTime); - send(barSizeSetting); - } - send(durationStr); - send(useRTH); - send(whatToShow); - if (m_serverVersion > 16) { - send(formatDate); - } - if (BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { - if (contract.m_comboLegs == null) { - send(0); - } - else { - send(contract.m_comboLegs.size()); - - ComboLeg comboLeg; - for (int i = 0; i < contract.m_comboLegs.size(); i++) { - comboLeg = contract.m_comboLegs.get(i); - send(comboLeg.m_conId); - send(comboLeg.m_ratio); - send(comboLeg.m_action); - send(comboLeg.m_exchange); - } - } - } - } - catch (Exception e) { - error(tickerId, EClientErrors.FAIL_SEND_REQHISTDATA, "" + e); - close(); - } - } - - public synchronized void reqRealTimeBars(int tickerId, Contract contract, int barSize, String whatToShow, boolean useRTH) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support real time bars."); - return; - } - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass) || (contract.m_conId > 0)) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support conId and tradingClass parameters in reqRealTimeBars."); - return; - } - } - - final int VERSION = 2; - - try { - // send req mkt data msg - send(REQ_REAL_TIME_BARS); - send(VERSION); - send(tickerId); - - // send contract fields - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_conId); - } - send(contract.m_symbol); - send(contract.m_secType); - send(contract.m_expiry); - send(contract.m_strike); - send(contract.m_right); - send(contract.m_multiplier); - send(contract.m_exchange); - send(contract.m_primaryExch); - send(contract.m_currency); - send(contract.m_localSymbol); - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - send(barSize); // this parameter is not currently used - send(whatToShow); - send(useRTH); - - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_REQRTBARS, "" + e); - close(); - } - } - - public synchronized void reqContractDetails(int reqId, Contract contract) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - // This feature is only available for versions of TWS >=4 - if( m_serverVersion < 4) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), - EClientErrors.UPDATE_TWS.msg()); - return; - } - - if( m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { - if (!IsEmpty(contract.m_secIdType) || !IsEmpty(contract.m_secId)) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support secIdType and secId parameters."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass)) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support tradingClass parameter in reqContractDetails."); - return; - } - } - - final int VERSION = 7; - - try { - // send req mkt data msg - send( REQ_CONTRACT_DATA); - send( VERSION); - - if (m_serverVersion >= MIN_SERVER_VER_CONTRACT_DATA_CHAIN) { - send( reqId); - } - - // send contract fields - if (m_serverVersion >= MIN_SERVER_VER_CONTRACT_CONID) { - send(contract.m_conId); - } - send( contract.m_symbol); - send( contract.m_secType); - send( contract.m_expiry); - send( contract.m_strike); - send( contract.m_right); - if (m_serverVersion >= 15) { - send(contract.m_multiplier); - } - send( contract.m_exchange); - send( contract.m_currency); - send( contract.m_localSymbol); - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - if (m_serverVersion >= 31) { - send(contract.m_includeExpired); - } - if (m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE) { - send( contract.m_secIdType); - send( contract.m_secId); - } - - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQCONTRACT, "" + e); - close(); - } - } - - public synchronized void reqMktDepth( int tickerId, Contract contract, int numRows) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - // This feature is only available for versions of TWS >=6 - if( m_serverVersion < 6) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), - EClientErrors.UPDATE_TWS.msg()); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass) || (contract.m_conId > 0)) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support conId and tradingClass parameters in reqMktDepth."); - return; - } - } - - final int VERSION = 4; - - try { - // send req mkt data msg - send( REQ_MKT_DEPTH); - send( VERSION); - send( tickerId); - - // send contract fields - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_conId); - } - send( contract.m_symbol); - send( contract.m_secType); - send( contract.m_expiry); - send( contract.m_strike); - send( contract.m_right); - if (m_serverVersion >= 15) { - send(contract.m_multiplier); - } - send( contract.m_exchange); - send( contract.m_currency); - send( contract.m_localSymbol); - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - if (m_serverVersion >= 19) { - send( numRows); - } - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_REQMKTDEPTH, "" + e); - close(); - } - } - - public synchronized void cancelMktData( int tickerId) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send cancel mkt data msg - try { - send( CANCEL_MKT_DATA); - send( VERSION); - send( tickerId); - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_CANMKT, "" + e); - close(); - } - } - - public synchronized void cancelMktDepth( int tickerId) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - // This feature is only available for versions of TWS >=6 - if( m_serverVersion < 6) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), - EClientErrors.UPDATE_TWS.msg()); - return; - } - - final int VERSION = 1; - - // send cancel mkt data msg - try { - send( CANCEL_MKT_DEPTH); - send( VERSION); - send( tickerId); - } - catch( Exception e) { - error( tickerId, EClientErrors.FAIL_SEND_CANMKTDEPTH, "" + e); - close(); - } - } - - public synchronized void exerciseOptions( int tickerId, Contract contract, - int exerciseAction, int exerciseQuantity, - String account, int override) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 2; - - try { - if (m_serverVersion < 21) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support options exercise from the API."); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass) || (contract.m_conId > 0)) { - error(tickerId, EClientErrors.UPDATE_TWS, - " It does not support conId and tradingClass parameters in exerciseOptions."); - return; - } - } - - send(EXERCISE_OPTIONS); - send(VERSION); - send(tickerId); - - // send contract fields - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_conId); - } - send(contract.m_symbol); - send(contract.m_secType); - send(contract.m_expiry); - send(contract.m_strike); - send(contract.m_right); - send(contract.m_multiplier); - send(contract.m_exchange); - send(contract.m_currency); - send(contract.m_localSymbol); - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - send(exerciseAction); - send(exerciseQuantity); - send(account); - send(override); - } - catch (Exception e) { - error(tickerId, EClientErrors.FAIL_SEND_REQMKT, "" + e); - close(); - } - } - - public synchronized void placeOrder( int id, Contract contract, Order order) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS) { - if (order.m_scaleInitLevelSize != Integer.MAX_VALUE || - order.m_scalePriceIncrement != Double.MAX_VALUE) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support Scale orders."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_SSHORT_COMBO_LEGS) { - if (!contract.m_comboLegs.isEmpty()) { - ComboLeg comboLeg; - for (int i = 0; i < contract.m_comboLegs.size(); ++i) { - comboLeg = contract.m_comboLegs.get(i); - if (comboLeg.m_shortSaleSlot != 0 || - !IsEmpty(comboLeg.m_designatedLocation)) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support SSHORT flag for combo legs."); - return; - } - } - } - } - - if (m_serverVersion < MIN_SERVER_VER_WHAT_IF_ORDERS) { - if (order.m_whatIf) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support what-if orders."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { - if (contract.m_underComp != null) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support delta-neutral orders."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS2) { - if (order.m_scaleSubsLevelSize != Integer.MAX_VALUE) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support Subsequent Level Size for Scale orders."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_ALGO_ORDERS) { - if (!IsEmpty(order.m_algoStrategy)) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support algo orders."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_NOT_HELD) { - if (order.m_notHeld) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support notHeld parameter."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { - if (!IsEmpty(contract.m_secIdType) || !IsEmpty(contract.m_secId)) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support secIdType and secId parameters."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_PLACE_ORDER_CONID) { - if (contract.m_conId > 0) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support conId parameter."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { - if (order.m_exemptCode != -1) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support exemptCode parameter."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { - if (!contract.m_comboLegs.isEmpty()) { - ComboLeg comboLeg; - for (int i = 0; i < contract.m_comboLegs.size(); ++i) { - comboLeg = contract.m_comboLegs.get(i); - if (comboLeg.m_exemptCode != -1) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support exemptCode parameter."); - return; - } - } - } - } - - if (m_serverVersion < MIN_SERVER_VER_HEDGE_ORDERS) { - if (!IsEmpty(order.m_hedgeType)) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support hedge orders."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) { - if (order.m_optOutSmartRouting) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support optOutSmartRouting parameter."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_DELTA_NEUTRAL_CONID) { - if (order.m_deltaNeutralConId > 0 - || !IsEmpty(order.m_deltaNeutralSettlingFirm) - || !IsEmpty(order.m_deltaNeutralClearingAccount) - || !IsEmpty(order.m_deltaNeutralClearingIntent) - ) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent"); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE) { - if (!IsEmpty(order.m_deltaNeutralOpenClose) - || order.m_deltaNeutralShortSale - || order.m_deltaNeutralShortSaleSlot > 0 - || !IsEmpty(order.m_deltaNeutralDesignatedLocation) - ) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support deltaNeutral parameters: OpenClose, ShortSale, ShortSaleSlot, DesignatedLocation"); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS3) { - if (order.m_scalePriceIncrement > 0 && order.m_scalePriceIncrement != Double.MAX_VALUE) { - if (order.m_scalePriceAdjustValue != Double.MAX_VALUE || - order.m_scalePriceAdjustInterval != Integer.MAX_VALUE || - order.m_scaleProfitOffset != Double.MAX_VALUE || - order.m_scaleAutoReset || - order.m_scaleInitPosition != Integer.MAX_VALUE || - order.m_scaleInitFillQty != Integer.MAX_VALUE || - order.m_scaleRandomPercent) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support Scale order parameters: PriceAdjustValue, PriceAdjustInterval, " + - "ProfitOffset, AutoReset, InitPosition, InitFillQty and RandomPercent"); - return; - } - } - } - - if (m_serverVersion < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { - if (!order.m_orderComboLegs.isEmpty()) { - OrderComboLeg orderComboLeg; - for (int i = 0; i < order.m_orderComboLegs.size(); ++i) { - orderComboLeg = order.m_orderComboLegs.get(i); - if (orderComboLeg.m_price != Double.MAX_VALUE) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support per-leg prices for order combo legs."); - return; - } - } - } - } - - if (m_serverVersion < MIN_SERVER_VER_TRAILING_PERCENT) { - if (order.m_trailingPercent != Double.MAX_VALUE) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support trailing percent parameter"); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass)) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support tradingClass parameters in placeOrder."); - return; - } - } - - if (m_serverVersion < MIN_SERVER_VER_SCALE_TABLE) { - if (!IsEmpty(order.m_scaleTable) || !IsEmpty(order.m_activeStartTime) || !IsEmpty(order.m_activeStopTime)) { - error(id, EClientErrors.UPDATE_TWS, - " It does not support scaleTable, activeStartTime and activeStopTime parameters."); - return; - } - } - - int VERSION = (m_serverVersion < MIN_SERVER_VER_NOT_HELD) ? 27 : 41; - - // send place order msg - try { - send( PLACE_ORDER); - send( VERSION); - send( id); - - // send contract fields - if( m_serverVersion >= MIN_SERVER_VER_PLACE_ORDER_CONID) { - send(contract.m_conId); - } - send( contract.m_symbol); - send( contract.m_secType); - send( contract.m_expiry); - send( contract.m_strike); - send( contract.m_right); - if (m_serverVersion >= 15) { - send(contract.m_multiplier); - } - send( contract.m_exchange); - if( m_serverVersion >= 14) { - send(contract.m_primaryExch); - } - send( contract.m_currency); - if( m_serverVersion >= 2) { - send (contract.m_localSymbol); - } - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - if( m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE){ - send( contract.m_secIdType); - send( contract.m_secId); - } - - // send main order fields - send( order.m_action); - send( order.m_totalQuantity); - send( order.m_orderType); - if (m_serverVersion < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE) { - send( order.m_lmtPrice == Double.MAX_VALUE ? 0 : order.m_lmtPrice); - } - else { - sendMax( order.m_lmtPrice); - } - if (m_serverVersion < MIN_SERVER_VER_TRAILING_PERCENT) { - send( order.m_auxPrice == Double.MAX_VALUE ? 0 : order.m_auxPrice); - } - else { - sendMax( order.m_auxPrice); - } - - // send extended order fields - send( order.m_tif); - send( order.m_ocaGroup); - send( order.m_account); - send( order.m_openClose); - send( order.m_origin); - send( order.m_orderRef); - send( order.m_transmit); - if( m_serverVersion >= 4 ) { - send (order.m_parentId); - } - - if( m_serverVersion >= 5 ) { - send (order.m_blockOrder); - send (order.m_sweepToFill); - send (order.m_displaySize); - send (order.m_triggerMethod); - if (m_serverVersion < 38) { - // will never happen - send(/* order.m_ignoreRth */ false); - } - else { - send (order.m_outsideRth); - } - } - - if(m_serverVersion >= 7 ) { - send(order.m_hidden); - } - - // Send combo legs for BAG requests - if(m_serverVersion >= 8 && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { - if ( contract.m_comboLegs == null ) { - send( 0); - } - else { - send( contract.m_comboLegs.size()); - - ComboLeg comboLeg; - for (int i=0; i < contract.m_comboLegs.size(); i ++) { - comboLeg = contract.m_comboLegs.get(i); - send( comboLeg.m_conId); - send( comboLeg.m_ratio); - send( comboLeg.m_action); - send( comboLeg.m_exchange); - send( comboLeg.m_openClose); - - if (m_serverVersion >= MIN_SERVER_VER_SSHORT_COMBO_LEGS) { - send( comboLeg.m_shortSaleSlot); - send( comboLeg.m_designatedLocation); - } - if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { - send( comboLeg.m_exemptCode); - } - } - } - } - - // Send order combo legs for BAG requests - if(m_serverVersion >= MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { - if ( order.m_orderComboLegs == null ) { - send( 0); - } - else { - send( order.m_orderComboLegs.size()); - - for (int i = 0; i < order.m_orderComboLegs.size(); i++) { - OrderComboLeg orderComboLeg = order.m_orderComboLegs.get(i); - sendMax( orderComboLeg.m_price); - } - } - } - - if(m_serverVersion >= MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { - java.util.Vector smartComboRoutingParams = order.m_smartComboRoutingParams; - int smartComboRoutingParamsCount = smartComboRoutingParams == null ? 0 : smartComboRoutingParams.size(); - send( smartComboRoutingParamsCount); - if( smartComboRoutingParamsCount > 0) { - for( int i = 0; i < smartComboRoutingParamsCount; ++i) { - TagValue tagValue = (TagValue)smartComboRoutingParams.get(i); - send( tagValue.m_tag); - send( tagValue.m_value); - } - } - } - - if ( m_serverVersion >= 9 ) { - // send deprecated sharesAllocation field - send( ""); - } - - if ( m_serverVersion >= 10 ) { - send( order.m_discretionaryAmt); - } - - if ( m_serverVersion >= 11 ) { - send( order.m_goodAfterTime); - } - - if ( m_serverVersion >= 12 ) { - send( order.m_goodTillDate); - } - - if ( m_serverVersion >= 13 ) { - send( order.m_faGroup); - send( order.m_faMethod); - send( order.m_faPercentage); - send( order.m_faProfile); - } - if (m_serverVersion >= 18) { // institutional short sale slot fields. - send( order.m_shortSaleSlot); // 0 only for retail, 1 or 2 only for institution. - send( order.m_designatedLocation); // only populate when order.m_shortSaleSlot = 2. - } - if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { - send( order.m_exemptCode); - } - if (m_serverVersion >= 19) { - send( order.m_ocaType); - if (m_serverVersion < 38) { - // will never happen - send( /* order.m_rthOnly */ false); - } - send( order.m_rule80A); - send( order.m_settlingFirm); - send( order.m_allOrNone); - sendMax( order.m_minQty); - sendMax( order.m_percentOffset); - send( order.m_eTradeOnly); - send( order.m_firmQuoteOnly); - sendMax( order.m_nbboPriceCap); - sendMax( order.m_auctionStrategy); - sendMax( order.m_startingPrice); - sendMax( order.m_stockRefPrice); - sendMax( order.m_delta); - // Volatility orders had specific watermark price attribs in server version 26 - double lower = (m_serverVersion == 26 && order.m_orderType.equals("VOL")) - ? Double.MAX_VALUE - : order.m_stockRangeLower; - double upper = (m_serverVersion == 26 && order.m_orderType.equals("VOL")) - ? Double.MAX_VALUE - : order.m_stockRangeUpper; - sendMax( lower); - sendMax( upper); - } - - if (m_serverVersion >= 22) { - send( order.m_overridePercentageConstraints); - } - - if (m_serverVersion >= 26) { // Volatility orders - sendMax( order.m_volatility); - sendMax( order.m_volatilityType); - if (m_serverVersion < 28) { - send( order.m_deltaNeutralOrderType.equalsIgnoreCase("MKT")); - } else { - send( order.m_deltaNeutralOrderType); - sendMax( order.m_deltaNeutralAuxPrice); - - if (m_serverVersion >= MIN_SERVER_VER_DELTA_NEUTRAL_CONID && !IsEmpty(order.m_deltaNeutralOrderType)){ - send( order.m_deltaNeutralConId); - send( order.m_deltaNeutralSettlingFirm); - send( order.m_deltaNeutralClearingAccount); - send( order.m_deltaNeutralClearingIntent); - } - - if (m_serverVersion >= MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE && !IsEmpty(order.m_deltaNeutralOrderType)){ - send( order.m_deltaNeutralOpenClose); - send( order.m_deltaNeutralShortSale); - send( order.m_deltaNeutralShortSaleSlot); - send( order.m_deltaNeutralDesignatedLocation); - } - } - send( order.m_continuousUpdate); - if (m_serverVersion == 26) { - // Volatility orders had specific watermark price attribs in server version 26 - double lower = order.m_orderType.equals("VOL") ? order.m_stockRangeLower : Double.MAX_VALUE; - double upper = order.m_orderType.equals("VOL") ? order.m_stockRangeUpper : Double.MAX_VALUE; - sendMax( lower); - sendMax( upper); - } - sendMax( order.m_referencePriceType); - } - - if (m_serverVersion >= 30) { // TRAIL_STOP_LIMIT stop price - sendMax( order.m_trailStopPrice); - } - - if( m_serverVersion >= MIN_SERVER_VER_TRAILING_PERCENT){ - sendMax( order.m_trailingPercent); - } - - if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS) { - if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS2) { - sendMax (order.m_scaleInitLevelSize); - sendMax (order.m_scaleSubsLevelSize); - } - else { - send (""); - sendMax (order.m_scaleInitLevelSize); - - } - sendMax (order.m_scalePriceIncrement); - } - - if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS3 && order.m_scalePriceIncrement > 0.0 && order.m_scalePriceIncrement != Double.MAX_VALUE) { - sendMax (order.m_scalePriceAdjustValue); - sendMax (order.m_scalePriceAdjustInterval); - sendMax (order.m_scaleProfitOffset); - send (order.m_scaleAutoReset); - sendMax (order.m_scaleInitPosition); - sendMax (order.m_scaleInitFillQty); - send (order.m_scaleRandomPercent); - } - - if (m_serverVersion >= MIN_SERVER_VER_SCALE_TABLE) { - send (order.m_scaleTable); - send (order.m_activeStartTime); - send (order.m_activeStopTime); - } - - if (m_serverVersion >= MIN_SERVER_VER_HEDGE_ORDERS) { - send (order.m_hedgeType); - if (!IsEmpty(order.m_hedgeType)) { - send (order.m_hedgeParam); - } - } - - if (m_serverVersion >= MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) { - send (order.m_optOutSmartRouting); - } - - if (m_serverVersion >= MIN_SERVER_VER_PTA_ORDERS) { - send (order.m_clearingAccount); - send (order.m_clearingIntent); - } - - if (m_serverVersion >= MIN_SERVER_VER_NOT_HELD) { - send (order.m_notHeld); - } - - if (m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { - if (contract.m_underComp != null) { - UnderComp underComp = contract.m_underComp; - send( true); - send( underComp.m_conId); - send( underComp.m_delta); - send( underComp.m_price); - } - else { - send( false); - } - } - - if (m_serverVersion >= MIN_SERVER_VER_ALGO_ORDERS) { - send( order.m_algoStrategy); - if( !IsEmpty(order.m_algoStrategy)) { - java.util.Vector algoParams = order.m_algoParams; - int algoParamsCount = algoParams == null ? 0 : algoParams.size(); - send( algoParamsCount); - if( algoParamsCount > 0) { - for( int i = 0; i < algoParamsCount; ++i) { - TagValue tagValue = (TagValue)algoParams.get(i); - send( tagValue.m_tag); - send( tagValue.m_value); - } - } - } - } - - if (m_serverVersion >= MIN_SERVER_VER_WHAT_IF_ORDERS) { - send (order.m_whatIf); - } - } - catch( Exception e) { - error( id, EClientErrors.FAIL_SEND_ORDER, "" + e); - close(); - } - } - - public synchronized void reqAccountUpdates(boolean subscribe, String acctCode) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 2; - - // send cancel order msg - try { - send( REQ_ACCOUNT_DATA ); - send( VERSION); - send( subscribe); - - // Send the account code. This will only be used for FA clients - if ( m_serverVersion >= 9 ) { - send( acctCode); - } - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_ACCT, "" + e); - close(); - } - } - - public synchronized void reqExecutions(int reqId, ExecutionFilter filter) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 3; - - // send cancel order msg - try { - send( REQ_EXECUTIONS); - send( VERSION); - - if (m_serverVersion >= MIN_SERVER_VER_EXECUTION_DATA_CHAIN) { - send( reqId); - } - - // Send the execution rpt filter data - if ( m_serverVersion >= 9 ) { - send( filter.m_clientId); - send( filter.m_acctCode); - - // Note that the valid format for m_time is "yyyymmdd-hh:mm:ss" - send( filter.m_time); - send( filter.m_symbol); - send( filter.m_secType); - send( filter.m_exchange); - send( filter.m_side); - } - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_EXEC, "" + e); - close(); - } - } - - public synchronized void cancelOrder( int id) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send cancel order msg - try { - send( CANCEL_ORDER); - send( VERSION); - send( id); - } - catch( Exception e) { - error( id, EClientErrors.FAIL_SEND_CORDER, "" + e); - close(); - } - } - - public synchronized void reqOpenOrders() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send cancel order msg - try { - send( REQ_OPEN_ORDERS); - send( VERSION); - } - catch( Exception e) { - error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); - close(); - } - } - - public synchronized void reqIds( int numIds) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - try { - send( REQ_IDS); - send( VERSION); - send( numIds); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, "" + e); - close(); - } - } - - public synchronized void reqNewsBulletins( boolean allMsgs) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - try { - send( REQ_NEWS_BULLETINS); - send( VERSION); - send( allMsgs); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, "" + e); - close(); - } - } - - public synchronized void cancelNewsBulletins() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send cancel order msg - try { - send( CANCEL_NEWS_BULLETINS); - send( VERSION); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, "" + e); - close(); - } - } - - public synchronized void setServerLogLevel(int logLevel) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send the set server logging level message - try { - send( SET_SERVER_LOGLEVEL); - send( VERSION); - send( logLevel); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_SERVER_LOG_LEVEL, "" + e); - close(); - } - } - - public synchronized void reqAutoOpenOrders(boolean bAutoBind) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send req open orders msg - try { - send( REQ_AUTO_OPEN_ORDERS); - send( VERSION); - send( bAutoBind); - } - catch( Exception e) { - error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); - close(); - } - } - - public synchronized void reqAllOpenOrders() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send req all open orders msg - try { - send( REQ_ALL_OPEN_ORDERS); - send( VERSION); - } - catch( Exception e) { - error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); - close(); - } - } - - public synchronized void reqManagedAccts() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - final int VERSION = 1; - - // send req FA managed accounts msg - try { - send( REQ_MANAGED_ACCTS); - send( VERSION); - } - catch( Exception e) { - error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); - close(); - } - } - - public synchronized void requestFA( int faDataType ) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - // This feature is only available for versions of TWS >= 13 - if( m_serverVersion < 13) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), - EClientErrors.UPDATE_TWS.msg()); - return; - } - - final int VERSION = 1; - - try { - send( REQ_FA ); - send( VERSION); - send( faDataType); - } - catch( Exception e) { - error( faDataType, EClientErrors.FAIL_SEND_FA_REQUEST, "" + e); - close(); - } - } - - public synchronized void replaceFA( int faDataType, String xml ) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - // This feature is only available for versions of TWS >= 13 - if( m_serverVersion < 13) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), - EClientErrors.UPDATE_TWS.msg()); - return; - } - - final int VERSION = 1; - - try { - send( REPLACE_FA ); - send( VERSION); - send( faDataType); - send( xml); - } - catch( Exception e) { - error( faDataType, EClientErrors.FAIL_SEND_FA_REPLACE, "" + e); - close(); - } - } - - public synchronized void reqCurrentTime() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - // This feature is only available for versions of TWS >= 33 - if( m_serverVersion < 33) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support current time requests."); - return; - } - - final int VERSION = 1; - - try { - send( REQ_CURRENT_TIME ); - send( VERSION); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQCURRTIME, "" + e); - close(); - } - } - - public synchronized void reqFundamentalData(int reqId, Contract contract, String reportType) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { - error( reqId, EClientErrors.UPDATE_TWS, - " It does not support fundamental data requests."); - return; - } - - if( m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if( contract.m_conId > 0) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support conId parameter in reqFundamentalData."); - return; - } - } - - final int VERSION = 2; - - try { - // send req fund data msg - send( REQ_FUNDAMENTAL_DATA); - send( VERSION); - send( reqId); - - // send contract fields - if( m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_conId); - } - send( contract.m_symbol); - send( contract.m_secType); - send( contract.m_exchange); - send( contract.m_primaryExch); - send( contract.m_currency); - send( contract.m_localSymbol); - - send( reportType); - } - catch( Exception e) { - error( reqId, EClientErrors.FAIL_SEND_REQFUNDDATA, "" + e); - close(); - } - } - - public synchronized void cancelFundamentalData(int reqId) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { - error( reqId, EClientErrors.UPDATE_TWS, - " It does not support fundamental data requests."); - return; - } - - final int VERSION = 1; - - try { - // send req mkt data msg - send( CANCEL_FUNDAMENTAL_DATA); - send( VERSION); - send( reqId); - } - catch( Exception e) { - error( reqId, EClientErrors.FAIL_SEND_CANFUNDDATA, "" + e); - close(); - } - } - - public synchronized void calculateImpliedVolatility(int reqId, Contract contract, - double optionPrice, double underPrice) { - - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support calculate implied volatility requests."); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass)) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support tradingClass parameter in calculateImpliedVolatility."); - return; - } - } - - final int VERSION = 2; - - try { - // send calculate implied volatility msg - send( REQ_CALC_IMPLIED_VOLAT); - send( VERSION); - send( reqId); - - // send contract fields - send( contract.m_conId); - send( contract.m_symbol); - send( contract.m_secType); - send( contract.m_expiry); - send( contract.m_strike); - send( contract.m_right); - send( contract.m_multiplier); - send( contract.m_exchange); - send( contract.m_primaryExch); - send( contract.m_currency); - send( contract.m_localSymbol); - if( m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - - send( optionPrice); - send( underPrice); - } - catch( Exception e) { - error( reqId, EClientErrors.FAIL_SEND_REQCALCIMPLIEDVOLAT, "" + e); - close(); - } - } - - public synchronized void cancelCalculateImpliedVolatility(int reqId) { - - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support calculate implied volatility cancellation."); - return; - } - - final int VERSION = 1; - - try { - // send cancel calculate implied volatility msg - send( CANCEL_CALC_IMPLIED_VOLAT); - send( VERSION); - send( reqId); - } - catch( Exception e) { - error( reqId, EClientErrors.FAIL_SEND_CANCALCIMPLIEDVOLAT, "" + e); - close(); - } - } - - public synchronized void calculateOptionPrice(int reqId, Contract contract, - double volatility, double underPrice) { - - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_OPTION_PRICE) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support calculate option price requests."); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_TRADING_CLASS) { - if (!IsEmpty(contract.m_tradingClass)) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support tradingClass parameter in calculateOptionPrice."); - return; - } - } - - final int VERSION = 2; - - try { - // send calculate option price msg - send( REQ_CALC_OPTION_PRICE); - send( VERSION); - send( reqId); - - // send contract fields - send( contract.m_conId); - send( contract.m_symbol); - send( contract.m_secType); - send( contract.m_expiry); - send( contract.m_strike); - send( contract.m_right); - send( contract.m_multiplier); - send( contract.m_exchange); - send( contract.m_primaryExch); - send( contract.m_currency); - send( contract.m_localSymbol); - if( m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - send(contract.m_tradingClass); - } - - send( volatility); - send( underPrice); - } - catch( Exception e) { - error( reqId, EClientErrors.FAIL_SEND_REQCALCOPTIONPRICE, "" + e); - close(); - } - } - - public synchronized void cancelCalculateOptionPrice(int reqId) { - - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE) { - error(reqId, EClientErrors.UPDATE_TWS, - " It does not support calculate option price cancellation."); - return; - } - - final int VERSION = 1; - - try { - // send cancel calculate option price msg - send( CANCEL_CALC_OPTION_PRICE); - send( VERSION); - send( reqId); - } - catch( Exception e) { - error( reqId, EClientErrors.FAIL_SEND_CANCALCOPTIONPRICE, "" + e); - close(); - } - } - - public synchronized void reqGlobalCancel() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_REQ_GLOBAL_CANCEL) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support globalCancel requests."); - return; - } - - final int VERSION = 1; - - // send request global cancel msg - try { - send( REQ_GLOBAL_CANCEL); - send( VERSION); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQGLOBALCANCEL, "" + e); - close(); - } - } - - public synchronized void reqMarketDataType(int marketDataType) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_REQ_MARKET_DATA_TYPE) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support marketDataType requests."); - return; - } - - final int VERSION = 1; - - // send the reqMarketDataType message - try { - send( REQ_MARKET_DATA_TYPE); - send( VERSION); - send( marketDataType); - } - catch( Exception e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQMARKETDATATYPE, "" + e); - close(); - } - } - - public synchronized void reqPositions() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support position requests."); - return; - } - - final int VERSION = 1; - - Builder b = new Builder(); - b.send( REQ_POSITIONS); - b.send( VERSION); - - - try { - m_dos.write( b.getBytes() ); - } - catch (IOException e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQPOSITIONS, "" + e); - } - } - - public synchronized void cancelPositions() { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support position cancellation."); - return; - } - - final int VERSION = 1; - - Builder b = new Builder(); - b.send( CANCEL_POSITIONS); - b.send( VERSION); - - try { - m_dos.write( b.getBytes() ); - } - catch (IOException e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CANPOSITIONS, "" + e); - } - } - - public synchronized void reqAccountSummary( int reqId, String group, String tags) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support account summary requests."); - return; - } - - final int VERSION = 1; - - Builder b = new Builder(); - b.send( REQ_ACCOUNT_SUMMARY); - b.send( VERSION); - b.send( reqId); - b.send( group); - b.send( tags); - - try { - m_dos.write( b.getBytes() ); - } - catch (IOException e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQACCOUNTDATA, "" + e); - } - } - - public synchronized void cancelAccountSummary( int reqId) { - // not connected? - if( !m_connected) { - notConnected(); - return; - } - - if (m_serverVersion < MIN_SERVER_VER_ACCT_SUMMARY) { - error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, - " It does not support account summary cancellation."); - return; - } - - final int VERSION = 1; - - Builder b = new Builder(); - b.send( CANCEL_ACCOUNT_SUMMARY); - b.send( VERSION); - b.send( reqId); - - try { - m_dos.write( b.getBytes() ); - } - catch (IOException e) { - error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CANACCOUNTDATA, "" + e); - } - } - - /** @deprecated, never called. */ - protected synchronized void error( String err) { - m_anyWrapper.error( err); - } - - protected synchronized void error( int id, int errorCode, String errorMsg) { - m_anyWrapper.error( id, errorCode, errorMsg); - } - - protected void close() { - eDisconnect(); - wrapper().connectionClosed(); - } - - private static boolean is( String str) { - // return true if the string is not empty - return str != null && str.length() > 0; - } - - private static boolean isNull( String str) { - // return true if the string is null or empty - return !is( str); - } - - protected void error(int id, EClientErrors.CodeMsgPair pair, String tail) { - error(id, pair.code(), pair.msg() + tail); - } - - protected void send( String str) throws IOException { - // write string to data buffer; writer thread will - // write it to socket - if( !IsEmpty(str)) { - m_dos.write( str.getBytes() ); - } - sendEOL(); - } - - private void sendEOL() throws IOException { - m_dos.write( EOL); - } - - protected void send( int val) throws IOException { - send( String.valueOf( val) ); - } - - protected void send( char val) throws IOException { - m_dos.write( val); - sendEOL(); - } - - protected void send( double val) throws IOException { - send( String.valueOf( val) ); - } - - protected void send( long val) throws IOException { - send( String.valueOf( val) ); - } - - private void sendMax( double val) throws IOException { - if (val == Double.MAX_VALUE) { - sendEOL(); - } - else { - send(String.valueOf(val)); - } - } - - private void sendMax( int val) throws IOException { - if (val == Integer.MAX_VALUE) { - sendEOL(); - } - else { - send(String.valueOf(val)); - } - } - - protected void send( boolean val) throws IOException { - send( val ? 1 : 0); - } - - private static boolean IsEmpty(String str) { - return Util.StringIsEmpty(str); - } - - protected void notConnected() { - error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); - } + eDisconnect( true ); + } + + private synchronized void eDisconnect( boolean resetState ) { + // not connected? + if( m_dis == null && m_socketTransport == null) { + return; + } + + if ( resetState ) { + m_connected = false; + m_extraAuth = false; + m_clientId = -1; + m_serverVersion = 0; + m_TwsTime = ""; + m_redirectCount = 0; + } + + FilterInputStream dis = m_dis; + m_dis = null; + if (m_socketTransport != null) { + try { + m_socketTransport.close(); + } catch (IOException ignored) { + } finally { + m_socketTransport = null; + } + } + + try { + if (dis != null) + dis.close(); + } catch (Exception ignored) { + } + } + + public int read(byte[] buf, int off, int len) throws IOException { + return m_dis.read(buf, off, len); + } + + public int readInt() throws IOException { + return m_dis.readInt(); + } + + @Override + public synchronized boolean isConnected() { + return m_socket != null && m_socket.isConnected() && m_connected; + } } diff --git a/ref/client/EClientSocketSSL.java b/ref/client/EClientSocketSSL.java new file mode 100644 index 0000000..a256f68 --- /dev/null +++ b/ref/client/EClientSocketSSL.java @@ -0,0 +1,89 @@ +package com.ib.client; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +public class EClientSocketSSL extends EClientSocket { + + public EClientSocketSSL(EWrapper eWrapper, EReaderSignal signal) { + super(eWrapper, signal); + + SSLContext ctx; + try { + ctx = SSLContext.getInstance("TLS"); + ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom()); + SSLContext.setDefault(ctx); + } catch (KeyManagementException | NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private static class DefaultTrustManager implements X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } + + @Override + public synchronized void eConnect( String host, int port, int clientId, boolean extraAuth) { + // already connected? + m_host = checkConnected(host); + + m_clientId = clientId; + m_extraAuth = extraAuth; + m_redirectCount = 0; + + if(m_host == null){ + return; + } + + try{ + SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(m_host, port); + eConnect(socket); + } + catch( Exception e) { + eDisconnect(); + wrapper().error(e); + } + } + + @Override + protected synchronized void performRedirect( String address, int defaultPort ) throws IOException { + System.out.println("Server Redirect: " + address); + + // Get host:port from address string and reconnect (note: port is optional) + String[] array = address.split(":"); + m_host = array[0]; // reset connected host + int newPort; + + try { + newPort = ( array.length > 1 ) ? Integer.parseInt(array[1]) : defaultPort; + } + catch ( NumberFormatException e ) { + System.out.println( "Warning: redirect port is invalid, using default port"); + newPort = defaultPort; + } + + eConnect( SSLSocketFactory.getDefault().createSocket( m_host, newPort ) ); + } +} diff --git a/ref/client/EDecoder.java b/ref/client/EDecoder.java new file mode 100644 index 0000000..101e0ba --- /dev/null +++ b/ref/client/EDecoder.java @@ -0,0 +1,2102 @@ +/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +import java.io.Closeable; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInput; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +class EDecoder implements ObjectInput { + // incoming msg id's + private static final int END_CONN = -1; + private static final int TICK_PRICE = 1; + private static final int TICK_SIZE = 2; + private static final int ORDER_STATUS = 3; + private static final int ERR_MSG = 4; + private static final int OPEN_ORDER = 5; + private static final int ACCT_VALUE = 6; + private static final int PORTFOLIO_VALUE = 7; + private static final int ACCT_UPDATE_TIME = 8; + private static final int NEXT_VALID_ID = 9; + private static final int CONTRACT_DATA = 10; + private static final int EXECUTION_DATA = 11; + private static final int MARKET_DEPTH = 12; + private static final int MARKET_DEPTH_L2 = 13; + private static final int NEWS_BULLETINS = 14; + private static final int MANAGED_ACCTS = 15; + private static final int RECEIVE_FA = 16; + private static final int HISTORICAL_DATA = 17; + private static final int BOND_CONTRACT_DATA = 18; + private static final int SCANNER_PARAMETERS = 19; + private static final int SCANNER_DATA = 20; + private static final int TICK_OPTION_COMPUTATION = 21; + private static final int TICK_GENERIC = 45; + private static final int TICK_STRING = 46; + private static final int TICK_EFP = 47; + private static final int CURRENT_TIME = 49; + private static final int REAL_TIME_BARS = 50; + private static final int FUNDAMENTAL_DATA = 51; + private static final int CONTRACT_DATA_END = 52; + private static final int OPEN_ORDER_END = 53; + private static final int ACCT_DOWNLOAD_END = 54; + private static final int EXECUTION_DATA_END = 55; + private static final int DELTA_NEUTRAL_VALIDATION = 56; + private static final int TICK_SNAPSHOT_END = 57; + private static final int MARKET_DATA_TYPE = 58; + private static final int COMMISSION_REPORT = 59; + private static final int POSITION = 61; + private static final int POSITION_END = 62; + private static final int ACCOUNT_SUMMARY = 63; + private static final int ACCOUNT_SUMMARY_END = 64; + private static final int VERIFY_MESSAGE_API = 65; + private static final int VERIFY_COMPLETED = 66; + private static final int DISPLAY_GROUP_LIST = 67; + private static final int DISPLAY_GROUP_UPDATED = 68; + private static final int VERIFY_AND_AUTH_MESSAGE_API = 69; + private static final int VERIFY_AND_AUTH_COMPLETED = 70; + private static final int POSITION_MULTI = 71; + private static final int POSITION_MULTI_END = 72; + private static final int ACCOUNT_UPDATE_MULTI = 73; + private static final int ACCOUNT_UPDATE_MULTI_END = 74; + private static final int SECURITY_DEFINITION_OPTION_PARAMETER = 75; + private static final int SECURITY_DEFINITION_OPTION_PARAMETER_END = 76; + private static final int SOFT_DOLLAR_TIERS = 77; + private static final int FAMILY_CODES = 78; + private static final int SYMBOL_SAMPLES = 79; + private static final int MKT_DEPTH_EXCHANGES = 80; + private static final int TICK_REQ_PARAMS = 81; + private static final int SMART_COMPONENTS = 82; + private static final int NEWS_ARTICLE = 83; + private static final int TICK_NEWS = 84; + private static final int NEWS_PROVIDERS = 85; + private static final int HISTORICAL_NEWS = 86; + private static final int HISTORICAL_NEWS_END = 87; + private static final int HEAD_TIMESTAMP = 88; + private static final int HISTOGRAM_DATA = 89; + private static final int HISTORICAL_DATA_UPDATE = 90; + private static final int REROUTE_MKT_DATA_REQ = 91; + private static final int REROUTE_MKT_DEPTH_REQ = 92; + private static final int MARKET_RULE = 93; + private static final int PNL = 94; + private static final int PNL_SINGLE = 95; + + static final int MAX_MSG_LENGTH = 0xffffff; + private static final int REDIRECT_MSG_ID = -1; + + private EClientMsgSink m_clientMsgSink; + private EWrapper m_EWrapper; + private int m_serverVersion; + private IMessageReader m_messageReader; + + public EDecoder(int serverVersion, EWrapper callback) { + this(serverVersion, callback, null); + } + + public EDecoder(int serverVersion, EWrapper callback, EClientMsgSink sink) { + m_clientMsgSink = sink; + m_serverVersion = serverVersion; + m_EWrapper = callback; + } + + private void processFirstMsg() throws IOException { + m_serverVersion = readInt(); + + // Handle redirect + if( m_serverVersion == REDIRECT_MSG_ID ) { + String newAddress = readStr(); + + m_serverVersion = 0; + + if (m_clientMsgSink != null) + m_clientMsgSink.redirect(newAddress); + + return; + } + + + if (m_serverVersion >= 20) { + // currently with Unified both server version and time sent in one + // message + String twsTime = readStr(); + + if (m_clientMsgSink != null) + m_clientMsgSink.serverVersion(m_serverVersion, twsTime); + } else { + if (m_clientMsgSink != null) + m_clientMsgSink.serverVersion(m_serverVersion, null); + } + + m_EWrapper.connectAck(); + } + + private boolean readMessageToInternalBuf(InputStream dis) { + m_messageReader = new PreV100MessageReader(dis); + return true; + } + + public int processMsg(EMessage msg) throws IOException { + if (!readMessageToInternalBuf(msg.getStream())) { + return 0; + } + + if (m_serverVersion == 0) { + processFirstMsg(); + + return m_messageReader.msgLength(); + } + + int msgId = readInt(); + + switch( msgId) { + case END_CONN: + return 0; + + case TICK_PRICE: + processTickPriceMsg(); + break; + + case TICK_SIZE: + processTickSizeMsg(); + break; + + case POSITION: + processPositionMsg(); + break; + + case POSITION_END: + processPositionEndMsg(); + break; + + case ACCOUNT_SUMMARY: + processAccountSummaryMsg(); + break; + + case ACCOUNT_SUMMARY_END: + processAccountSummaryEndMsg(); + break; + + case TICK_OPTION_COMPUTATION: + processTickOptionComputationMsg(); + break; + + case TICK_GENERIC: + processTickGenericMsg(); + break; + + case TICK_STRING: + processTickStringMsg(); + break; + + case TICK_EFP: + processTickEFPMsg(); + break; + + case ORDER_STATUS: + processOrderStatusMsg(); + break; + + case ACCT_VALUE: + processAcctValueMsg(); + break; + + case PORTFOLIO_VALUE: + processPortfolioValueMsg(); + + break; + + case ACCT_UPDATE_TIME: + processAcctUpdateTimeMsg(); + break; + + case ERR_MSG: + processErrMsgMsg(); + break; + + case OPEN_ORDER: + processOpenOrderMsg(); + break; + + case NEXT_VALID_ID: + processNextValidIdMsg(); + break; + + case SCANNER_DATA: + processScannerDataMsg(); + break; + + case CONTRACT_DATA: + processContractDataMsg(); + break; + + case BOND_CONTRACT_DATA: + processBondContractDataMsg(); + break; + + case EXECUTION_DATA: + processExecutionDataMsg(); + break; + + case MARKET_DEPTH: + processMarketDepthMsg(); + break; + + case MARKET_DEPTH_L2: + processMarketDepthL2Msg(); + break; + + case NEWS_BULLETINS: + processNewsBulletinsMsg(); + break; + + case MANAGED_ACCTS: + processManagedAcctsMsg(); + break; + + case RECEIVE_FA: + processReceiveFaMsg(); + break; + + case HISTORICAL_DATA: + processHistoricalDataMsg(); + break; + + case SCANNER_PARAMETERS: + processScannerParametersMsg(); + break; + + case CURRENT_TIME: + processCurrentTimeMsg(); + break; + + case REAL_TIME_BARS: + processRealTimeBarsMsg(); + break; + + case FUNDAMENTAL_DATA: + processFundamentalDataMsg(); + break; + + case CONTRACT_DATA_END: + processContractDataEndMsg(); + break; + + case OPEN_ORDER_END: + processOpenOrderEndMsg(); + break; + + case ACCT_DOWNLOAD_END: + processAcctDownloadEndMsg(); + break; + + case EXECUTION_DATA_END: + processExecutionDataEndMsg(); + break; + + case DELTA_NEUTRAL_VALIDATION: + processDeltaNeutralValidationMsg(); + break; + + case TICK_SNAPSHOT_END: + processTickSnapshotEndMsg(); + break; + + case MARKET_DATA_TYPE: + processMarketDataTypeMsg(); + break; + + case COMMISSION_REPORT: + processCommissionReportMsg(); + break; + + case VERIFY_MESSAGE_API: + processVerifyMessageApiMsg(); + break; + + case VERIFY_COMPLETED: + processVerifyCompletedMsg(); + break; + + case DISPLAY_GROUP_LIST: + processDisplayGroupListMsg(); + break; + + case DISPLAY_GROUP_UPDATED: + processDisplayGroupUpdatedMsg(); + break; + + case VERIFY_AND_AUTH_MESSAGE_API: + processVerifyAndAuthMessageMsg(); + break; + + case VERIFY_AND_AUTH_COMPLETED: + processVerifyAndAuthCompletedMsg(); + break; + + case POSITION_MULTI: + processPositionMultiMsg(); + break; + + case POSITION_MULTI_END: + processPositionMultiEndMsg(); + break; + + case ACCOUNT_UPDATE_MULTI: + processAccountUpdateMultiMsg(); + break; + + case ACCOUNT_UPDATE_MULTI_END: + processAccountUpdateMultiEndMsg(); + break; + + case SECURITY_DEFINITION_OPTION_PARAMETER: + processSecurityDefinitionOptionalParameterMsg(); + break; + + case SECURITY_DEFINITION_OPTION_PARAMETER_END: + processSecurityDefinitionOptionalParameterEndMsg(); + break; + + case SOFT_DOLLAR_TIERS: + processSoftDollarTiersMsg(); + break; + + case FAMILY_CODES: + processFamilyCodesMsg(); + break; + + case SMART_COMPONENTS: + processSmartComponentsMsg(); + break; + + case TICK_REQ_PARAMS: + processTickReqParamsMsg(); + break; + + case SYMBOL_SAMPLES: + processSymbolSamplesMsg(); + break; + + case MKT_DEPTH_EXCHANGES: + processMktDepthExchangesMsg(); + break; + + case HEAD_TIMESTAMP: + processHeadTimestampMsg(); + break; + + case TICK_NEWS: + processTickNewsMsg(); + break; + + case NEWS_PROVIDERS: + processNewsProvidersMsg(); + break; + + case NEWS_ARTICLE: + processNewsArticleMsg(); + break; + + case HISTORICAL_NEWS: + processHistoricalNewsMsg(); + break; + + case HISTORICAL_NEWS_END: + processHistoricalNewsEndMsg(); + break; + + case HISTOGRAM_DATA: + processHistogramDataMsg(); + break; + + case HISTORICAL_DATA_UPDATE: + processHistoricalDataUpdateMsg(); + break; + + case REROUTE_MKT_DATA_REQ: + processRerouteMktDataReq(); + break; + + case REROUTE_MKT_DEPTH_REQ: + processRerouteMktDepthReq(); + break; + + case MARKET_RULE: + processMarketRuleMsg(); + break; + + case PNL: + processPnLMsg(); + break; + + case PNL_SINGLE: + processPnLSingleMsg(); + break; + + default: { + m_EWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.UNKNOWN_ID.code(), EClientErrors.UNKNOWN_ID.msg()); + return 0; + } + } + + m_messageReader.close(); + return m_messageReader.msgLength(); + } + + private void processMarketRuleMsg() throws IOException { + int marketRuleId = readInt(); + + PriceIncrement[] priceIncrements; + int nPriceIncrements = readInt(); + if (nPriceIncrements > 0) { + priceIncrements = new PriceIncrement[nPriceIncrements]; + for (int i = 0; i < nPriceIncrements; i++){ + priceIncrements[i] = new PriceIncrement(readDouble(), readDouble()); + } + } else { + priceIncrements = new PriceIncrement[0]; + } + + m_EWrapper.marketRule(marketRuleId, priceIncrements); + } + + private void processRerouteMktDepthReq() throws IOException { + int reqId = readInt(); + int conId = readInt(); + String exchange = readStr(); + + m_EWrapper.rerouteMktDepthReq(reqId, conId, exchange); + } + + private void processRerouteMktDataReq() throws IOException { + int reqId = readInt(); + int conId = readInt(); + String exchange = readStr(); + + m_EWrapper.rerouteMktDataReq(reqId, conId, exchange); + } + + private void processHistoricalDataUpdateMsg() throws IOException { + int reqId = readInt(); + int barCount = readInt(); + String date = readStr(); + double open = readDouble(); + double close = readDouble(); + double high = readDouble(); + double low = readDouble(); + double WAP = readDouble(); + long volume = readLong(); + + m_EWrapper.historicalDataUpdate(reqId, new Bar(date, open, high, low, close, volume, barCount, WAP)); + } + + private void processPnLSingleMsg() throws IOException { + int reqId = readInt(); + int pos = readInt(); + double dailyPnL = readDouble(); + double unrealizedPnL = Double.MAX_VALUE; + + if (m_serverVersion >= EClient.MIN_SERVER_VER_UNREALIZED_PNL) { + unrealizedPnL = readDouble(); + } + + double value = readDouble(); + + + m_EWrapper.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, value); + } + + private void processPnLMsg() throws IOException { + int reqId = readInt(); + double dailyPnL = readDouble(); + double unrealizedPnL = Double.MAX_VALUE; + + if (m_serverVersion >= EClient.MIN_SERVER_VER_UNREALIZED_PNL) { + unrealizedPnL = readDouble(); + } + + m_EWrapper.pnl(reqId, dailyPnL, unrealizedPnL); + } + + private void processHistogramDataMsg() throws IOException { + int reqId = readInt(); + int n = readInt(); + List items = new ArrayList<>(n); + + for (int i = 0; i < n; i++) { + items.add(new HistogramEntry(readDouble(), readLong())); + } + + m_EWrapper.histogramData(reqId, items); + } + + private void processHistoricalNewsEndMsg() throws IOException { + int requestId = readInt(); + boolean hasMore = readBoolFromInt(); + + m_EWrapper.historicalNewsEnd(requestId, hasMore); + } + + private void processHistoricalNewsMsg() throws IOException { + int requestId = readInt(); + String time = readStr(); + String providerCode = readStr(); + String articleId = readStr(); + String headline = readStr(); + + m_EWrapper.historicalNews(requestId, time, providerCode, articleId, headline); + } + + private void processNewsArticleMsg() throws IOException { + int requestId = readInt(); + int articleType = readInt(); + String articleText = readStr(); + + m_EWrapper.newsArticle(requestId, articleType, articleText); + } + + private void processNewsProvidersMsg() throws IOException { + NewsProvider[] newsProviders = new NewsProvider[0]; + int nNewsProviders = readInt(); + + if (nNewsProviders > 0) { + newsProviders = new NewsProvider[nNewsProviders]; + + for (int i = 0; i < nNewsProviders; i++) + { + newsProviders[i] = new NewsProvider(readStr(), readStr()); + } + } + + m_EWrapper.newsProviders(newsProviders); + } + + private void processTickNewsMsg() throws IOException { + int tickerId = readInt(); + long timeStamp = readLong(); + String providerCode = readStr(); + String articleId = readStr(); + String headline = readStr(); + String extraData = readStr(); + + m_EWrapper.tickNews(tickerId, timeStamp, providerCode, articleId, headline, extraData); + } + + private void processHeadTimestampMsg() throws IOException { + int reqId = readInt(); + String headTimestamp = readStr(); + + m_EWrapper.headTimestamp(reqId, headTimestamp); + } + + private void processMktDepthExchangesMsg() throws IOException { + DepthMktDataDescription[] depthMktDataDescriptions = new DepthMktDataDescription[0]; + int nDepthMktDataDescriptions = readInt(); + + if (nDepthMktDataDescriptions > 0) { + depthMktDataDescriptions = new DepthMktDataDescription[nDepthMktDataDescriptions]; + + for (int i = 0; i < nDepthMktDataDescriptions; i++) + { + if (m_serverVersion >= EClient.MIN_SERVER_VER_SERVICE_DATA_TYPE) { + depthMktDataDescriptions[i] = new DepthMktDataDescription(readStr(), readStr(), readStr(), readStr(), readIntMax()); + } else { + depthMktDataDescriptions[i] = new DepthMktDataDescription(readStr(), readStr(), "", readBoolFromInt() ? "Deep2" : "Deep", Integer.MAX_VALUE); + } + } + } + + m_EWrapper.mktDepthExchanges(depthMktDataDescriptions); + } + + private void processSymbolSamplesMsg() throws IOException { + int reqId = readInt(); + ContractDescription[] contractDescriptions = new ContractDescription[0]; + int nContractDescriptions = readInt(); + + if (nContractDescriptions > 0){ + contractDescriptions = new ContractDescription[nContractDescriptions]; + + for (int i = 0; i < nContractDescriptions; i++) + { + // read contract fields + Contract contract = new Contract(); + contract.conid(readInt()); + contract.symbol(readStr()); + contract.secType(readStr()); + contract.primaryExch(readStr()); + contract.currency(readStr()); + + // read derivative sec types list + String[] derivativeSecTypes = new String[0]; + int nDerivativeSecTypes = readInt(); + + if (nDerivativeSecTypes > 0){ + derivativeSecTypes = new String[nDerivativeSecTypes]; + for (int j = 0; j < nDerivativeSecTypes; j++) + { + derivativeSecTypes[j] = readStr(); + } + } + + ContractDescription contractDescription = new ContractDescription(contract, derivativeSecTypes); + contractDescriptions[i] = contractDescription; + } + } + + m_EWrapper.symbolSamples(reqId, contractDescriptions); + } + + private void processFamilyCodesMsg() throws IOException { + FamilyCode[] familyCodes = new FamilyCode[0]; + int nFamilyCodes = readInt(); + + if (nFamilyCodes > 0) { + familyCodes = new FamilyCode[nFamilyCodes]; + + for (int i = 0; i < nFamilyCodes; i++) + { + familyCodes[i] = new FamilyCode(readStr(), readStr()); + } + } + + m_EWrapper.familyCodes(familyCodes); + } + + private void processSoftDollarTiersMsg() throws IOException { + int reqId = readInt(); + int nTiers = readInt(); + SoftDollarTier[] tiers = new SoftDollarTier[nTiers]; + + for (int i = 0; i < nTiers; i++) { + tiers[i] = new SoftDollarTier(readStr(), readStr(), readStr()); + } + + m_EWrapper.softDollarTiers(reqId, tiers); + } + + private void processSecurityDefinitionOptionalParameterEndMsg() throws IOException { + int reqId = readInt(); + + m_EWrapper.securityDefinitionOptionalParameterEnd(reqId); + } + + private void processSecurityDefinitionOptionalParameterMsg() throws IOException { + int reqId = readInt(); + String exchange = readStr(); + int underlyingConId = readInt(); + String tradingClass = readStr(); + String multiplier = readStr(); + int expirationsSize = readInt(); + Set expirations = new HashSet<>(); + Set strikes = new HashSet<>(); + + for (int i = 0; i < expirationsSize; i++) { + expirations.add(readStr()); + } + + int strikesSize = readInt(); + + for (int i = 0; i < strikesSize; i++) { + strikes.add(readDouble()); + } + + m_EWrapper.securityDefinitionOptionalParameter(reqId, exchange, underlyingConId, tradingClass, multiplier, expirations, strikes); + } + + private void processVerifyAndAuthCompletedMsg() throws IOException { + /*int version =*/ readInt(); + String isSuccessfulStr = readStr(); + boolean isSuccessful = "true".equals(isSuccessfulStr); + String errorText = readStr(); + + m_EWrapper.verifyAndAuthCompleted(isSuccessful, errorText); + } + + private void processVerifyAndAuthMessageMsg() throws IOException { + /*int version =*/ readInt(); + String apiData = readStr(); + String xyzChallenge = readStr(); + + m_EWrapper.verifyAndAuthMessageAPI(apiData, xyzChallenge); + } + + private void processDisplayGroupUpdatedMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + String contractInfo = readStr(); + + m_EWrapper.displayGroupUpdated(reqId, contractInfo); + } + + private void processDisplayGroupListMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + String groups = readStr(); + + m_EWrapper.displayGroupList(reqId, groups); + } + + private void processVerifyCompletedMsg() throws IOException { + /*int version =*/ readInt(); + String isSuccessfulStr = readStr(); + boolean isSuccessful = "true".equals(isSuccessfulStr); + String errorText = readStr(); + + m_EWrapper.verifyCompleted(isSuccessful, errorText); + } + + private void processVerifyMessageApiMsg() throws IOException { + /*int version =*/ readInt(); + String apiData = readStr(); + + m_EWrapper.verifyMessageAPI(apiData); + } + + private void processCommissionReportMsg() throws IOException { + /*int version =*/ readInt(); + + CommissionReport commissionReport = new CommissionReport(); + commissionReport.m_execId = readStr(); + commissionReport.m_commission = readDouble(); + commissionReport.m_currency = readStr(); + commissionReport.m_realizedPNL = readDouble(); + commissionReport.m_yield = readDouble(); + commissionReport.m_yieldRedemptionDate = readInt(); + + m_EWrapper.commissionReport( commissionReport); + } + + private void processMarketDataTypeMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + int marketDataType = readInt(); + + m_EWrapper.marketDataType( reqId, marketDataType); + } + + private void processTickSnapshotEndMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + + m_EWrapper.tickSnapshotEnd( reqId); + } + + private void processDeltaNeutralValidationMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + + DeltaNeutralContract underComp = new DeltaNeutralContract(readInt(), readDouble(), readDouble()); + m_EWrapper.deltaNeutralValidation( reqId, underComp); + } + + private void processExecutionDataEndMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + m_EWrapper.execDetailsEnd( reqId); + } + + private void processAcctDownloadEndMsg() throws IOException { + /*int version =*/ readInt(); + String accountName = readStr(); + m_EWrapper.accountDownloadEnd( accountName); + } + + private void processOpenOrderEndMsg() throws IOException { + /*int version =*/ readInt(); + m_EWrapper.openOrderEnd(); + } + + private void processContractDataEndMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + m_EWrapper.contractDetailsEnd(reqId); + } + + private void processFundamentalDataMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + String data = readStr(); + m_EWrapper.fundamentalData(reqId, data); + } + + private void processRealTimeBarsMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + long time = readLong(); + double open = readDouble(); + double high = readDouble(); + double low = readDouble(); + double close = readDouble(); + long volume = readLong(); + double wap = readDouble(); + int count = readInt(); + m_EWrapper.realtimeBar(reqId, time, open, high, low, close, volume, wap, count); + } + + private void processCurrentTimeMsg() throws IOException { + /*int version =*/ readInt(); + long time = readLong(); + m_EWrapper.currentTime(time); + } + + private void processScannerParametersMsg() throws IOException { + /*int version =*/ readInt(); + String xml = readStr(); + m_EWrapper.scannerParameters(xml); + } + + private void processHistoricalDataMsg() throws IOException { + int version = Integer.MAX_VALUE; + + if (m_serverVersion < EClient.MIN_SERVER_VER_SYNT_REALTIME_BARS) { + version = readInt(); + } + + int reqId = readInt(); + String startDateStr = ""; + String endDateStr = ""; + + if (version >= 2) { + startDateStr = readStr(); + endDateStr = readStr(); + } + int itemCount = readInt(); + for (int ctr = 0; ctr < itemCount; ctr++) { + String date = readStr(); + double open = readDouble(); + double high = readDouble(); + double low = readDouble(); + double close = readDouble(); + long volume = m_serverVersion < EClient.MIN_SERVER_VER_SYNT_REALTIME_BARS ? readInt() : readLong(); + double WAP = readDouble(); + + if (m_serverVersion < EClient.MIN_SERVER_VER_SYNT_REALTIME_BARS) { + /*String hasGaps = */readStr(); + } + + int barCount = -1; + + if (version >= 3) { + barCount = readInt(); + } + + m_EWrapper.historicalData(reqId, new Bar(date, open, high, low, close, volume, barCount, WAP)); + } + // send end of dataset marker + m_EWrapper.historicalDataEnd(reqId, startDateStr, endDateStr); + } + + private void processReceiveFaMsg() throws IOException { + /*int version =*/ readInt(); + int faDataType = readInt(); + String xml = readStr(); + + m_EWrapper.receiveFA(faDataType, xml); + } + + private void processManagedAcctsMsg() throws IOException { + /*int version =*/ readInt(); + String accountsList = readStr(); + + m_EWrapper.managedAccounts( accountsList); + } + + private void processNewsBulletinsMsg() throws IOException { + /*int version =*/ readInt(); + int newsMsgId = readInt(); + int newsMsgType = readInt(); + String newsMessage = readStr(); + String originatingExch = readStr(); + + m_EWrapper.updateNewsBulletin( newsMsgId, newsMsgType, newsMessage, originatingExch); + } + + private void processMarketDepthL2Msg() throws IOException { + /*int version =*/ readInt(); + int id = readInt(); + + int position = readInt(); + String marketMaker = readStr(); + int operation = readInt(); + int side = readInt(); + double price = readDouble(); + int size = readInt(); + + m_EWrapper.updateMktDepthL2(id, position, marketMaker, + operation, side, price, size); + } + + private void processMarketDepthMsg() throws IOException { + /*int version =*/ readInt(); + int id = readInt(); + + int position = readInt(); + int operation = readInt(); + int side = readInt(); + double price = readDouble(); + int size = readInt(); + + m_EWrapper.updateMktDepth(id, position, operation, + side, price, size); + } + + private void processExecutionDataMsg() throws IOException { + int version = readInt(); + + int reqId = -1; + if (version >= 7) { + reqId = readInt(); + } + + int orderId = readInt(); + + // read contract fields + Contract contract = new Contract(); + if (version >= 5) { + contract.conid(readInt()); + } + contract.symbol(readStr()); + contract.secType(readStr()); + contract.lastTradeDateOrContractMonth(readStr()); + contract.strike(readDouble()); + contract.right(readStr()); + if (version >= 9) { + contract.multiplier(readStr()); + } + contract.exchange(readStr()); + contract.currency(readStr()); + contract.localSymbol(readStr()); + if (version >= 10) { + contract.tradingClass(readStr()); + } + + Execution exec = new Execution(); + exec.orderId(orderId); + exec.execId(readStr()); + exec.time(readStr()); + exec.acctNumber(readStr()); + exec.exchange(readStr()); + exec.side(readStr()); + + if (m_serverVersion >= EClient.MIN_SERVER_VER_FRACTIONAL_POSITIONS) + exec.shares(readDouble()); + else + exec.shares(readInt()); + + exec.price(readDouble()); + if ( version >= 2 ) { + exec.permId(readInt()); + } + if ( version >= 3) { + exec.clientId(readInt()); + } + if ( version >= 4) { + exec.liquidation(readInt()); + } + if (version >= 6) { + exec.cumQty(readDouble()); + exec.avgPrice(readDouble()); + } + if (version >= 8) { + exec.orderRef(readStr()); + } + if (version >= 9) { + exec.evRule(readStr()); + exec.evMultiplier(readDouble()); + } + if (m_serverVersion >= EClient.MIN_SERVER_VER_MODELS_SUPPORT) { + exec.modelCode(readStr()); + } + + m_EWrapper.execDetails( reqId, contract, exec); + } + + private void processBondContractDataMsg() throws IOException { + int version = readInt(); + + int reqId = -1; + if (version >= 3) { + reqId = readInt(); + } + + ContractDetails contract = new ContractDetails(); + + contract.contract().symbol(readStr()); + contract.contract().secType(readStr()); + contract.cusip(readStr()); + contract.coupon(readDouble()); + contract.maturity(readStr()); + contract.issueDate(readStr()); + contract.ratings(readStr()); + contract.bondType(readStr()); + contract.couponType(readStr()); + contract.convertible(readBoolFromInt()); + contract.callable(readBoolFromInt()); + contract.putable(readBoolFromInt()); + contract.descAppend(readStr()); + contract.contract().exchange(readStr()); + contract.contract().currency(readStr()); + contract.marketName(readStr()); + contract.contract().tradingClass(readStr()); + contract.contract().conid(readInt()); + contract.minTick(readDouble()); + if (m_serverVersion >= EClient.MIN_SERVER_VER_MD_SIZE_MULTIPLIER) { + contract.mdSizeMultiplier(readInt()); + } + contract.orderTypes(readStr()); + contract.validExchanges(readStr()); + if (version >= 2) { + contract.nextOptionDate(readStr()); + contract.nextOptionType(readStr()); + contract.nextOptionPartial(readBoolFromInt()); + contract.notes(readStr()); + } + if( version >= 4) { + contract.longName(readStr()); + } + if ( version >= 6) { + contract.evRule(readStr()); + contract.evMultiplier(readDouble()); + } + if (version >= 5) { + int secIdListCount = readInt(); + if (secIdListCount > 0) { + contract.secIdList(new ArrayList<>(secIdListCount)); + for (int i = 0; i < secIdListCount; ++i) { + TagValue tagValue = new TagValue(); + tagValue.m_tag = readStr(); + tagValue.m_value = readStr(); + contract.secIdList().add(tagValue); + } + } + } + if (m_serverVersion >= EClient.MIN_SERVER_VER_AGG_GROUP) { + contract.aggGroup(readInt()); + } + if (m_serverVersion >= EClient.MIN_SERVER_VER_MARKET_RULES) { + contract.marketRuleIds(readStr()); + } + + m_EWrapper.bondContractDetails( reqId, contract); + } + + private void processContractDataMsg() throws IOException { + int version = readInt(); + + int reqId = -1; + if (version >= 3) { + reqId = readInt(); + } + + ContractDetails contract = new ContractDetails(); + contract.contract().symbol(readStr()); + contract.contract().secType(readStr()); + contract.contract().lastTradeDateOrContractMonth(readStr()); + contract.contract().strike(readDouble()); + contract.contract().right(readStr()); + contract.contract().exchange(readStr()); + contract.contract().currency(readStr()); + contract.contract().localSymbol(readStr()); + contract.marketName(readStr()); + contract.contract().tradingClass(readStr()); + contract.contract().conid(readInt()); + contract.minTick(readDouble()); + if (m_serverVersion >= EClient.MIN_SERVER_VER_MD_SIZE_MULTIPLIER) { + contract.mdSizeMultiplier(readInt()); + } + contract.contract().multiplier(readStr()); + contract.orderTypes(readStr()); + contract.validExchanges(readStr()); + if (version >= 2) { + contract.priceMagnifier(readInt()); + } + if (version >= 4) { + contract.underConid(readInt()); + } + if( version >= 5) { + contract.longName(readStr()); + contract.contract().primaryExch(readStr()); + } + if( version >= 6) { + contract.contractMonth(readStr()); + contract.industry(readStr()); + contract.category(readStr()); + contract.subcategory(readStr()); + contract.timeZoneId(readStr()); + contract.tradingHours(readStr()); + contract.liquidHours(readStr()); + } + if (version >= 8) { + contract.evRule(readStr()); + contract.evMultiplier(readDouble()); + } + if (version >= 7) { + int secIdListCount = readInt(); + if (secIdListCount > 0) { + contract.secIdList(new ArrayList<>(secIdListCount)); + for (int i = 0; i < secIdListCount; ++i) { + TagValue tagValue = new TagValue(); + tagValue.m_tag = readStr(); + tagValue.m_value = readStr(); + contract.secIdList().add(tagValue); + } + } + } + if (m_serverVersion >= EClient.MIN_SERVER_VER_AGG_GROUP) { + contract.aggGroup(readInt()); + } + if (m_serverVersion >= EClient.MIN_SERVER_VER_UNDERLYING_INFO) { + contract.underSymbol(readStr()); + contract.underSecType(readStr()); + } + if (m_serverVersion >= EClient.MIN_SERVER_VER_MARKET_RULES) { + contract.marketRuleIds(readStr()); + } + + m_EWrapper.contractDetails( reqId, contract); + } + + private void processScannerDataMsg() throws IOException { + int version = readInt(); + int tickerId = readInt(); + int numberOfElements = readInt(); + for (int ctr=0; ctr < numberOfElements; ctr++) { + int rank = readInt(); + ContractDetails contract = new ContractDetails(); + if (version >= 3) { + contract.contract().conid(readInt()); + } + contract.contract().symbol(readStr()); + contract.contract().secType(readStr()); + contract.contract().lastTradeDateOrContractMonth(readStr()); + contract.contract().strike(readDouble()); + contract.contract().right(readStr()); + contract.contract().exchange(readStr()); + contract.contract().currency(readStr()); + contract.contract().localSymbol(readStr()); + contract.marketName(readStr()); + contract.contract().tradingClass(readStr()); + String distance = readStr(); + String benchmark = readStr(); + String projection = readStr(); + String legsStr = null; + if (version >= 2) { + legsStr = readStr(); + } + m_EWrapper.scannerData(tickerId, rank, contract, distance, + benchmark, projection, legsStr); + } + m_EWrapper.scannerDataEnd(tickerId); + } + + private void processNextValidIdMsg() throws IOException { + /*int version =*/ readInt(); + int orderId = readInt(); + m_EWrapper.nextValidId( orderId); + } + + private void processOpenOrderMsg() throws IOException { + // read version + int version = readInt(); + + // read order id + Order order = new Order(); + order.orderId(readInt()); + + // read contract fields + Contract contract = new Contract(); + if (version >= 17) { + contract.conid(readInt()); + } + contract.symbol(readStr()); + contract.secType(readStr()); + contract.lastTradeDateOrContractMonth(readStr()); + contract.strike(readDouble()); + contract.right(readStr()); + if ( version >= 32) { + contract.multiplier(readStr()); + } + contract.exchange(readStr()); + contract.currency(readStr()); + if ( version >= 2 ) { + contract.localSymbol(readStr()); + } + if (version >= 32) { + contract.tradingClass(readStr()); + } + + // read order fields + order.action(readStr()); + + if (m_serverVersion >= EClient.MIN_SERVER_VER_FRACTIONAL_POSITIONS) + order.totalQuantity(readDouble()); + else + order.totalQuantity(readInt()); + + order.orderType(readStr()); + if (version < 29) { + order.lmtPrice(readDouble()); + } + else { + order.lmtPrice(readDoubleMax()); + } + if (version < 30) { + order.auxPrice(readDouble()); + } + else { + order.auxPrice(readDoubleMax()); + } + order.tif(readStr()); + order.ocaGroup(readStr()); + order.account(readStr()); + order.openClose(readStr()); + order.origin(readInt()); + order.orderRef(readStr()); + + if(version >= 3) { + order.clientId(readInt()); + } + + if( version >= 4 ) { + order.permId(readInt()); + if ( version < 18) { + // will never happen + /* order.m_ignoreRth = */ readBoolFromInt(); + } + else { + order.outsideRth(readBoolFromInt()); + } + order.hidden(readInt() == 1); + order.discretionaryAmt(readDouble()); + } + + if ( version >= 5 ) { + order.goodAfterTime(readStr()); + } + + if ( version >= 6 ) { + // skip deprecated sharesAllocation field + readStr(); + } + + if ( version >= 7 ) { + order.faGroup(readStr()); + order.faMethod(readStr()); + order.faPercentage(readStr()); + order.faProfile(readStr()); + } + + if ( m_serverVersion >= EClient.MIN_SERVER_VER_MODELS_SUPPORT) { + order.modelCode(readStr()); + } + + if ( version >= 8 ) { + order.goodTillDate(readStr()); + } + + if ( version >= 9) { + order.rule80A(readStr()); + order.percentOffset(readDoubleMax()); + order.settlingFirm(readStr()); + order.shortSaleSlot(readInt()); + order.designatedLocation(readStr()); + if ( m_serverVersion == 51){ + readInt(); // exemptCode + } + else if ( version >= 23){ + order.exemptCode(readInt()); + } + order.auctionStrategy(readInt()); + order.startingPrice(readDoubleMax()); + order.stockRefPrice(readDoubleMax()); + order.delta(readDoubleMax()); + order.stockRangeLower(readDoubleMax()); + order.stockRangeUpper(readDoubleMax()); + order.displaySize(readInt()); + if ( version < 18) { + // will never happen + /* order.m_rthOnly = */ readBoolFromInt(); + } + order.blockOrder(readBoolFromInt()); + order.sweepToFill(readBoolFromInt()); + order.allOrNone(readBoolFromInt()); + order.minQty(readIntMax()); + order.ocaType(readInt()); + order.eTradeOnly(readBoolFromInt()); + order.firmQuoteOnly(readBoolFromInt()); + order.nbboPriceCap(readDoubleMax()); + } + + if ( version >= 10) { + order.parentId(readInt()); + order.triggerMethod(readInt()); + } + + if (version >= 11) { + order.volatility(readDoubleMax()); + order.volatilityType(readInt()); + if (version == 11) { + int receivedInt = readInt(); + order.deltaNeutralOrderType( (receivedInt == 0) ? "NONE" : "MKT" ); + } else { // version 12 and up + order.deltaNeutralOrderType(readStr()); + order.deltaNeutralAuxPrice(readDoubleMax()); + + if (version >= 27 && !Util.StringIsEmpty(order.getDeltaNeutralOrderType())) { + order.deltaNeutralConId(readInt()); + order.deltaNeutralSettlingFirm(readStr()); + order.deltaNeutralClearingAccount(readStr()); + order.deltaNeutralClearingIntent(readStr()); + } + + if (version >= 31 && !Util.StringIsEmpty(order.getDeltaNeutralOrderType())) { + order.deltaNeutralOpenClose(readStr()); + order.deltaNeutralShortSale(readBoolFromInt()); + order.deltaNeutralShortSaleSlot(readInt()); + order.deltaNeutralDesignatedLocation(readStr()); + } + } + order.continuousUpdate(readInt()); + if (m_serverVersion == 26) { + order.stockRangeLower(readDouble()); + order.stockRangeUpper(readDouble()); + } + order.referencePriceType(readInt()); + } + + if (version >= 13) { + order.trailStopPrice(readDoubleMax()); + } + + if (version >= 30) { + order.trailingPercent(readDoubleMax()); + } + + if (version >= 14) { + order.basisPoints(readDoubleMax()); + order.basisPointsType(readIntMax()); + contract.comboLegsDescrip(readStr()); + } + + if (version >= 29) { + int comboLegsCount = readInt(); + if (comboLegsCount > 0) { + contract.comboLegs(new ArrayList<>(comboLegsCount)); + for (int i = 0; i < comboLegsCount; ++i) { + int conId = readInt(); + int ratio = readInt(); + String action = readStr(); + String exchange = readStr(); + int openClose = readInt(); + int shortSaleSlot = readInt(); + String designatedLocation = readStr(); + int exemptCode = readInt(); + + ComboLeg comboLeg = new ComboLeg(conId, ratio, action, exchange, openClose, + shortSaleSlot, designatedLocation, exemptCode); + contract.comboLegs().add(comboLeg); + } + } + + int orderComboLegsCount = readInt(); + if (orderComboLegsCount > 0) { + order.orderComboLegs(new ArrayList<>(orderComboLegsCount)); + for (int i = 0; i < orderComboLegsCount; ++i) { + double price = readDoubleMax(); + + OrderComboLeg orderComboLeg = new OrderComboLeg(price); + order.orderComboLegs().add(orderComboLeg); + } + } + } + + if (version >= 26) { + int smartComboRoutingParamsCount = readInt(); + if (smartComboRoutingParamsCount > 0) { + order.smartComboRoutingParams(new ArrayList<>(smartComboRoutingParamsCount)); + for (int i = 0; i < smartComboRoutingParamsCount; ++i) { + TagValue tagValue = new TagValue(); + tagValue.m_tag = readStr(); + tagValue.m_value = readStr(); + order.smartComboRoutingParams().add(tagValue); + } + } + } + + if (version >= 15) { + if (version >= 20) { + order.scaleInitLevelSize(readIntMax()); + order.scaleSubsLevelSize(readIntMax()); + } + else { + /* int notSuppScaleNumComponents = */ readIntMax(); + order.scaleInitLevelSize(readIntMax()); + } + order.scalePriceIncrement(readDoubleMax()); + } + + if (version >= 28 && order.scalePriceIncrement() > 0.0 && order.scalePriceIncrement() != Double.MAX_VALUE) { + order.scalePriceAdjustValue(readDoubleMax()); + order.scalePriceAdjustInterval(readIntMax()); + order.scaleProfitOffset(readDoubleMax()); + order.scaleAutoReset(readBoolFromInt()); + order.scaleInitPosition(readIntMax()); + order.scaleInitFillQty(readIntMax()); + order.scaleRandomPercent(readBoolFromInt()); + } + + if (version >= 24) { + order.hedgeType(readStr()); + if (!Util.StringIsEmpty(order.getHedgeType())) { + order.hedgeParam(readStr()); + } + } + + if (version >= 25) { + order.optOutSmartRouting(readBoolFromInt()); + } + + if (version >= 19) { + order.clearingAccount(readStr()); + order.clearingIntent(readStr()); + } + + if (version >= 22) { + order.notHeld(readBoolFromInt()); + } + + if (version >= 20) { + if (readBoolFromInt()) { + DeltaNeutralContract underComp = new DeltaNeutralContract(); + underComp.conid(readInt()); + underComp.delta(readDouble()); + underComp.price(readDouble()); + contract.underComp(underComp); + } + } + + if (version >= 21) { + order.algoStrategy(readStr()); + if (!Util.StringIsEmpty(order.getAlgoStrategy())) { + int algoParamsCount = readInt(); + if (algoParamsCount > 0) { + for (int i = 0; i < algoParamsCount; ++i) { + TagValue tagValue = new TagValue(); + tagValue.m_tag = readStr(); + tagValue.m_value = readStr(); + order.algoParams().add(tagValue); + } + } + } + } + + if (version >= 33) { + order.solicited(readBoolFromInt()); + } + + OrderState orderState = new OrderState(); + + if (version >= 16) { + order.whatIf(readBoolFromInt()); + + orderState.status(readStr()); + orderState.initMargin(readStr()); + orderState.maintMargin(readStr()); + orderState.equityWithLoan(readStr()); + orderState.commission(readDoubleMax()); + orderState.minCommission(readDoubleMax()); + orderState.maxCommission(readDoubleMax()); + orderState.commissionCurrency(readStr()); + orderState.warningText(readStr()); + } + + if (version >= 34) { + order.randomizeSize(readBoolFromInt()); + order.randomizePrice(readBoolFromInt()); + } + + if (m_serverVersion >= EClient.MIN_SERVER_VER_PEGGED_TO_BENCHMARK) { + if (order.orderType() == OrderType.PEG_BENCH) { + order.referenceContractId(readInt()); + order.isPeggedChangeAmountDecrease(readBoolFromInt()); + order.peggedChangeAmount(readDouble()); + order.referenceChangeAmount(readDouble()); + order.referenceExchangeId(readStr()); + } + + int nConditions = readInt(); + + if (nConditions > 0) { + for (int i = 0; i < nConditions; i++) { + OrderConditionType orderConditionType = OrderConditionType.fromInt(readInt()); + OrderCondition condition = OrderCondition.create(orderConditionType); + + condition.readFrom(this); + order.conditions().add(condition); + } + + order.conditionsIgnoreRth(readBoolFromInt()); + order.conditionsCancelOrder(readBoolFromInt()); + } + + order.adjustedOrderType(OrderType.get(readStr())); + order.triggerPrice(readDoubleMax()); + order.trailStopPrice(readDoubleMax()); + order.lmtPriceOffset(readDoubleMax()); + order.adjustedStopPrice(readDoubleMax()); + order.adjustedStopLimitPrice(readDoubleMax()); + order.adjustedTrailingAmount(readDoubleMax()); + order.adjustableTrailingUnit(readInt()); + } + + if (m_serverVersion >= EClient.MIN_SERVER_VER_SOFT_DOLLAR_TIER) { + order.softDollarTier(new SoftDollarTier(readStr(), readStr(), readStr())); + } + + if (m_serverVersion >= EClient.MIN_SERVER_VER_CASH_QTY) { + order.cashQty(readDoubleMax()); + } + + m_EWrapper.openOrder( order.orderId(), contract, order, orderState); + } + + private void processErrMsgMsg() throws IOException { + int version = readInt(); + if(version < 2) { + String msg = readStr(); + m_EWrapper.error( msg); + } else { + int id = readInt(); + int errorCode = readInt(); + String errorMsg = readStr(); + m_EWrapper.error(id, errorCode, errorMsg); + } + } + + private void processAcctUpdateTimeMsg() throws IOException { + /*int version =*/ readInt(); + String timeStamp = readStr(); + m_EWrapper.updateAccountTime(timeStamp); + } + + private void processPortfolioValueMsg() throws IOException { + int version = readInt(); + Contract contract = new Contract(); + if (version >= 6) { + contract.conid(readInt()); + } + contract.symbol(readStr()); + contract.secType(readStr()); + contract.lastTradeDateOrContractMonth(readStr()); + contract.strike(readDouble()); + contract.right(readStr()); + if (version >= 7) { + contract.multiplier(readStr()); + contract.primaryExch(readStr()); + } + contract.currency(readStr()); + if ( version >= 2 ) { + contract.localSymbol(readStr()); + } + if (version >= 8) { + contract.tradingClass(readStr()); + } + + double position = m_serverVersion >= EClient.MIN_SERVER_VER_FRACTIONAL_POSITIONS ? readDouble() : readInt(); + double marketPrice = readDouble(); + double marketValue = readDouble(); + double averageCost = 0.0; + double unrealizedPNL = 0.0; + double realizedPNL = 0.0; + if (version >=3 ) { + averageCost = readDouble(); + unrealizedPNL = readDouble(); + realizedPNL = readDouble(); + } + + String accountName = null ; + if( version >= 4) { + accountName = readStr(); + } + + if(version == 6 && m_serverVersion == 39) { + contract.primaryExch(readStr()); + } + + m_EWrapper.updatePortfolio(contract, position, marketPrice, marketValue, + averageCost, unrealizedPNL, realizedPNL, accountName); + } + + private void processAcctValueMsg() throws IOException { + int version = readInt(); + String key = readStr(); + String val = readStr(); + String cur = readStr(); + String accountName = null ; + if( version >= 2) { + accountName = readStr(); + } + m_EWrapper.updateAccountValue(key, val, cur, accountName); + } + + private void processOrderStatusMsg() throws IOException { + int version = readInt(); + int id = readInt(); + String status = readStr(); + double filled = m_serverVersion >= EClient.MIN_SERVER_VER_FRACTIONAL_POSITIONS ? readDouble() : readInt(); + double remaining = m_serverVersion >= EClient.MIN_SERVER_VER_FRACTIONAL_POSITIONS ? readDouble() : readInt(); + double avgFillPrice = readDouble(); + + int permId = 0; + if( version >= 2) { + permId = readInt(); + } + + int parentId = 0; + if( version >= 3) { + parentId = readInt(); + } + + double lastFillPrice = 0; + if( version >= 4) { + lastFillPrice = readDouble(); + } + + int clientId = 0; + if( version >= 5) { + clientId = readInt(); + } + + String whyHeld = null; + if( version >= 6) { + whyHeld = readStr(); + } + + m_EWrapper.orderStatus( id, status, filled, remaining, avgFillPrice, + permId, parentId, lastFillPrice, clientId, whyHeld); + } + + private void processTickEFPMsg() throws IOException { + /*int version =*/ readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double basisPoints = readDouble(); + String formattedBasisPoints = readStr(); + double impliedFuturesPrice = readDouble(); + int holdDays = readInt(); + String futureLastTradeDate = readStr(); + double dividendImpact = readDouble(); + double dividendsToLastTradeDate = readDouble(); + m_EWrapper.tickEFP( tickerId, tickType, basisPoints, formattedBasisPoints, + impliedFuturesPrice, holdDays, futureLastTradeDate, dividendImpact, dividendsToLastTradeDate); + } + + private void processTickStringMsg() throws IOException { + /*int version =*/ readInt(); + int tickerId = readInt(); + int tickType = readInt(); + String value = readStr(); + + m_EWrapper.tickString( tickerId, tickType, value); + } + + private void processTickGenericMsg() throws IOException { + /*int version =*/ readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double value = readDouble(); + + m_EWrapper.tickGeneric( tickerId, tickType, value); + } + + private void processTickOptionComputationMsg() throws IOException { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double impliedVol = readDouble(); + if (impliedVol < 0) { // -1 is the "not yet computed" indicator + impliedVol = Double.MAX_VALUE; + } + double delta = readDouble(); + if (Math.abs(delta) > 1) { // -2 is the "not yet computed" indicator + delta = Double.MAX_VALUE; + } + double optPrice = Double.MAX_VALUE; + double pvDividend = Double.MAX_VALUE; + double gamma = Double.MAX_VALUE; + double vega = Double.MAX_VALUE; + double theta = Double.MAX_VALUE; + double undPrice = Double.MAX_VALUE; + if (version >= 6 || tickType == TickType.MODEL_OPTION.index() + || tickType == TickType.DELAYED_MODEL_OPTION.index()) { // introduced in version == 5 + optPrice = readDouble(); + if (optPrice < 0) { // -1 is the "not yet computed" indicator + optPrice = Double.MAX_VALUE; + } + pvDividend = readDouble(); + if (pvDividend < 0) { // -1 is the "not yet computed" indicator + pvDividend = Double.MAX_VALUE; + } + } + if (version >= 6) { + gamma = readDouble(); + if (Math.abs(gamma) > 1) { // -2 is the "not yet computed" indicator + gamma = Double.MAX_VALUE; + } + vega = readDouble(); + if (Math.abs(vega) > 1) { // -2 is the "not yet computed" indicator + vega = Double.MAX_VALUE; + } + theta = readDouble(); + if (Math.abs(theta) > 1) { // -2 is the "not yet computed" indicator + theta = Double.MAX_VALUE; + } + undPrice = readDouble(); + if (undPrice < 0) { // -1 is the "not yet computed" indicator + undPrice = Double.MAX_VALUE; + } + } + + m_EWrapper.tickOptionComputation( tickerId, tickType, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice); + } + + private void processAccountSummaryEndMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + m_EWrapper.accountSummaryEnd(reqId); + } + + private void processAccountSummaryMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + String account = readStr(); + String tag = readStr(); + String value = readStr(); + String currency = readStr(); + m_EWrapper.accountSummary(reqId, account, tag, value, currency); + } + + private void processPositionEndMsg() throws IOException { + /*int version =*/ readInt(); + m_EWrapper.positionEnd(); + } + + private void processPositionMsg() throws IOException { + int version = readInt(); + String account = readStr(); + + Contract contract = new Contract(); + contract.conid(readInt()); + contract.symbol(readStr()); + contract.secType(readStr()); + contract.lastTradeDateOrContractMonth(readStr()); + contract.strike(readDouble()); + contract.right(readStr()); + contract.multiplier(readStr()); + contract.exchange(readStr()); + contract.currency(readStr()); + contract.localSymbol(readStr()); + if (version >= 2) { + contract.tradingClass(readStr()); + } + + double pos = m_serverVersion >= EClient.MIN_SERVER_VER_FRACTIONAL_POSITIONS ? readDouble() : readInt(); + double avgCost = 0; + if (version >= 3) { + avgCost = readDouble(); + } + + m_EWrapper.position( account, contract, pos, avgCost); + } + + private void processTickSizeMsg() throws IOException { + /*int version =*/ readInt(); + int tickerId = readInt(); + int tickType = readInt(); + int size = readInt(); + + m_EWrapper.tickSize( tickerId, tickType, size); + } + + private void processTickPriceMsg() throws IOException { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double price = readDouble(); + int size = 0; + TickAttr attribs = new TickAttr(); + + if( version >= 2) { + size = readInt(); + } + + if (version >= 3) { + int attrMask = readInt(); + + attribs.canAutoExecute(attrMask == 1); + + if (m_serverVersion >= EClient.MIN_SERVER_VER_PAST_LIMIT) { + BitMask mask = new BitMask(attrMask); + + attribs.canAutoExecute(mask.get(0)); + attribs.pastLimit(mask.get(1)); + } + } + + + m_EWrapper.tickPrice( tickerId, tickType, price, attribs); + + if( version >= 2) { + final int sizeTickType; + switch (tickType) { + case 1: // BID + sizeTickType = 0 ; // BID_SIZE + break ; + case 2: // ASK + sizeTickType = 3 ; // ASK_SIZE + break ; + case 4: // LAST + sizeTickType = 5 ; // LAST_SIZE + break ; + case 66: // DELAYED_BID + sizeTickType = 69 ; // DELAYED_BID_SIZE + break ; + case 67: // DELAYED_ASK + sizeTickType = 70 ; // DELAYED_ASK_SIZE + break ; + case 68: // DELAYED_LAST + sizeTickType = 71 ; // DELAYED_LAST_SIZE + break ; + default: + sizeTickType = -1; // not a tick + } + if (sizeTickType != -1) { + m_EWrapper.tickSize( tickerId, sizeTickType, size); + } + } + } + + private void processPositionMultiMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + String account = readStr(); + + Contract contract = new Contract(); + contract.conid(readInt()); + contract.symbol(readStr()); + contract.secType(readStr()); + contract.lastTradeDateOrContractMonth(readStr()); + contract.strike(readDouble()); + contract.right(readStr()); + contract.multiplier(readStr()); + contract.exchange(readStr()); + contract.currency(readStr()); + contract.localSymbol(readStr()); + contract.tradingClass(readStr()); + double pos = readDouble(); + double avgCost = readDouble(); + String modelCode = readStr(); + + m_EWrapper.positionMulti( reqId, account, modelCode, contract, pos, avgCost); + } + + private void processPositionMultiEndMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + + m_EWrapper.positionMultiEnd( reqId); + } + + private void processAccountUpdateMultiMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + String account = readStr(); + String modelCode = readStr(); + String key = readStr(); + String value = readStr(); + String currency = readStr(); + + m_EWrapper.accountUpdateMulti( reqId, account, modelCode, key, value, currency); + } + + private void processAccountUpdateMultiEndMsg() throws IOException { + /*int version =*/ readInt(); + int reqId = readInt(); + + m_EWrapper.accountUpdateMultiEnd( reqId); + } + + private void processSmartComponentsMsg() throws IOException { + int reqId = readInt(); + int n = readInt(); + Map> theMap = new HashMap<>(); + + for (int i = 0; i < n; i++) { + int bitNumber = readInt(); + String exchange = readStr(); + char exchangeLetter = readChar(); + + theMap.put(bitNumber, new SimpleEntry<>(exchange, exchangeLetter)); + } + + m_EWrapper.smartComponents(reqId, theMap); + } + + private void processTickReqParamsMsg() throws IOException { + int tickerId = readInt(); + double minTick = readDouble(); + String bboExchange = readStr(); + int snapshotPermissions = readInt(); + + m_EWrapper.tickReqParams(tickerId, minTick, bboExchange, snapshotPermissions); + } + + private String readStr() throws IOException { + return m_messageReader.readStr(); + } + + private boolean readBoolFromInt() throws IOException { + String str = readStr(); + return str != null && (Integer.parseInt(str) != 0); + } + + public int readInt() throws IOException { + String str = readStr(); + return str == null ? 0 : Integer.parseInt( str); + } + + private int readIntMax() throws IOException { + String str = readStr(); + return (str == null || str.length() == 0) ? Integer.MAX_VALUE + : Integer.parseInt( str); + } + + public long readLong() throws IOException { + String str = readStr(); + return str == null ? 0L : Long.parseLong(str); + } + + public double readDouble() throws IOException { + String str = readStr(); + return str == null ? 0 : Double.parseDouble( str); + } + + private double readDoubleMax() throws IOException { + String str = readStr(); + return (str == null || str.length() == 0) ? Double.MAX_VALUE + : Double.parseDouble( str); + } + + /** Message reader interface */ + private interface IMessageReader extends Closeable { + String readStr() throws IOException; + int msgLength(); + } + + private static class PreV100MessageReader implements IMessageReader { + private final InputStream m_din; + private int m_msgLength = 0; + + PreV100MessageReader( InputStream din ) { + m_din = din; + } + + @Override + public int msgLength() { + return m_msgLength; + } + + @Override public String readStr() throws IOException { + StringBuilder sb = new StringBuilder(); + + for(; true; m_msgLength++) { + int c = m_din.read(); + if( c <= 0) { + if ( c < 0 ) { + throw new EOFException(); + } + + m_msgLength++; + break; + } + sb.append( (char)c); + } + + String str = sb.toString(); + return str.length() == 0 ? null : str; + } + + @Override public void close() { + /* noop in pre-v100 */ + } + } + + @Override + public int skipBytes(int arg0) throws IOException { throw new UnsupportedOperationException(); } + + @Override + public int readUnsignedShort() throws IOException { throw new UnsupportedOperationException(); } + + @Override + public int readUnsignedByte() throws IOException { throw new UnsupportedOperationException(); } + + @Override + public String readUTF() throws IOException { return readStr(); } + + @Override + public short readShort() throws IOException { throw new UnsupportedOperationException(); } + + @Override + public String readLine() throws IOException { return readStr(); } + + @Override + public void readFully(byte[] arg0, int arg1, int arg2) throws IOException { throw new UnsupportedOperationException(); } + + @Override + public void readFully(byte[] arg0) throws IOException { throw new UnsupportedOperationException(); } + + @Override + public float readFloat() throws IOException { throw new UnsupportedOperationException(); } + + @Override + public char readChar() throws IOException { return readStr().charAt(0); } + + @Override + public byte readByte() throws IOException { throw new UnsupportedOperationException(); } + + @Override + public boolean readBoolean() throws IOException { return readBoolFromInt(); } + + @Override + public long skip(long arg0) throws IOException { throw new UnsupportedOperationException(); } + + @Override + public Object readObject() throws ClassNotFoundException, IOException { throw new UnsupportedOperationException(); } + + @Override + public int read(byte[] arg0, int arg1, int arg2) throws IOException { throw new UnsupportedOperationException(); } + + @Override + public int read(byte[] arg0) throws IOException { throw new UnsupportedOperationException(); } + + @Override + public int read() throws IOException { throw new UnsupportedOperationException(); } + + @Override + public void close() throws IOException { m_messageReader.close(); } + + @Override + public int available() throws IOException { throw new UnsupportedOperationException(); } + +} diff --git a/ref/client/EJavaSignal.java b/ref/client/EJavaSignal.java new file mode 100644 index 0000000..46d6518 --- /dev/null +++ b/ref/client/EJavaSignal.java @@ -0,0 +1,30 @@ +package com.ib.client; + + +public class EJavaSignal implements EReaderSignal { + private final Object monitor = new Object(); + private boolean open = false; + + @Override + public void issueSignal() { + synchronized (monitor) { + open = true; + monitor.notifyAll(); + } + } + + @Override + public void waitForSignal() { + synchronized (monitor) { + while (!open) { + try { + monitor.wait(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + } + open = false; + } + } +} diff --git a/ref/client/EMessage.java b/ref/client/EMessage.java new file mode 100644 index 0000000..e88e9e9 --- /dev/null +++ b/ref/client/EMessage.java @@ -0,0 +1,31 @@ +package com.ib.client; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class EMessage { + ByteArrayOutputStream m_buf; + + public EMessage(byte[] buf, int len) { + m_buf = new ByteArrayOutputStream(); + + m_buf.write(buf, 0, len); + } + + public EMessage(Builder buf) throws IOException { + m_buf = new ByteArrayOutputStream(); + + buf.writeTo(new DataOutputStream(m_buf)); + } + + public InputStream getStream() { + return new ByteArrayInputStream(m_buf.toByteArray()); + } + + public byte[] getRawData() { + return m_buf.toByteArray(); + } +} diff --git a/ref/client/EReader.java b/ref/client/EReader.java index bb2a877..5d66014 100644 --- a/ref/client/EReader.java +++ b/ref/client/EReader.java @@ -3,1174 +3,184 @@ package com.ib.client; -import java.io.DataInputStream; +import java.io.EOFException; import java.io.IOException; -import java.util.Vector; +import java.util.Arrays; +import java.util.Deque; +import java.util.LinkedList; -public class EReader extends Thread { - - // incoming msg id's - static final int TICK_PRICE = 1; - static final int TICK_SIZE = 2; - static final int ORDER_STATUS = 3; - static final int ERR_MSG = 4; - static final int OPEN_ORDER = 5; - static final int ACCT_VALUE = 6; - static final int PORTFOLIO_VALUE = 7; - static final int ACCT_UPDATE_TIME = 8; - static final int NEXT_VALID_ID = 9; - static final int CONTRACT_DATA = 10; - static final int EXECUTION_DATA = 11; - static final int MARKET_DEPTH = 12; - static final int MARKET_DEPTH_L2 = 13; - static final int NEWS_BULLETINS = 14; - static final int MANAGED_ACCTS = 15; - static final int RECEIVE_FA = 16; - static final int HISTORICAL_DATA = 17; - static final int BOND_CONTRACT_DATA = 18; - static final int SCANNER_PARAMETERS = 19; - static final int SCANNER_DATA = 20; - static final int TICK_OPTION_COMPUTATION = 21; - static final int TICK_GENERIC = 45; - static final int TICK_STRING = 46; - static final int TICK_EFP = 47; - static final int CURRENT_TIME = 49; - static final int REAL_TIME_BARS = 50; - static final int FUNDAMENTAL_DATA = 51; - static final int CONTRACT_DATA_END = 52; - static final int OPEN_ORDER_END = 53; - static final int ACCT_DOWNLOAD_END = 54; - static final int EXECUTION_DATA_END = 55; - static final int DELTA_NEUTRAL_VALIDATION = 56; - static final int TICK_SNAPSHOT_END = 57; - static final int MARKET_DATA_TYPE = 58; - static final int COMMISSION_REPORT = 59; - static final int POSITION = 61; - static final int POSITION_END = 62; - static final int ACCOUNT_SUMMARY = 63; - static final int ACCOUNT_SUMMARY_END = 64; - - private EClientSocket m_parent; - private DataInputStream m_dis; - protected EClientSocket parent() { return m_parent; } - private EWrapper eWrapper() { return (EWrapper)parent().wrapper(); } - public EReader( EClientSocket parent, DataInputStream dis) { - this("EReader", parent, dis); - } - - protected EReader( String name, EClientSocket parent, DataInputStream dis) { - setName( name); - m_parent = parent; - m_dis = dis; +/** + * This class reads commands from TWS and passes them to the user defined + * EWrapper. + * + * This class is initialized with a DataInputStream that is connected to the + * TWS. Messages begin with an ID and any relevant data are passed afterwards. + */ +public class EReader extends Thread { + private EClientSocket m_clientSocket; + private EReaderSignal m_signal; + private EDecoder m_processMsgsDecoder; + private static final EWrapper defaultWrapper = new DefaultEWrapper(); + private static final int IN_BUF_SIZE_DEFAULT = 8192; + private byte[] m_iBuf = new byte[IN_BUF_SIZE_DEFAULT]; + private int m_iBufLen = 0; + private final Deque m_msgQueue = new LinkedList<>(); + + protected boolean isUseV100Plus() { + return m_clientSocket.isUseV100Plus(); + } + + protected EClient parent() { return m_clientSocket; } + private EWrapper eWrapper() { return parent().wrapper(); } + + /** + * Construct the EReader. + * @param parent An EClientSocket connected to TWS. + * @param signal A callback that informs that there are messages in msg queue. + */ + public EReader(EClientSocket parent, EReaderSignal signal) { + m_clientSocket = parent; + m_signal = signal; + m_processMsgsDecoder = new EDecoder(parent.serverVersion(), parent.wrapper(), parent); } - + + /** + * Read and put messages to the msg queue until interrupted or TWS closes connection. + */ + @Override public void run() { try { // loop until thread is terminated - while( !isInterrupted() && processMsg(readInt())); - } - catch ( Exception ex ) { - if (parent().isConnected()) { - eWrapper().error( ex); - } - } - if (parent().isConnected()) { - m_parent.close(); - } - try { - m_dis.close(); - m_dis = null; - } - catch (IOException e) { - } - } - - /** Overridden in subclass. */ - protected boolean processMsg(int msgId) throws IOException{ - if( msgId == -1) return false; - - switch( msgId) { - case TICK_PRICE: { - int version = readInt(); - int tickerId = readInt(); - int tickType = readInt(); - double price = readDouble(); - int size = 0; - if( version >= 2) { - size = readInt(); - } - int canAutoExecute = 0; - if (version >= 3) { - canAutoExecute = readInt(); - } - eWrapper().tickPrice( tickerId, tickType, price, canAutoExecute); - - if( version >= 2) { - int sizeTickType = -1 ; // not a tick - switch (tickType) { - case 1: // BID - sizeTickType = 0 ; // BID_SIZE - break ; - case 2: // ASK - sizeTickType = 3 ; // ASK_SIZE - break ; - case 4: // LAST - sizeTickType = 5 ; // LAST_SIZE - break ; - } - if (sizeTickType != -1) { - eWrapper().tickSize( tickerId, sizeTickType, size); - } - } - break; - } - case TICK_SIZE: { - int version = readInt(); - int tickerId = readInt(); - int tickType = readInt(); - int size = readInt(); - - eWrapper().tickSize( tickerId, tickType, size); - break; - } - - case POSITION:{ - int version = readInt(); - String account = readStr(); - - Contract contract = new Contract(); - contract.m_conId = readInt(); - contract.m_symbol = readStr(); - contract.m_secType = readStr(); - contract.m_expiry = readStr(); - contract.m_strike = readDouble(); - contract.m_right = readStr(); - contract.m_multiplier = readStr(); - contract.m_exchange = readStr(); - contract.m_currency = readStr(); - contract.m_localSymbol = readStr(); - if (version >= 2) { - contract.m_tradingClass = readStr(); - } - - int pos = readInt(); - double avgCost = 0; - if (version >= 3) { - avgCost = readDouble(); - } - - eWrapper().position( account, contract, pos, avgCost); - break; - } - - case POSITION_END:{ - int version = readInt(); - eWrapper().positionEnd(); - break; - } - - case ACCOUNT_SUMMARY:{ - int version = readInt(); - int reqId = readInt(); - String account = readStr(); - String tag = readStr(); - String value = readStr(); - String currency = readStr(); - eWrapper().accountSummary(reqId, account, tag, value, currency); - break; - } - - case ACCOUNT_SUMMARY_END:{ - int version = readInt(); - int reqId = readInt(); - eWrapper().accountSummaryEnd(reqId); - break; - } - - case TICK_OPTION_COMPUTATION: { - int version = readInt(); - int tickerId = readInt(); - int tickType = readInt(); - double impliedVol = readDouble(); - if (impliedVol < 0) { // -1 is the "not yet computed" indicator - impliedVol = Double.MAX_VALUE; - } - double delta = readDouble(); - if (Math.abs(delta) > 1) { // -2 is the "not yet computed" indicator - delta = Double.MAX_VALUE; - } - double optPrice = Double.MAX_VALUE; - double pvDividend = Double.MAX_VALUE; - double gamma = Double.MAX_VALUE; - double vega = Double.MAX_VALUE; - double theta = Double.MAX_VALUE; - double undPrice = Double.MAX_VALUE; - if (version >= 6 || tickType == TickType.MODEL_OPTION) { // introduced in version == 5 - optPrice = readDouble(); - if (optPrice < 0) { // -1 is the "not yet computed" indicator - optPrice = Double.MAX_VALUE; - } - pvDividend = readDouble(); - if (pvDividend < 0) { // -1 is the "not yet computed" indicator - pvDividend = Double.MAX_VALUE; - } - } - if (version >= 6) { - gamma = readDouble(); - if (Math.abs(gamma) > 1) { // -2 is the "not yet computed" indicator - gamma = Double.MAX_VALUE; - } - vega = readDouble(); - if (Math.abs(vega) > 1) { // -2 is the "not yet computed" indicator - vega = Double.MAX_VALUE; - } - theta = readDouble(); - if (Math.abs(theta) > 1) { // -2 is the "not yet computed" indicator - theta = Double.MAX_VALUE; - } - undPrice = readDouble(); - if (undPrice < 0) { // -1 is the "not yet computed" indicator - undPrice = Double.MAX_VALUE; - } - } - - eWrapper().tickOptionComputation( tickerId, tickType, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice); - break; - } - - case TICK_GENERIC: { - int version = readInt(); - int tickerId = readInt(); - int tickType = readInt(); - double value = readDouble(); - - eWrapper().tickGeneric( tickerId, tickType, value); - break; - } - - case TICK_STRING: { - int version = readInt(); - int tickerId = readInt(); - int tickType = readInt(); - String value = readStr(); - - eWrapper().tickString( tickerId, tickType, value); - break; - } - - case TICK_EFP: { - int version = readInt(); - int tickerId = readInt(); - int tickType = readInt(); - double basisPoints = readDouble(); - String formattedBasisPoints = readStr(); - double impliedFuturesPrice = readDouble(); - int holdDays = readInt(); - String futureExpiry = readStr(); - double dividendImpact = readDouble(); - double dividendsToExpiry = readDouble(); - eWrapper().tickEFP( tickerId, tickType, basisPoints, formattedBasisPoints, - impliedFuturesPrice, holdDays, futureExpiry, dividendImpact, dividendsToExpiry); - break; - } - - case ORDER_STATUS: { - int version = readInt(); - int id = readInt(); - String status = readStr(); - int filled = readInt(); - int remaining = readInt(); - double avgFillPrice = readDouble(); - - int permId = 0; - if( version >= 2) { - permId = readInt(); - } - - int parentId = 0; - if( version >= 3) { - parentId = readInt(); - } - - double lastFillPrice = 0; - if( version >= 4) { - lastFillPrice = readDouble(); - } - - int clientId = 0; - if( version >= 5) { - clientId = readInt(); - } - - String whyHeld = null; - if( version >= 6) { - whyHeld = readStr(); - } - - eWrapper().orderStatus( id, status, filled, remaining, avgFillPrice, - permId, parentId, lastFillPrice, clientId, whyHeld); - break; - } - - case ACCT_VALUE: { - int version = readInt(); - String key = readStr(); - String val = readStr(); - String cur = readStr(); - String accountName = null ; - if( version >= 2) { - accountName = readStr(); - } - eWrapper().updateAccountValue(key, val, cur, accountName); - break; - } - - case PORTFOLIO_VALUE: { - int version = readInt(); - Contract contract = new Contract(); - if (version >= 6) { - contract.m_conId = readInt(); - } - contract.m_symbol = readStr(); - contract.m_secType = readStr(); - contract.m_expiry = readStr(); - contract.m_strike = readDouble(); - contract.m_right = readStr(); - if (version >= 7) { - contract.m_multiplier = readStr(); - contract.m_primaryExch = readStr(); - } - contract.m_currency = readStr(); - if ( version >= 2 ) { - contract.m_localSymbol = readStr(); - } - if (version >= 8) { - contract.m_tradingClass = readStr(); - } - - int position = readInt(); - double marketPrice = readDouble(); - double marketValue = readDouble(); - double averageCost = 0.0; - double unrealizedPNL = 0.0; - double realizedPNL = 0.0; - if (version >=3 ) { - averageCost = readDouble(); - unrealizedPNL = readDouble(); - realizedPNL = readDouble(); - } - - String accountName = null ; - if( version >= 4) { - accountName = readStr(); - } - - if(version == 6 && m_parent.serverVersion() == 39) { - contract.m_primaryExch = readStr(); - } - - eWrapper().updatePortfolio(contract, position, marketPrice, marketValue, - averageCost, unrealizedPNL, realizedPNL, accountName); - - break; - } - - case ACCT_UPDATE_TIME: { - int version = readInt(); - String timeStamp = readStr(); - eWrapper().updateAccountTime(timeStamp); - break; - } - - case ERR_MSG: { - int version = readInt(); - if(version < 2) { - String msg = readStr(); - m_parent.error( msg); - } else { - int id = readInt(); - int errorCode = readInt(); - String errorMsg = readStr(); - m_parent.error(id, errorCode, errorMsg); - } - break; - } - - case OPEN_ORDER: { - // read version - int version = readInt(); - - // read order id - Order order = new Order(); - order.m_orderId = readInt(); - - // read contract fields - Contract contract = new Contract(); - if (version >= 17) { - contract.m_conId = readInt(); - } - contract.m_symbol = readStr(); - contract.m_secType = readStr(); - contract.m_expiry = readStr(); - contract.m_strike = readDouble(); - contract.m_right = readStr(); - if ( version >= 32) { - contract.m_multiplier = readStr(); - } - contract.m_exchange = readStr(); - contract.m_currency = readStr(); - if ( version >= 2 ) { - contract.m_localSymbol = readStr(); - } - if (version >= 32) { - contract.m_tradingClass = readStr(); - } - - // read order fields - order.m_action = readStr(); - order.m_totalQuantity = readInt(); - order.m_orderType = readStr(); - if (version < 29) { - order.m_lmtPrice = readDouble(); - } - else { - order.m_lmtPrice = readDoubleMax(); - } - if (version < 30) { - order.m_auxPrice = readDouble(); - } - else { - order.m_auxPrice = readDoubleMax(); - } - order.m_tif = readStr(); - order.m_ocaGroup = readStr(); - order.m_account = readStr(); - order.m_openClose = readStr(); - order.m_origin = readInt(); - order.m_orderRef = readStr(); - - if(version >= 3) { - order.m_clientId = readInt(); - } - - if( version >= 4 ) { - order.m_permId = readInt(); - if ( version < 18) { - // will never happen - /* order.m_ignoreRth = */ readBoolFromInt(); - } - else { - order.m_outsideRth = readBoolFromInt(); - } - order.m_hidden = readInt() == 1; - order.m_discretionaryAmt = readDouble(); - } - - if ( version >= 5 ) { - order.m_goodAfterTime = readStr(); - } - - if ( version >= 6 ) { - // skip deprecated sharesAllocation field - readStr(); - } - - if ( version >= 7 ) { - order.m_faGroup = readStr(); - order.m_faMethod = readStr(); - order.m_faPercentage = readStr(); - order.m_faProfile = readStr(); - } - - if ( version >= 8 ) { - order.m_goodTillDate = readStr(); - } - - if ( version >= 9) { - order.m_rule80A = readStr(); - order.m_percentOffset = readDoubleMax(); - order.m_settlingFirm = readStr(); - order.m_shortSaleSlot = readInt(); - order.m_designatedLocation = readStr(); - if ( m_parent.serverVersion() == 51){ - readInt(); // exemptCode - } - else if ( version >= 23){ - order.m_exemptCode = readInt(); - } - order.m_auctionStrategy = readInt(); - order.m_startingPrice = readDoubleMax(); - order.m_stockRefPrice = readDoubleMax(); - order.m_delta = readDoubleMax(); - order.m_stockRangeLower = readDoubleMax(); - order.m_stockRangeUpper = readDoubleMax(); - order.m_displaySize = readInt(); - if ( version < 18) { - // will never happen - /* order.m_rthOnly = */ readBoolFromInt(); - } - order.m_blockOrder = readBoolFromInt(); - order.m_sweepToFill = readBoolFromInt(); - order.m_allOrNone = readBoolFromInt(); - order.m_minQty = readIntMax(); - order.m_ocaType = readInt(); - order.m_eTradeOnly = readBoolFromInt(); - order.m_firmQuoteOnly = readBoolFromInt(); - order.m_nbboPriceCap = readDoubleMax(); - } - - if ( version >= 10) { - order.m_parentId = readInt(); - order.m_triggerMethod = readInt(); - } - - if (version >= 11) { - order.m_volatility = readDoubleMax(); - order.m_volatilityType = readInt(); - if (version == 11) { - int receivedInt = readInt(); - order.m_deltaNeutralOrderType = ( (receivedInt == 0) ? "NONE" : "MKT" ); - } else { // version 12 and up - order.m_deltaNeutralOrderType = readStr(); - order.m_deltaNeutralAuxPrice = readDoubleMax(); - - if (version >= 27 && !Util.StringIsEmpty(order.m_deltaNeutralOrderType)) { - order.m_deltaNeutralConId = readInt(); - order.m_deltaNeutralSettlingFirm = readStr(); - order.m_deltaNeutralClearingAccount = readStr(); - order.m_deltaNeutralClearingIntent = readStr(); - } - - if (version >= 31 && !Util.StringIsEmpty(order.m_deltaNeutralOrderType)) { - order.m_deltaNeutralOpenClose = readStr(); - order.m_deltaNeutralShortSale = readBoolFromInt(); - order.m_deltaNeutralShortSaleSlot = readInt(); - order.m_deltaNeutralDesignatedLocation = readStr(); - } - } - order.m_continuousUpdate = readInt(); - if (m_parent.serverVersion() == 26) { - order.m_stockRangeLower = readDouble(); - order.m_stockRangeUpper = readDouble(); - } - order.m_referencePriceType = readInt(); - } - - if (version >= 13) { - order.m_trailStopPrice = readDoubleMax(); - } - - if (version >= 30) { - order.m_trailingPercent = readDoubleMax(); - } - - if (version >= 14) { - order.m_basisPoints = readDoubleMax(); - order.m_basisPointsType = readIntMax(); - contract.m_comboLegsDescrip = readStr(); - } - - if (version >= 29) { - int comboLegsCount = readInt(); - if (comboLegsCount > 0) { - contract.m_comboLegs = new Vector(comboLegsCount); - for (int i = 0; i < comboLegsCount; ++i) { - int conId = readInt(); - int ratio = readInt(); - String action = readStr(); - String exchange = readStr(); - int openClose = readInt(); - int shortSaleSlot = readInt(); - String designatedLocation = readStr(); - int exemptCode = readInt(); - - ComboLeg comboLeg = new ComboLeg(conId, ratio, action, exchange, openClose, - shortSaleSlot, designatedLocation, exemptCode); - contract.m_comboLegs.add(comboLeg); - } - } - - int orderComboLegsCount = readInt(); - if (orderComboLegsCount > 0) { - order.m_orderComboLegs = new Vector(orderComboLegsCount); - for (int i = 0; i < orderComboLegsCount; ++i) { - double price = readDoubleMax(); - - OrderComboLeg orderComboLeg = new OrderComboLeg(price); - order.m_orderComboLegs.add(orderComboLeg); - } - } - } - - if (version >= 26) { - int smartComboRoutingParamsCount = readInt(); - if (smartComboRoutingParamsCount > 0) { - order.m_smartComboRoutingParams = new Vector(smartComboRoutingParamsCount); - for (int i = 0; i < smartComboRoutingParamsCount; ++i) { - TagValue tagValue = new TagValue(); - tagValue.m_tag = readStr(); - tagValue.m_value = readStr(); - order.m_smartComboRoutingParams.add(tagValue); - } - } - } - - if (version >= 15) { - if (version >= 20) { - order.m_scaleInitLevelSize = readIntMax(); - order.m_scaleSubsLevelSize = readIntMax(); - } - else { - /* int notSuppScaleNumComponents = */ readIntMax(); - order.m_scaleInitLevelSize = readIntMax(); - } - order.m_scalePriceIncrement = readDoubleMax(); - } - - if (version >= 28 && order.m_scalePriceIncrement > 0.0 && order.m_scalePriceIncrement != Double.MAX_VALUE) { - order.m_scalePriceAdjustValue = readDoubleMax(); - order.m_scalePriceAdjustInterval = readIntMax(); - order.m_scaleProfitOffset = readDoubleMax(); - order.m_scaleAutoReset = readBoolFromInt(); - order.m_scaleInitPosition = readIntMax(); - order.m_scaleInitFillQty = readIntMax(); - order.m_scaleRandomPercent = readBoolFromInt(); - } - - if (version >= 24) { - order.m_hedgeType = readStr(); - if (!Util.StringIsEmpty(order.m_hedgeType)) { - order.m_hedgeParam = readStr(); - } - } - - if (version >= 25) { - order.m_optOutSmartRouting = readBoolFromInt(); - } - - if (version >= 19) { - order.m_clearingAccount = readStr(); - order.m_clearingIntent = readStr(); - } - - if (version >= 22) { - order.m_notHeld = readBoolFromInt(); - } - - if (version >= 20) { - if (readBoolFromInt()) { - UnderComp underComp = new UnderComp(); - underComp.m_conId = readInt(); - underComp.m_delta = readDouble(); - underComp.m_price = readDouble(); - contract.m_underComp = underComp; - } - } - - if (version >= 21) { - order.m_algoStrategy = readStr(); - if (!Util.StringIsEmpty(order.m_algoStrategy)) { - int algoParamsCount = readInt(); - if (algoParamsCount > 0) { - order.m_algoParams = new Vector(algoParamsCount); - for (int i = 0; i < algoParamsCount; ++i) { - TagValue tagValue = new TagValue(); - tagValue.m_tag = readStr(); - tagValue.m_value = readStr(); - order.m_algoParams.add(tagValue); - } - } - } - } - - OrderState orderState = new OrderState(); - - if (version >= 16) { - - order.m_whatIf = readBoolFromInt(); - - orderState.m_status = readStr(); - orderState.m_initMargin = readStr(); - orderState.m_maintMargin = readStr(); - orderState.m_equityWithLoan = readStr(); - orderState.m_commission = readDoubleMax(); - orderState.m_minCommission = readDoubleMax(); - orderState.m_maxCommission = readDoubleMax(); - orderState.m_commissionCurrency = readStr(); - orderState.m_warningText = readStr(); - } - - eWrapper().openOrder( order.m_orderId, contract, order, orderState); - break; - } - - case NEXT_VALID_ID: { - int version = readInt(); - int orderId = readInt(); - eWrapper().nextValidId( orderId); - break; - } - - case SCANNER_DATA: { - ContractDetails contract = new ContractDetails(); - int version = readInt(); - int tickerId = readInt(); - int numberOfElements = readInt(); - for (int ctr=0; ctr < numberOfElements; ctr++) { - int rank = readInt(); - if (version >= 3) { - contract.m_summary.m_conId = readInt(); - } - contract.m_summary.m_symbol = readStr(); - contract.m_summary.m_secType = readStr(); - contract.m_summary.m_expiry = readStr(); - contract.m_summary.m_strike = readDouble(); - contract.m_summary.m_right = readStr(); - contract.m_summary.m_exchange = readStr(); - contract.m_summary.m_currency = readStr(); - contract.m_summary.m_localSymbol = readStr(); - contract.m_marketName = readStr(); - contract.m_summary.m_tradingClass = readStr(); - String distance = readStr(); - String benchmark = readStr(); - String projection = readStr(); - String legsStr = null; - if (version >= 2) { - legsStr = readStr(); - } - eWrapper().scannerData(tickerId, rank, contract, distance, - benchmark, projection, legsStr); - } - eWrapper().scannerDataEnd(tickerId); - break; + while (!isInterrupted()) { + if (!putMessageToQueue()) + break; } - - case CONTRACT_DATA: { - int version = readInt(); - - int reqId = -1; - if (version >= 3) { - reqId = readInt(); - } - - ContractDetails contract = new ContractDetails(); - contract.m_summary.m_symbol = readStr(); - contract.m_summary.m_secType = readStr(); - contract.m_summary.m_expiry = readStr(); - contract.m_summary.m_strike = readDouble(); - contract.m_summary.m_right = readStr(); - contract.m_summary.m_exchange = readStr(); - contract.m_summary.m_currency = readStr(); - contract.m_summary.m_localSymbol = readStr(); - contract.m_marketName = readStr(); - contract.m_summary.m_tradingClass = readStr(); - contract.m_summary.m_conId = readInt(); - contract.m_minTick = readDouble(); - contract.m_summary.m_multiplier = readStr(); - contract.m_orderTypes = readStr(); - contract.m_validExchanges = readStr(); - if (version >= 2) { - contract.m_priceMagnifier = readInt(); - } - if (version >= 4) { - contract.m_underConId = readInt(); - } - if( version >= 5) { - contract.m_longName = readStr(); - contract.m_summary.m_primaryExch = readStr(); - } - if( version >= 6) { - contract.m_contractMonth = readStr(); - contract.m_industry = readStr(); - contract.m_category = readStr(); - contract.m_subcategory = readStr(); - contract.m_timeZoneId = readStr(); - contract.m_tradingHours = readStr(); - contract.m_liquidHours = readStr(); - } - if (version >= 8) { - contract.m_evRule = readStr(); - contract.m_evMultiplier = readDouble(); - } - if (version >= 7) { - int secIdListCount = readInt(); - if (secIdListCount > 0) { - contract.m_secIdList = new Vector(secIdListCount); - for (int i = 0; i < secIdListCount; ++i) { - TagValue tagValue = new TagValue(); - tagValue.m_tag = readStr(); - tagValue.m_value = readStr(); - contract.m_secIdList.add(tagValue); - } - } - } - - eWrapper().contractDetails( reqId, contract); - break; - } - case BOND_CONTRACT_DATA: { - int version = readInt(); - - int reqId = -1; - if (version >= 3) { - reqId = readInt(); - } - - ContractDetails contract = new ContractDetails(); - - contract.m_summary.m_symbol = readStr(); - contract.m_summary.m_secType = readStr(); - contract.m_cusip = readStr(); - contract.m_coupon = readDouble(); - contract.m_maturity = readStr(); - contract.m_issueDate = readStr(); - contract.m_ratings = readStr(); - contract.m_bondType = readStr(); - contract.m_couponType = readStr(); - contract.m_convertible = readBoolFromInt(); - contract.m_callable = readBoolFromInt(); - contract.m_putable = readBoolFromInt(); - contract.m_descAppend = readStr(); - contract.m_summary.m_exchange = readStr(); - contract.m_summary.m_currency = readStr(); - contract.m_marketName = readStr(); - contract.m_summary.m_tradingClass = readStr(); - contract.m_summary.m_conId = readInt(); - contract.m_minTick = readDouble(); - contract.m_orderTypes = readStr(); - contract.m_validExchanges = readStr(); - if (version >= 2) { - contract.m_nextOptionDate = readStr(); - contract.m_nextOptionType = readStr(); - contract.m_nextOptionPartial = readBoolFromInt(); - contract.m_notes = readStr(); - } - if( version >= 4) { - contract.m_longName = readStr(); - } - if ( version >= 6) { - contract.m_evRule = readStr(); - contract.m_evMultiplier = readDouble(); - } - if (version >= 5) { - int secIdListCount = readInt(); - if (secIdListCount > 0) { - contract.m_secIdList = new Vector(secIdListCount); - for (int i = 0; i < secIdListCount; ++i) { - TagValue tagValue = new TagValue(); - tagValue.m_tag = readStr(); - tagValue.m_value = readStr(); - contract.m_secIdList.add(tagValue); - } - } - } - - eWrapper().bondContractDetails( reqId, contract); - break; - } - case EXECUTION_DATA: { - int version = readInt(); - - int reqId = -1; - if (version >= 7) { - reqId = readInt(); - } - - int orderId = readInt(); - - // read contract fields - Contract contract = new Contract(); - if (version >= 5) { - contract.m_conId = readInt(); - } - contract.m_symbol = readStr(); - contract.m_secType = readStr(); - contract.m_expiry = readStr(); - contract.m_strike = readDouble(); - contract.m_right = readStr(); - if (version >= 9) { - contract.m_multiplier = readStr(); - } - contract.m_exchange = readStr(); - contract.m_currency = readStr(); - contract.m_localSymbol = readStr(); - if (version >= 10) { - contract.m_tradingClass = readStr(); - } - - Execution exec = new Execution(); - exec.m_orderId = orderId; - exec.m_execId = readStr(); - exec.m_time = readStr(); - exec.m_acctNumber = readStr(); - exec.m_exchange = readStr(); - exec.m_side = readStr(); - exec.m_shares = readInt(); - exec.m_price = readDouble(); - if ( version >= 2 ) { - exec.m_permId = readInt(); - } - if ( version >= 3) { - exec.m_clientId = readInt(); - } - if ( version >= 4) { - exec.m_liquidation = readInt(); - } - if (version >= 6) { - exec.m_cumQty = readInt(); - exec.m_avgPrice = readDouble(); - } - if (version >= 8) { - exec.m_orderRef = readStr(); - } - if (version >= 9) { - exec.m_evRule = readStr(); - exec.m_evMultiplier = readDouble(); - } - - eWrapper().execDetails( reqId, contract, exec); - break; - } - case MARKET_DEPTH: { - int version = readInt(); - int id = readInt(); - - int position = readInt(); - int operation = readInt(); - int side = readInt(); - double price = readDouble(); - int size = readInt(); - - eWrapper().updateMktDepth(id, position, operation, - side, price, size); - break; - } - case MARKET_DEPTH_L2: { - int version = readInt(); - int id = readInt(); - - int position = readInt(); - String marketMaker = readStr(); - int operation = readInt(); - int side = readInt(); - double price = readDouble(); - int size = readInt(); - - eWrapper().updateMktDepthL2(id, position, marketMaker, - operation, side, price, size); - break; - } - case NEWS_BULLETINS: { - int version = readInt(); - int newsMsgId = readInt(); - int newsMsgType = readInt(); - String newsMessage = readStr(); - String originatingExch = readStr(); - - eWrapper().updateNewsBulletin( newsMsgId, newsMsgType, newsMessage, originatingExch); - break; - } - case MANAGED_ACCTS: { - int version = readInt(); - String accountsList = readStr(); - - eWrapper().managedAccounts( accountsList); - break; - } - case RECEIVE_FA: { - int version = readInt(); - int faDataType = readInt(); - String xml = readStr(); - - eWrapper().receiveFA(faDataType, xml); - break; - } - case HISTORICAL_DATA: { - int version = readInt(); - int reqId = readInt(); - String startDateStr; - String endDateStr; - String completedIndicator = "finished"; - if (version >= 2) { - startDateStr = readStr(); - endDateStr = readStr(); - completedIndicator += "-" + startDateStr + "-" + endDateStr; - } - int itemCount = readInt(); - for (int ctr = 0; ctr < itemCount; ctr++) { - String date = readStr(); - double open = readDouble(); - double high = readDouble(); - double low = readDouble(); - double close = readDouble(); - int volume = readInt(); - double WAP = readDouble(); - String hasGaps = readStr(); - int barCount = -1; - if (version >= 3) { - barCount = readInt(); - } - eWrapper().historicalData(reqId, date, open, high, low, - close, volume, barCount, WAP, - Boolean.valueOf(hasGaps).booleanValue()); - } - // send end of dataset marker - eWrapper().historicalData(reqId, completedIndicator, -1, -1, -1, -1, -1, -1, -1, false); - break; - } - case SCANNER_PARAMETERS: { - int version = readInt(); - String xml = readStr(); - eWrapper().scannerParameters(xml); - break; - } - case CURRENT_TIME: { - /*int version =*/ readInt(); - long time = readLong(); - eWrapper().currentTime(time); - break; - } - case REAL_TIME_BARS: { - /*int version =*/ readInt(); - int reqId = readInt(); - long time = readLong(); - double open = readDouble(); - double high = readDouble(); - double low = readDouble(); - double close = readDouble(); - long volume = readLong(); - double wap = readDouble(); - int count = readInt(); - eWrapper().realtimeBar(reqId, time, open, high, low, close, volume, wap, count); - break; - } - case FUNDAMENTAL_DATA: { - /*int version =*/ readInt(); - int reqId = readInt(); - String data = readStr(); - eWrapper().fundamentalData(reqId, data); - break; - } - case CONTRACT_DATA_END: { - /*int version =*/ readInt(); - int reqId = readInt(); - eWrapper().contractDetailsEnd(reqId); - break; - } - case OPEN_ORDER_END: { - /*int version =*/ readInt(); - eWrapper().openOrderEnd(); - break; - } - case ACCT_DOWNLOAD_END: { - /*int version =*/ readInt(); - String accountName = readStr(); - eWrapper().accountDownloadEnd( accountName); - break; - } - case EXECUTION_DATA_END: { - /*int version =*/ readInt(); - int reqId = readInt(); - eWrapper().execDetailsEnd( reqId); - break; - } - case DELTA_NEUTRAL_VALIDATION: { - /*int version =*/ readInt(); - int reqId = readInt(); - - UnderComp underComp = new UnderComp(); - underComp.m_conId = readInt(); - underComp.m_delta = readDouble(); - underComp.m_price = readDouble(); - - eWrapper().deltaNeutralValidation( reqId, underComp); - break; - } - case TICK_SNAPSHOT_END: { - /*int version =*/ readInt(); - int reqId = readInt(); - - eWrapper().tickSnapshotEnd( reqId); - break; - } - case MARKET_DATA_TYPE: { - /*int version =*/ readInt(); - int reqId = readInt(); - int marketDataType = readInt(); - - eWrapper().marketDataType( reqId, marketDataType); - break; - } - case COMMISSION_REPORT: { - /*int version =*/ readInt(); - - CommissionReport commissionReport = new CommissionReport(); - commissionReport.m_execId = readStr(); - commissionReport.m_commission = readDouble(); - commissionReport.m_currency = readStr(); - commissionReport.m_realizedPNL = readDouble(); - commissionReport.m_yield = readDouble(); - commissionReport.m_yieldRedemptionDate = readInt(); - - eWrapper().commissionReport( commissionReport); - break; - } - - default: { - m_parent.error( EClientErrors.NO_VALID_ID, EClientErrors.UNKNOWN_ID.code(), EClientErrors.UNKNOWN_ID.msg()); - return false; - } - } - return true; - } - - - protected String readStr() throws IOException { - StringBuffer buf = new StringBuffer(); - while( true) { - byte c = m_dis.readByte(); - if( c == 0) { - break; - } - buf.append( (char)c); } - - String str = buf.toString(); - return str.length() == 0 ? null : str; - } - - - boolean readBoolFromInt() throws IOException { - String str = readStr(); - return str == null ? false : (Integer.parseInt( str) != 0); + catch ( Exception ex ) { + //if (parent().isConnected()) { + if( ex instanceof EOFException ) { + eWrapper().error(EClientErrors.NO_VALID_ID, EClientErrors.BAD_LENGTH.code(), + EClientErrors.BAD_LENGTH.msg() + " " + ex.getMessage()); + } + else { + eWrapper().error( ex); + } + //} + } + + m_signal.issueSignal(); } - protected int readInt() throws IOException { - String str = readStr(); - return str == null ? 0 : Integer.parseInt( str); + public boolean putMessageToQueue() throws IOException { + EMessage msg = readSingleMessage(); + + if (msg == null) + return false; + + synchronized(m_msgQueue) { + m_msgQueue.addFirst(msg); + } + + m_signal.issueSignal(); + + return true; + } + + protected EMessage getMsg() { + synchronized (m_msgQueue) { + return m_msgQueue.isEmpty() ? null : m_msgQueue.removeLast(); + } } + + static final int MAX_MSG_LENGTH = 0xffffff; - protected int readIntMax() throws IOException { - String str = readStr(); - return (str == null || str.length() == 0) ? Integer.MAX_VALUE - : Integer.parseInt( str); - } + private static class InvalidMessageLengthException extends IOException { + private static final long serialVersionUID = 1L; - protected long readLong() throws IOException { - String str = readStr(); - return str == null ? 0l : Long.parseLong(str); + InvalidMessageLengthException(String message) { + super(message); + } } - - protected double readDouble() throws IOException { - String str = readStr(); - return str == null ? 0 : Double.parseDouble( str); + + public void processMsgs() throws IOException { + EMessage msg = getMsg(); + + while (msg != null && m_processMsgsDecoder.processMsg(msg) > 0) { + msg = getMsg(); + } } - protected double readDoubleMax() throws IOException { - String str = readStr(); - return (str == null || str.length() == 0) ? Double.MAX_VALUE - : Double.parseDouble( str); - } + private EMessage readSingleMessage() throws IOException { + if (isUseV100Plus()) { + int msgSize = m_clientSocket.readInt(); + + if (msgSize > MAX_MSG_LENGTH) { + throw new InvalidMessageLengthException("message is too long: " + + msgSize); + } + + byte[] buf = new byte[msgSize]; + + int offset = 0; + + while (offset < msgSize) { + offset += m_clientSocket.read(buf, offset, msgSize - offset); + } + + return new EMessage(buf, buf.length); + } + + if (m_iBufLen == 0) { + m_iBufLen = appendIBuf(); + } + + int msgSize; + + while (true) + try { + msgSize = 0; + if (m_iBufLen > 0) { + try (EDecoder decoder = new EDecoder(m_clientSocket.serverVersion(), defaultWrapper)) { + msgSize = decoder.processMsg(new EMessage(m_iBuf, m_iBufLen)); + } + } + break; + } catch (IOException e) { + if (m_iBufLen >= m_iBuf.length * 3/4) { + byte[] tmp = new byte[m_iBuf.length * 2]; + + System.arraycopy(m_iBuf, 0, tmp, 0, m_iBuf.length); + + m_iBuf = tmp; + } + + m_iBufLen += appendIBuf(); + } + + if (msgSize == 0) + return null; + + + EMessage msg = new EMessage(m_iBuf, msgSize); + + System.arraycopy(Arrays.copyOfRange(m_iBuf, msgSize, m_iBuf.length), 0, m_iBuf, 0, m_iBuf.length - msgSize); + + m_iBufLen -= msgSize; + + if (m_iBufLen < IN_BUF_SIZE_DEFAULT && m_iBuf.length > IN_BUF_SIZE_DEFAULT) { + byte[] tmp = new byte[IN_BUF_SIZE_DEFAULT]; + + System.arraycopy(m_iBuf, 0, tmp, 0, tmp.length); + + m_iBuf = tmp; + } + + return msg; + } + + protected int appendIBuf() throws IOException { + return m_clientSocket.read(m_iBuf, m_iBufLen, m_iBuf.length - m_iBufLen); + } } diff --git a/ref/client/EReaderSignal.java b/ref/client/EReaderSignal.java new file mode 100644 index 0000000..a5733fd --- /dev/null +++ b/ref/client/EReaderSignal.java @@ -0,0 +1,6 @@ +package com.ib.client; + +public interface EReaderSignal { + void issueSignal(); + void waitForSignal(); +} diff --git a/ref/client/ESocket.java b/ref/client/ESocket.java new file mode 100644 index 0000000..8288de5 --- /dev/null +++ b/ref/client/ESocket.java @@ -0,0 +1,37 @@ +package com.ib.client; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +public class ESocket implements ETransport { + + protected DataOutputStream m_dos; // the socket output stream + + @Override + public void send(EMessage msg) throws IOException { + byte[] buf = msg.getRawData(); + + m_dos.write(buf, 0, buf.length); + } + + ESocket(Socket s) throws IOException { + m_dos = new DataOutputStream(s.getOutputStream()); + } + + // Sends String without length prefix (pre-V100 style) + protected void send(String str) throws IOException { + // Write string to data buffer + try (Builder b = new Builder(1024)) { + b.send(str); + b.writeTo(m_dos); + } + } + + @Override + public void close() throws IOException { + if (m_dos != null) { + m_dos.close(); + } + } +} diff --git a/ref/client/ETransport.java b/ref/client/ETransport.java new file mode 100644 index 0000000..39e3327 --- /dev/null +++ b/ref/client/ETransport.java @@ -0,0 +1,8 @@ +package com.ib.client; + +import java.io.Closeable; +import java.io.IOException; + +public interface ETransport extends Closeable { + void send(EMessage msg) throws IOException; +} diff --git a/ref/client/EWrapper.java b/ref/client/EWrapper.java index f74b548..43f55ba 100644 --- a/ref/client/EWrapper.java +++ b/ref/client/EWrapper.java @@ -3,12 +3,16 @@ package com.ib.client; -public interface EWrapper extends AnyWrapper { +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +public interface EWrapper { /////////////////////////////////////////////////////////////////////// // Interface methods /////////////////////////////////////////////////////////////////////// - void tickPrice( int tickerId, int field, double price, int canAutoExecute); + void tickPrice( int tickerId, int field, double price, TickAttr attrib); void tickSize( int tickerId, int field, int size); void tickOptionComputation( int tickerId, int field, double impliedVol, double delta, double optPrice, double pvDividend, @@ -17,14 +21,14 @@ void tickOptionComputation( int tickerId, int field, double impliedVol, void tickString(int tickerId, int tickType, String value); void tickEFP(int tickerId, int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, - String futureExpiry, double dividendImpact, double dividendsToExpiry); - void orderStatus( int orderId, String status, int filled, int remaining, + String futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate); + void orderStatus( int orderId, String status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld); void openOrder( int orderId, Contract contract, Order order, OrderState orderState); void openOrderEnd(); void updateAccountValue(String key, String value, String currency, String accountName); - void updatePortfolio(Contract contract, int position, double marketPrice, double marketValue, + void updatePortfolio(Contract contract, double position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, String accountName); void updateAccountTime(String timeStamp); void accountDownloadEnd(String accountName); @@ -40,8 +44,7 @@ void updateMktDepthL2( int tickerId, int position, String marketMaker, int opera void updateNewsBulletin( int msgId, int msgType, String message, String origExchange); void managedAccounts( String accountsList); void receiveFA(int faDataType, String xml); - void historicalData(int reqId, String date, double open, double high, double low, - double close, int volume, int count, double WAP, boolean hasGaps); + void historicalData(int reqId, Bar bar); void scannerParameters(String xml); void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, String benchmark, String projection, String legsStr); @@ -49,13 +52,50 @@ void scannerData(int reqId, int rank, ContractDetails contractDetails, String di void realtimeBar(int reqId, long time, double open, double high, double low, double close, long volume, double wap, int count); void currentTime(long time); void fundamentalData(int reqId, String data); - void deltaNeutralValidation(int reqId, UnderComp underComp); + void deltaNeutralValidation(int reqId, DeltaNeutralContract underComp); void tickSnapshotEnd(int reqId); void marketDataType(int reqId, int marketDataType); void commissionReport(CommissionReport commissionReport); - void position(String account, Contract contract, int pos, double avgCost); + void position(String account, Contract contract, double pos, double avgCost); void positionEnd(); void accountSummary(int reqId, String account, String tag, String value, String currency); void accountSummaryEnd(int reqId); + void verifyMessageAPI( String apiData); + void verifyCompleted( boolean isSuccessful, String errorText); + void verifyAndAuthMessageAPI( String apiData, String xyzChallenge); + void verifyAndAuthCompleted( boolean isSuccessful, String errorText); + void displayGroupList( int reqId, String groups); + void displayGroupUpdated( int reqId, String contractInfo); + void error( Exception e); + void error( String str); + void error(int id, int errorCode, String errorMsg); + void connectionClosed(); + void connectAck(); + void positionMulti( int reqId, String account, String modelCode, Contract contract, double pos, double avgCost); + void positionMultiEnd( int reqId); + void accountUpdateMulti( int reqId, String account, String modelCode, String key, String value, String currency); + void accountUpdateMultiEnd( int reqId); + void securityDefinitionOptionalParameter(int reqId, String exchange, int underlyingConId, String tradingClass, String multiplier, Set expirations, Set strikes); + void securityDefinitionOptionalParameterEnd(int reqId); + void softDollarTiers(int reqId, SoftDollarTier[] tiers); + void familyCodes(FamilyCode[] familyCodes); + void symbolSamples(int reqId, ContractDescription[] contractDescriptions); + void historicalDataEnd(int reqId, String startDateStr, String endDateStr); + void mktDepthExchanges(DepthMktDataDescription[] depthMktDataDescriptions); + void tickNews(int tickerId, long timeStamp, String providerCode, String articleId, String headline, String extraData); + void smartComponents(int reqId, Map> theMap); + void tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions); + void newsProviders(NewsProvider[] newsProviders); + void newsArticle(int requestId, int articleType, String articleText); + void historicalNews(int requestId, String time, String providerCode, String articleId, String headline); + void historicalNewsEnd(int requestId, boolean hasMore); + void headTimestamp(int reqId, String headTimestamp); + void histogramData(int reqId, List items); + void historicalDataUpdate(int reqId, Bar bar); + void rerouteMktDataReq(int reqId, int conId, String exchange); + void rerouteMktDepthReq(int reqId, int conId, String exchange); + void marketRule(int marketRuleId, PriceIncrement[] priceIncrements); + void pnl(int reqId, double dailyPnL, double unrealizedPnL); + void pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double value); } diff --git a/ref/client/EWrapperMsgGenerator.java b/ref/client/EWrapperMsgGenerator.java index d557b8e..9538ecf 100644 --- a/ref/client/EWrapperMsgGenerator.java +++ b/ref/client/EWrapperMsgGenerator.java @@ -4,56 +4,59 @@ package com.ib.client; import java.text.DateFormat; +import java.text.DecimalFormat; import java.util.Date; -import java.util.Vector; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; -public class EWrapperMsgGenerator extends AnyWrapperMsgGenerator { +public class EWrapperMsgGenerator { public static final String SCANNER_PARAMETERS = "SCANNER PARAMETERS:"; public static final String FINANCIAL_ADVISOR = "FA:"; - static public String tickPrice( int tickerId, int field, double price, int canAutoExecute) { + public static String tickPrice( int tickerId, int field, double price, TickAttr attribs) { return "id=" + tickerId + " " + TickType.getField( field) + "=" + price + " " + - ((canAutoExecute != 0) ? " canAutoExecute" : " noAutoExecute"); + (attribs.canAutoExecute() ? " canAutoExecute" : " noAutoExecute") + " pastLimit = " + attribs.pastLimit(); } - static public String tickSize( int tickerId, int field, int size) { + public static String tickSize( int tickerId, int field, int size) { return "id=" + tickerId + " " + TickType.getField( field) + "=" + size; } - static public String tickOptionComputation( int tickerId, int field, double impliedVol, + public static String tickOptionComputation( int tickerId, int field, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) { - String toAdd = "id=" + tickerId + " " + TickType.getField( field) + - ": vol = " + ((impliedVol >= 0 && impliedVol != Double.MAX_VALUE) ? Double.toString(impliedVol) : "N/A") + - " delta = " + ((Math.abs(delta) <= 1) ? Double.toString(delta) : "N/A") + - " gamma = " + ((Math.abs(gamma) <= 1) ? Double.toString(gamma) : "N/A") + - " vega = " + ((Math.abs(vega) <= 1) ? Double.toString(vega) : "N/A") + - " theta = " + ((Math.abs(theta) <= 1) ? Double.toString(theta) : "N/A") + - " optPrice = " + ((optPrice >= 0 && optPrice != Double.MAX_VALUE) ? Double.toString(optPrice) : "N/A") + - " pvDividend = " + ((pvDividend >= 0 && pvDividend != Double.MAX_VALUE) ? Double.toString(pvDividend) : "N/A") + - " undPrice = " + ((undPrice >= 0 && undPrice != Double.MAX_VALUE) ? Double.toString(undPrice) : "N/A"); - return toAdd; - } - - static public String tickGeneric(int tickerId, int tickType, double value) { + return "id=" + tickerId + " " + TickType.getField( field) + + ": vol = " + ((impliedVol >= 0 && impliedVol != Double.MAX_VALUE) ? Double.toString(impliedVol) : "N/A") + + " delta = " + ((Math.abs(delta) <= 1) ? Double.toString(delta) : "N/A") + + " gamma = " + ((Math.abs(gamma) <= 1) ? Double.toString(gamma) : "N/A") + + " vega = " + ((Math.abs(vega) <= 1) ? Double.toString(vega) : "N/A") + + " theta = " + ((Math.abs(theta) <= 1) ? Double.toString(theta) : "N/A") + + " optPrice = " + ((optPrice >= 0 && optPrice != Double.MAX_VALUE) ? Double.toString(optPrice) : "N/A") + + " pvDividend = " + ((pvDividend >= 0 && pvDividend != Double.MAX_VALUE) ? Double.toString(pvDividend) : "N/A") + + " undPrice = " + ((undPrice >= 0 && undPrice != Double.MAX_VALUE) ? Double.toString(undPrice) : "N/A"); + } + + public static String tickGeneric(int tickerId, int tickType, double value) { return "id=" + tickerId + " " + TickType.getField( tickType) + "=" + value; } - static public String tickString(int tickerId, int tickType, String value) { + public static String tickString(int tickerId, int tickType, String value) { return "id=" + tickerId + " " + TickType.getField( tickType) + "=" + value; } - static public String tickEFP(int tickerId, int tickType, double basisPoints, + public static String tickEFP(int tickerId, int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, - String futureExpiry, double dividendImpact, double dividendsToExpiry) { + String futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate) { return "id=" + tickerId + " " + TickType.getField(tickType) + ": basisPoints = " + basisPoints + "/" + formattedBasisPoints + " impliedFuture = " + impliedFuture + " holdDays = " + holdDays + - " futureExpiry = " + futureExpiry + " dividendImpact = " + dividendImpact + - " dividends to expiry = " + dividendsToExpiry; + " futureLastTradeDate = " + futureLastTradeDate + " dividendImpact = " + dividendImpact + + " dividends to expiry = " + dividendsToLastTradeDate; } - static public String orderStatus( int orderId, String status, int filled, int remaining, + public static String orderStatus( int orderId, String status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld) { return "order status: orderId=" + orderId + " clientId=" + clientId + " permId=" + permId + @@ -62,367 +65,367 @@ static public String orderStatus( int orderId, String status, int filled, int re " parent Id=" + parentId + " whyHeld=" + whyHeld; } - static public String openOrder( int orderId, Contract contract, Order order, OrderState orderState) { - String msg = "open order: orderId=" + orderId + - " action=" + order.m_action + - " quantity=" + order.m_totalQuantity + - " conid=" + contract.m_conId + - " symbol=" + contract.m_symbol + - " secType=" + contract.m_secType + - " expiry=" + contract.m_expiry + - " strike=" + contract.m_strike + - " right=" + contract.m_right + - " multiplier=" + contract.m_multiplier + - " exchange=" + contract.m_exchange + - " primaryExch=" + contract.m_primaryExch + - " currency=" + contract.m_currency + - " localSymbol=" + contract.m_localSymbol + - " tradingClass=" + contract.m_tradingClass + - " type=" + order.m_orderType + - " lmtPrice=" + Util.DoubleMaxString(order.m_lmtPrice) + - " auxPrice=" + Util.DoubleMaxString(order.m_auxPrice) + - " TIF=" + order.m_tif + - " localSymbol=" + contract.m_localSymbol + - " client Id=" + order.m_clientId + - " parent Id=" + order.m_parentId + - " permId=" + order.m_permId + - " outsideRth=" + order.m_outsideRth + - " hidden=" + order.m_hidden + - " discretionaryAmt=" + order.m_discretionaryAmt + - " displaySize=" + order.m_displaySize + - " triggerMethod=" + order.m_triggerMethod + - " goodAfterTime=" + order.m_goodAfterTime + - " goodTillDate=" + order.m_goodTillDate + - " faGroup=" + order.m_faGroup + - " faMethod=" + order.m_faMethod + - " faPercentage=" + order.m_faPercentage + - " faProfile=" + order.m_faProfile + - " shortSaleSlot=" + order.m_shortSaleSlot + - " designatedLocation=" + order.m_designatedLocation + - " exemptCode=" + order.m_exemptCode + - " ocaGroup=" + order.m_ocaGroup + - " ocaType=" + order.m_ocaType + - " rule80A=" + order.m_rule80A + - " allOrNone=" + order.m_allOrNone + - " minQty=" + Util.IntMaxString(order.m_minQty) + - " percentOffset=" + Util.DoubleMaxString(order.m_percentOffset) + - " eTradeOnly=" + order.m_eTradeOnly + - " firmQuoteOnly=" + order.m_firmQuoteOnly + - " nbboPriceCap=" + Util.DoubleMaxString(order.m_nbboPriceCap) + - " optOutSmartRouting=" + order.m_optOutSmartRouting + - " auctionStrategy=" + order.m_auctionStrategy + - " startingPrice=" + Util.DoubleMaxString(order.m_startingPrice) + - " stockRefPrice=" + Util.DoubleMaxString(order.m_stockRefPrice) + - " delta=" + Util.DoubleMaxString(order.m_delta) + - " stockRangeLower=" + Util.DoubleMaxString(order.m_stockRangeLower) + - " stockRangeUpper=" + Util.DoubleMaxString(order.m_stockRangeUpper) + - " volatility=" + Util.DoubleMaxString(order.m_volatility) + - " volatilityType=" + order.m_volatilityType + - " deltaNeutralOrderType=" + order.m_deltaNeutralOrderType + - " deltaNeutralAuxPrice=" + Util.DoubleMaxString(order.m_deltaNeutralAuxPrice) + - " deltaNeutralConId=" + order.m_deltaNeutralConId + - " deltaNeutralSettlingFirm=" + order.m_deltaNeutralSettlingFirm + - " deltaNeutralClearingAccount=" + order.m_deltaNeutralClearingAccount + - " deltaNeutralClearingIntent=" + order.m_deltaNeutralClearingIntent + - " deltaNeutralOpenClose=" + order.m_deltaNeutralOpenClose + - " deltaNeutralShortSale=" + order.m_deltaNeutralShortSale + - " deltaNeutralShortSaleSlot=" + order.m_deltaNeutralShortSaleSlot + - " deltaNeutralDesignatedLocation=" + order.m_deltaNeutralDesignatedLocation + - " continuousUpdate=" + order.m_continuousUpdate + - " referencePriceType=" + order.m_referencePriceType + - " trailStopPrice=" + Util.DoubleMaxString(order.m_trailStopPrice) + - " trailingPercent=" + Util.DoubleMaxString(order.m_trailingPercent) + - " scaleInitLevelSize=" + Util.IntMaxString(order.m_scaleInitLevelSize) + - " scaleSubsLevelSize=" + Util.IntMaxString(order.m_scaleSubsLevelSize) + - " scalePriceIncrement=" + Util.DoubleMaxString(order.m_scalePriceIncrement) + - " scalePriceAdjustValue=" + Util.DoubleMaxString(order.m_scalePriceAdjustValue) + - " scalePriceAdjustInterval=" + Util.IntMaxString(order.m_scalePriceAdjustInterval) + - " scaleProfitOffset=" + Util.DoubleMaxString(order.m_scaleProfitOffset) + - " scaleAutoReset=" + order.m_scaleAutoReset + - " scaleInitPosition=" + Util.IntMaxString(order.m_scaleInitPosition) + - " scaleInitFillQty=" + Util.IntMaxString(order.m_scaleInitFillQty) + - " scaleRandomPercent=" + order.m_scaleRandomPercent + - " hedgeType=" + order.m_hedgeType + - " hedgeParam=" + order.m_hedgeParam + - " account=" + order.m_account + - " settlingFirm=" + order.m_settlingFirm + - " clearingAccount=" + order.m_clearingAccount + - " clearingIntent=" + order.m_clearingIntent + - " notHeld=" + order.m_notHeld + - " whatIf=" + order.m_whatIf - ; - - if ("BAG".equals(contract.m_secType)) { - if (contract.m_comboLegsDescrip != null) { - msg += " comboLegsDescrip=" + contract.m_comboLegsDescrip; + public static String openOrder( int orderId, Contract contract, Order order, OrderState orderState) { + final StringBuilder sb = new StringBuilder(1024); + sb.append("open order: orderId=").append(orderId) + .append(" action=").append(order.getAction()) + .append(" quantity=").append(order.totalQuantity()) + .append(" cashQty=").append(Util.DoubleMaxString(order.cashQty())) + .append(" conid=").append(contract.conid()) + .append(" symbol=").append(contract.symbol()) + .append(" secType=").append(contract.getSecType()) + .append(" lastTradeDate=").append(contract.lastTradeDateOrContractMonth()) + .append(" strike=").append(contract.strike()) + .append(" right=").append(contract.getRight()) + .append(" multiplier=").append(contract.multiplier()) + .append(" exchange=").append(contract.exchange()) + .append(" primaryExch=").append(contract.primaryExch()) + .append(" currency=").append(contract.currency()) + .append(" localSymbol=").append(contract.localSymbol()) + .append(" tradingClass=").append(contract.tradingClass()) + .append(" type=").append(order.getOrderType()) + .append(" lmtPrice=").append(Util.DoubleMaxString(order.lmtPrice())) + .append(" auxPrice=").append(Util.DoubleMaxString(order.auxPrice())) + .append(" TIF=").append(order.getTif()) + .append(" localSymbol=").append(contract.localSymbol()) + .append(" client Id=").append(order.clientId()) + .append(" parent Id=").append(order.parentId()) + .append(" permId=").append(order.permId()) + .append(" outsideRth=").append(order.outsideRth()) + .append(" hidden=").append(order.hidden()) + .append(" discretionaryAmt=").append(order.discretionaryAmt()) + .append(" displaySize=").append(order.displaySize()) + .append(" triggerMethod=").append(order.getTriggerMethod()) + .append(" goodAfterTime=").append(order.goodAfterTime()) + .append(" goodTillDate=").append(order.goodTillDate()) + .append(" faGroup=").append(order.faGroup()) + .append(" faMethod=").append(order.getFaMethod()) + .append(" faPercentage=").append(order.faPercentage()) + .append(" faProfile=").append(order.faProfile()) + .append(" shortSaleSlot=").append(order.shortSaleSlot()) + .append(" designatedLocation=").append(order.designatedLocation()) + .append(" exemptCode=").append(order.exemptCode()) + .append(" ocaGroup=").append(order.ocaGroup()) + .append(" ocaType=").append(order.getOcaType()) + .append(" rule80A=").append(order.getRule80A()) + .append(" allOrNone=").append(order.allOrNone()) + .append(" minQty=").append(Util.IntMaxString(order.minQty())) + .append(" percentOffset=").append( Util.DoubleMaxString(order.percentOffset())) + .append(" eTradeOnly=").append(order.eTradeOnly()) + .append(" firmQuoteOnly=").append(order.firmQuoteOnly()) + .append(" nbboPriceCap=").append(Util.DoubleMaxString(order.nbboPriceCap())) + .append(" optOutSmartRouting=").append(order.optOutSmartRouting()) + .append(" auctionStrategy=").append(order.auctionStrategy()) + .append(" startingPrice=").append(Util.DoubleMaxString(order.startingPrice())) + .append(" stockRefPrice=").append(Util.DoubleMaxString(order.stockRefPrice())) + .append(" delta=").append(Util.DoubleMaxString(order.delta())) + .append(" stockRangeLower=").append(Util.DoubleMaxString(order.stockRangeLower())) + .append(" stockRangeUpper=").append( Util.DoubleMaxString(order.stockRangeUpper())) + .append(" volatility=").append(Util.DoubleMaxString(order.volatility())) + .append(" volatilityType=").append(order.getVolatilityType()) + .append(" deltaNeutralOrderType=").append(order.getDeltaNeutralOrderType()) + .append(" deltaNeutralAuxPrice=").append(Util.DoubleMaxString(order.deltaNeutralAuxPrice())) + .append(" deltaNeutralConId=").append(order.deltaNeutralConId()) + .append(" deltaNeutralSettlingFirm=").append(order.deltaNeutralSettlingFirm()) + .append(" deltaNeutralClearingAccount=").append(order.deltaNeutralClearingAccount()) + .append(" deltaNeutralClearingIntent=").append(order.deltaNeutralClearingIntent()) + .append(" deltaNeutralOpenClose=").append(order.deltaNeutralOpenClose()) + .append(" deltaNeutralShortSale=").append(order.deltaNeutralShortSale()) + .append(" deltaNeutralShortSaleSlot=").append(order.deltaNeutralShortSaleSlot()) + .append(" deltaNeutralDesignatedLocation=").append(order.deltaNeutralDesignatedLocation()) + .append(" continuousUpdate=").append(order.continuousUpdate()) + .append(" referencePriceType=").append(order.getReferencePriceType()) + .append(" trailStopPrice=").append(Util.DoubleMaxString(order.trailStopPrice())) + .append(" trailingPercent=").append(Util.DoubleMaxString(order.trailingPercent())) + .append(" scaleInitLevelSize=").append(Util.IntMaxString(order.scaleInitLevelSize())) + .append(" scaleSubsLevelSize=").append(Util.IntMaxString(order.scaleSubsLevelSize())) + .append(" scalePriceIncrement=").append(Util.DoubleMaxString(order.scalePriceIncrement())) + .append(" scalePriceAdjustValue=").append(Util.DoubleMaxString(order.scalePriceAdjustValue())) + .append(" scalePriceAdjustInterval=").append(Util.IntMaxString(order.scalePriceAdjustInterval())) + .append(" scaleProfitOffset=").append(Util.DoubleMaxString(order.scaleProfitOffset())) + .append(" scaleAutoReset=").append(order.scaleAutoReset()) + .append(" scaleInitPosition=").append(Util.IntMaxString(order.scaleInitPosition())) + .append(" scaleInitFillQty=").append(Util.IntMaxString(order.scaleInitFillQty())) + .append(" scaleRandomPercent=").append(order.scaleRandomPercent()) + .append(" hedgeType=").append(order.getHedgeType()) + .append(" hedgeParam=").append(order.hedgeParam()) + .append(" account=").append(order.account()) + .append(" modelCode=").append(order.modelCode()) + .append(" settlingFirm=").append(order.settlingFirm()) + .append(" clearingAccount=").append(order.clearingAccount()) + .append(" clearingIntent=").append(order.clearingIntent()) + .append(" notHeld=").append(order.notHeld()) + .append(" whatIf=").append(order.whatIf()) + .append(" solicited=").append(order.solicited()) + .append(" randomize size=").append(order.randomizeSize()) + .append(" randomize price=").append(order.randomizePrice()); + + + if ("BAG".equals(contract.getSecType())) { + if (contract.comboLegsDescrip() != null) { + sb.append(" comboLegsDescrip=").append(contract.comboLegsDescrip()); } - msg += " comboLegs={"; - if (contract.m_comboLegs != null) { - for (int i = 0; i < contract.m_comboLegs.size(); ++i) { - ComboLeg comboLeg = contract.m_comboLegs.get(i); - msg += " leg " + (i+1) + ": "; - msg += "conId=" + comboLeg.m_conId; - msg += " ratio=" + comboLeg.m_ratio; - msg += " action=" + comboLeg.m_action; - msg += " exchange=" + comboLeg.m_exchange; - msg += " openClose=" + comboLeg.m_openClose; - msg += " shortSaleSlot=" + comboLeg.m_shortSaleSlot; - msg += " designatedLocation=" + comboLeg.m_designatedLocation; - msg += " exemptCode=" + comboLeg.m_exemptCode; - if (order.m_orderComboLegs != null && contract.m_comboLegs.size() == order.m_orderComboLegs.size()) { - OrderComboLeg orderComboLeg = order.m_orderComboLegs.get(i); - msg += " price=" + Util.DoubleMaxString(orderComboLeg.m_price); + sb.append(" comboLegs={"); + if (contract.comboLegs() != null) { + for (int i = 0; i < contract.comboLegs().size(); ++i) { + ComboLeg comboLeg = contract.comboLegs().get(i); + sb.append(" leg ").append(i+1).append(": ") + .append("conId=").append(comboLeg.conid()) + .append(" ratio=").append(comboLeg.ratio()) + .append(" action=").append(comboLeg.getAction()) + .append(" exchange=").append(comboLeg.exchange()) + .append(" openClose=").append(comboLeg.getOpenClose()) + .append(" shortSaleSlot=").append(comboLeg.shortSaleSlot()) + .append(" designatedLocation=").append(comboLeg.designatedLocation()) + .append(" exemptCode=").append(comboLeg.exemptCode()); + if (order.orderComboLegs() != null && contract.comboLegs().size() == order.orderComboLegs().size()) { + OrderComboLeg orderComboLeg = order.orderComboLegs().get(i); + sb.append(" price=").append(Util.DoubleMaxString(orderComboLeg.price())); } - msg += ";"; + sb.append(';'); } } - msg += "}"; + sb.append('}'); - if (order.m_basisPoints != Double.MAX_VALUE) { - msg += " basisPoints=" + Util.DoubleMaxString(order.m_basisPoints); - msg += " basisPointsType=" + Util.IntMaxString(order.m_basisPointsType); + if (order.basisPoints() != Double.MAX_VALUE) { + sb.append(" basisPoints=").append(Util.DoubleMaxString(order.basisPoints())) + .append(" basisPointsType=").append(Util.IntMaxString(order.basisPointsType())); } } - if (contract.m_underComp != null) { - UnderComp underComp = contract.m_underComp; - msg += - " underComp.conId =" + underComp.m_conId + - " underComp.delta =" + underComp.m_delta + - " underComp.price =" + underComp.m_price ; + if (contract.underComp() != null) { + DeltaNeutralContract underComp = contract.underComp(); + sb.append(" underComp.conId=").append(underComp.conid()) + .append(" underComp.delta=").append(underComp.delta()) + .append(" underComp.price=").append(underComp.price()); } - if (!Util.StringIsEmpty(order.m_algoStrategy)) { - msg += " algoStrategy=" + order.m_algoStrategy; - msg += " algoParams={"; - if (order.m_algoParams != null) { - Vector algoParams = order.m_algoParams; - for (int i = 0; i < algoParams.size(); ++i) { - TagValue param = (TagValue)algoParams.elementAt(i); - if (i > 0) { - msg += ","; - } - msg += param.m_tag + "=" + param.m_value; - } + if (!Util.StringIsEmpty(order.getAlgoStrategy())) { + sb.append(" algoStrategy=").append(order.getAlgoStrategy()).append(" algoParams={"); + if (order.algoParams() != null) { + for (TagValue param : order.algoParams()) { + sb.append(param.m_tag).append('=').append(param.m_value).append(','); + } + if (!order.algoParams().isEmpty()) { + sb.setLength(sb.length() - 1); + } } - msg += "}"; + sb.append('}'); } - if ("BAG".equals(contract.m_secType)) { - msg += " smartComboRoutingParams={"; - if (order.m_smartComboRoutingParams != null) { - Vector smartComboRoutingParams = order.m_smartComboRoutingParams; - for (int i = 0; i < smartComboRoutingParams.size(); ++i) { - TagValue param = (TagValue)smartComboRoutingParams.elementAt(i); - if (i > 0) { - msg += ","; - } - msg += param.m_tag + "=" + param.m_value; - } + if ("BAG".equals(contract.getSecType())) { + sb.append(" smartComboRoutingParams={"); + if (order.smartComboRoutingParams() != null) { + for (TagValue param : order.smartComboRoutingParams()) { + sb.append(param.m_tag).append('=').append(param.m_value).append(','); + } + if (!order.smartComboRoutingParams().isEmpty()) { + sb.setLength(sb.length() - 1); + } } - msg += "}"; + sb.append('}'); } - String orderStateMsg = - " status=" + orderState.m_status - + " initMargin=" + orderState.m_initMargin - + " maintMargin=" + orderState.m_maintMargin - + " equityWithLoan=" + orderState.m_equityWithLoan - + " commission=" + Util.DoubleMaxString(orderState.m_commission) - + " minCommission=" + Util.DoubleMaxString(orderState.m_minCommission) - + " maxCommission=" + Util.DoubleMaxString(orderState.m_maxCommission) - + " commissionCurrency=" + orderState.m_commissionCurrency - + " warningText=" + orderState.m_warningText - ; + sb.append(" status=").append(orderState.getStatus()) + .append(" initMargin=").append(orderState.initMargin()) + .append(" maintMargin=").append(orderState.maintMargin()) + .append(" equityWithLoan=").append(orderState.equityWithLoan()) + .append(" commission=").append(Util.DoubleMaxString(orderState.commission())) + .append(" minCommission=").append(Util.DoubleMaxString(orderState.minCommission())) + .append(" maxCommission=").append(Util.DoubleMaxString(orderState.maxCommission())) + .append(" commissionCurrency=").append(orderState.commissionCurrency()) + .append(" warningText=").append(orderState.warningText()); - return msg + orderStateMsg; + return sb.toString(); } - static public String openOrderEnd() { + public static String openOrderEnd() { return " =============== end ==============="; } - static public String updateAccountValue(String key, String value, String currency, String accountName) { + public static String updateAccountValue(String key, String value, String currency, String accountName) { return "updateAccountValue: " + key + " " + value + " " + currency + " " + accountName; } - static public String updatePortfolio(Contract contract, int position, double marketPrice, + public static String updatePortfolio(Contract contract, double position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, String accountName) { - String msg = "updatePortfolio: " - + contractMsg(contract) - + position + " " + marketPrice + " " + marketValue + " " + averageCost + " " + unrealizedPNL + " " + realizedPNL + " " + accountName; - return msg; + return "updatePortfolio: " + + contractMsg(contract) + + position + " " + marketPrice + " " + marketValue + " " + averageCost + " " + unrealizedPNL + " " + realizedPNL + " " + accountName; } - static public String updateAccountTime(String timeStamp) { + public static String updateAccountTime(String timeStamp) { return "updateAccountTime: " + timeStamp; } - static public String accountDownloadEnd(String accountName) { + public static String accountDownloadEnd(String accountName) { return "accountDownloadEnd: " + accountName; } - static public String nextValidId( int orderId) { + public static String nextValidId( int orderId) { return "Next Valid Order ID: " + orderId; } - static public String contractDetails(int reqId, ContractDetails contractDetails) { - Contract contract = contractDetails.m_summary; - String msg = "reqId = " + reqId + " ===================================\n" - + " ---- Contract Details begin ----\n" - + contractMsg(contract) + contractDetailsMsg(contractDetails) - + " ---- Contract Details End ----\n"; - return msg; + public static String contractDetails(int reqId, ContractDetails contractDetails) { + Contract contract = contractDetails.contract(); + return "reqId = " + reqId + " ===================================\n" + + " ---- Contract Details begin ----\n" + + contractMsg(contract) + contractDetailsMsg(contractDetails) + + " ---- Contract Details End ----\n"; } private static String contractDetailsMsg(ContractDetails contractDetails) { - String msg = "marketName = " + contractDetails.m_marketName + "\n" - + "minTick = " + contractDetails.m_minTick + "\n" - + "price magnifier = " + contractDetails.m_priceMagnifier + "\n" - + "orderTypes = " + contractDetails.m_orderTypes + "\n" - + "validExchanges = " + contractDetails.m_validExchanges + "\n" - + "underConId = " + contractDetails.m_underConId + "\n" - + "longName = " + contractDetails.m_longName + "\n" - + "contractMonth = " + contractDetails.m_contractMonth + "\n" - + "industry = " + contractDetails.m_industry + "\n" - + "category = " + contractDetails.m_category + "\n" - + "subcategory = " + contractDetails.m_subcategory + "\n" - + "timeZoneId = " + contractDetails.m_timeZoneId + "\n" - + "tradingHours = " + contractDetails.m_tradingHours + "\n" - + "liquidHours = " + contractDetails.m_liquidHours + "\n" - + "evRule = " + contractDetails.m_evRule + "\n" - + "evMultiplier = " + contractDetails.m_evMultiplier + "\n" + return "marketName = " + contractDetails.marketName() + "\n" + + "minTick = " + contractDetails.minTick() + "\n" + + "price magnifier = " + contractDetails.priceMagnifier() + "\n" + + "orderTypes = " + contractDetails.orderTypes() + "\n" + + "validExchanges = " + contractDetails.validExchanges() + "\n" + + "underConId = " + contractDetails.underConid() + "\n" + + "longName = " + contractDetails.longName() + "\n" + + "contractMonth = " + contractDetails.contractMonth() + "\n" + + "industry = " + contractDetails.industry() + "\n" + + "category = " + contractDetails.category() + "\n" + + "subcategory = " + contractDetails.subcategory() + "\n" + + "timeZoneId = " + contractDetails.timeZoneId() + "\n" + + "tradingHours = " + contractDetails.tradingHours() + "\n" + + "liquidHours = " + contractDetails.liquidHours() + "\n" + + "evRule = " + contractDetails.evRule() + "\n" + + "evMultiplier = " + contractDetails.evMultiplier() + "\n" + + "mdSizeMultiplier = " + contractDetails.mdSizeMultiplier() + "\n" + + "aggGroup = " + contractDetails.aggGroup() + "\n" + + "underSymbol = " + contractDetails.underSymbol() + "\n" + + "underSecType = " + contractDetails.underSecType() + "\n" + + "marketRuleIds = " + contractDetails.marketRuleIds() + "\n" + contractDetailsSecIdList(contractDetails); - return msg; - } - - static public String contractMsg(Contract contract) { - String msg = "conid = " + contract.m_conId + "\n" - + "symbol = " + contract.m_symbol + "\n" - + "secType = " + contract.m_secType + "\n" - + "expiry = " + contract.m_expiry + "\n" - + "strike = " + contract.m_strike + "\n" - + "right = " + contract.m_right + "\n" - + "multiplier = " + contract.m_multiplier + "\n" - + "exchange = " + contract.m_exchange + "\n" - + "primaryExch = " + contract.m_primaryExch + "\n" - + "currency = " + contract.m_currency + "\n" - + "localSymbol = " + contract.m_localSymbol + "\n" - + "tradingClass = " + contract.m_tradingClass + "\n"; - return msg; + } + + private static String contractMsg(Contract contract) { + return "conid = " + contract.conid() + "\n" + + "symbol = " + contract.symbol() + "\n" + + "secType = " + contract.getSecType() + "\n" + + "lastTradeDate = " + contract.lastTradeDateOrContractMonth() + "\n" + + "strike = " + contract.strike() + "\n" + + "right = " + contract.getRight() + "\n" + + "multiplier = " + contract.multiplier() + "\n" + + "exchange = " + contract.exchange() + "\n" + + "primaryExch = " + contract.primaryExch() + "\n" + + "currency = " + contract.currency() + "\n" + + "localSymbol = " + contract.localSymbol() + "\n" + + "tradingClass = " + contract.tradingClass() + "\n"; } - static public String bondContractDetails(int reqId, ContractDetails contractDetails) { - Contract contract = contractDetails.m_summary; - String msg = "reqId = " + reqId + " ===================================\n" + public static String bondContractDetails(int reqId, ContractDetails contractDetails) { + Contract contract = contractDetails.contract(); + return "reqId = " + reqId + " ===================================\n" + " ---- Bond Contract Details begin ----\n" - + "symbol = " + contract.m_symbol + "\n" - + "secType = " + contract.m_secType + "\n" - + "cusip = " + contractDetails.m_cusip + "\n" - + "coupon = " + contractDetails.m_coupon + "\n" - + "maturity = " + contractDetails.m_maturity + "\n" - + "issueDate = " + contractDetails.m_issueDate + "\n" - + "ratings = " + contractDetails.m_ratings + "\n" - + "bondType = " + contractDetails.m_bondType + "\n" - + "couponType = " + contractDetails.m_couponType + "\n" - + "convertible = " + contractDetails.m_convertible + "\n" - + "callable = " + contractDetails.m_callable + "\n" - + "putable = " + contractDetails.m_putable + "\n" - + "descAppend = " + contractDetails.m_descAppend + "\n" - + "exchange = " + contract.m_exchange + "\n" - + "currency = " + contract.m_currency + "\n" - + "marketName = " + contractDetails.m_marketName + "\n" - + "tradingClass = " + contract.m_tradingClass + "\n" - + "conid = " + contract.m_conId + "\n" - + "minTick = " + contractDetails.m_minTick + "\n" - + "orderTypes = " + contractDetails.m_orderTypes + "\n" - + "validExchanges = " + contractDetails.m_validExchanges + "\n" - + "nextOptionDate = " + contractDetails.m_nextOptionDate + "\n" - + "nextOptionType = " + contractDetails.m_nextOptionType + "\n" - + "nextOptionPartial = " + contractDetails.m_nextOptionPartial + "\n" - + "notes = " + contractDetails.m_notes + "\n" - + "longName = " + contractDetails.m_longName + "\n" - + "evRule = " + contractDetails.m_evRule + "\n" - + "evMultiplier = " + contractDetails.m_evMultiplier + "\n" + + "symbol = " + contract.symbol() + "\n" + + "secType = " + contract.getSecType() + "\n" + + "cusip = " + contractDetails.cusip() + "\n" + + "coupon = " + contractDetails.coupon() + "\n" + + "maturity = " + contractDetails.maturity() + "\n" + + "issueDate = " + contractDetails.issueDate() + "\n" + + "ratings = " + contractDetails.ratings() + "\n" + + "bondType = " + contractDetails.bondType() + "\n" + + "couponType = " + contractDetails.couponType() + "\n" + + "convertible = " + contractDetails.convertible() + "\n" + + "callable = " + contractDetails.callable() + "\n" + + "putable = " + contractDetails.putable() + "\n" + + "descAppend = " + contractDetails.descAppend() + "\n" + + "exchange = " + contract.exchange() + "\n" + + "currency = " + contract.currency() + "\n" + + "marketName = " + contractDetails.marketName() + "\n" + + "tradingClass = " + contract.tradingClass() + "\n" + + "conid = " + contract.conid() + "\n" + + "minTick = " + contractDetails.minTick() + "\n" + + "orderTypes = " + contractDetails.orderTypes() + "\n" + + "validExchanges = " + contractDetails.validExchanges() + "\n" + + "nextOptionDate = " + contractDetails.nextOptionDate() + "\n" + + "nextOptionType = " + contractDetails.nextOptionType() + "\n" + + "nextOptionPartial = " + contractDetails.nextOptionPartial() + "\n" + + "notes = " + contractDetails.notes() + "\n" + + "longName = " + contractDetails.longName() + "\n" + + "evRule = " + contractDetails.evRule() + "\n" + + "evMultiplier = " + contractDetails.evMultiplier() + "\n" + + "mdSizeMultiplier = " + contractDetails.mdSizeMultiplier() + "\n" + + "aggGroup = " + contractDetails.aggGroup() + "\n" + + "marketRuleIds = " + contractDetails.marketRuleIds() + "\n" + contractDetailsSecIdList(contractDetails) + " ---- Bond Contract Details End ----\n"; - return msg; - } - - static public String contractDetailsSecIdList(ContractDetails contractDetails) { - String msg = "secIdList={"; - if (contractDetails.m_secIdList != null) { - Vector secIdList = contractDetails.m_secIdList; - for (int i = 0; i < secIdList.size(); ++i) { - TagValue param = (TagValue)secIdList.elementAt(i); - if (i > 0) { - msg += ","; - } - msg += param.m_tag + "=" + param.m_value; - } + } + + private static String contractDetailsSecIdList(ContractDetails contractDetails) { + final StringBuilder sb = new StringBuilder(32); + sb.append("secIdList={"); + if (contractDetails.secIdList() != null) { + for (TagValue param : contractDetails.secIdList()) { + sb.append(param.m_tag).append("=").append(param.m_value).append(','); + } + if (!contractDetails.secIdList().isEmpty()) { + sb.setLength(sb.length() - 1); + } } - msg += "}\n"; - return msg; + sb.append("}\n"); + return sb.toString(); } - static public String contractDetailsEnd(int reqId) { + public static String contractDetailsEnd(int reqId) { return "reqId = " + reqId + " =============== end ==============="; } - static public String execDetails( int reqId, Contract contract, Execution execution) { - String msg = " ---- Execution Details begin ----\n" + public static String execDetails( int reqId, Contract contract, Execution execution) { + return " ---- Execution Details begin ----\n" + "reqId = " + reqId + "\n" - + "orderId = " + execution.m_orderId + "\n" - + "clientId = " + execution.m_clientId + "\n" + + "orderId = " + execution.orderId() + "\n" + + "clientId = " + execution.clientId() + "\n" + contractMsg(contract) - + "execId = " + execution.m_execId + "\n" - + "time = " + execution.m_time + "\n" - + "acctNumber = " + execution.m_acctNumber + "\n" - + "executionExchange = " + execution.m_exchange + "\n" - + "side = " + execution.m_side + "\n" - + "shares = " + execution.m_shares + "\n" - + "price = " + execution.m_price + "\n" - + "permId = " + execution.m_permId + "\n" - + "liquidation = " + execution.m_liquidation + "\n" - + "cumQty = " + execution.m_cumQty + "\n" - + "avgPrice = " + execution.m_avgPrice + "\n" - + "orderRef = " + execution.m_orderRef + "\n" - + "evRule = " + execution.m_evRule + "\n" - + "evMultiplier = " + execution.m_evMultiplier + "\n" + + "execId = " + execution.execId() + "\n" + + "time = " + execution.time() + "\n" + + "acctNumber = " + execution.acctNumber() + "\n" + + "executionExchange = " + execution.exchange() + "\n" + + "side = " + execution.side() + "\n" + + "shares = " + execution.shares() + "\n" + + "price = " + execution.price() + "\n" + + "permId = " + execution.permId() + "\n" + + "liquidation = " + execution.liquidation() + "\n" + + "cumQty = " + execution.cumQty() + "\n" + + "avgPrice = " + execution.avgPrice() + "\n" + + "orderRef = " + execution.orderRef() + "\n" + + "evRule = " + execution.evRule() + "\n" + + "evMultiplier = " + execution.evMultiplier() + "\n" + + "modelCode = " + execution.modelCode() + "\n" + " ---- Execution Details end ----\n"; - return msg; } - static public String execDetailsEnd(int reqId) { + public static String execDetailsEnd(int reqId) { return "reqId = " + reqId + " =============== end ==============="; } - static public String updateMktDepth( int tickerId, int position, int operation, int side, + public static String updateMktDepth( int tickerId, int position, int operation, int side, double price, int size) { return "updateMktDepth: " + tickerId + " " + position + " " + operation + " " + side + " " + price + " " + size; } - static public String updateMktDepthL2( int tickerId, int position, String marketMaker, + public static String updateMktDepthL2( int tickerId, int position, String marketMaker, int operation, int side, double price, int size) { return "updateMktDepth: " + tickerId + " " + position + " " + marketMaker + " " + operation + " " + side + " " + price + " " + size; } - static public String updateNewsBulletin( int msgId, int msgType, String message, String origExchange) { + public static String updateNewsBulletin( int msgId, int msgType, String message, String origExchange) { return "MsgId=" + msgId + " :: MsgType=" + msgType + " :: Origin=" + origExchange + " :: Message=" + message; } - static public String managedAccounts( String accountsList) { + public static String managedAccounts( String accountsList) { return "Connected : The list of managed accounts are : [" + accountsList + "]"; } - static public String receiveFA(int faDataType, String xml) { - return FINANCIAL_ADVISOR + " " + EClientSocket.faMsgTypeName(faDataType) + " " + xml; + public static String receiveFA(int faDataType, String xml) { + return FINANCIAL_ADVISOR + " " + EClient.faMsgTypeName(faDataType) + " " + xml; } - static public String historicalData(int reqId, String date, double open, double high, double low, - double close, int volume, int count, double WAP, boolean hasGaps) { + public static String historicalData(int reqId, String date, double open, double high, double low, + double close, long volume, int count, double WAP) { return "id=" + reqId + " date = " + date + " open=" + open + @@ -431,9 +434,14 @@ static public String historicalData(int reqId, String date, double open, double " close=" + close + " volume=" + volume + " count=" + count + - " WAP=" + WAP + - " hasGaps=" + hasGaps; + " WAP=" + WAP; } + public static String historicalDataEnd(int reqId, String startDate, String endDate) { + return "id=" + reqId + + " start date = " + startDate + + " end date=" + endDate; + } + public static String realtimeBar(int reqId, long time, double open, double high, double low, double close, long volume, double wap, int count) { return "id=" + reqId + @@ -447,97 +455,328 @@ public static String realtimeBar(int reqId, long time, double open, " WAP=" + wap; } - static public String scannerParameters(String xml) { + public static String scannerParameters(String xml) { return SCANNER_PARAMETERS + "\n" + xml; } - static public String scannerData(int reqId, int rank, ContractDetails contractDetails, + public static String scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, String benchmark, String projection, String legsStr) { - Contract contract = contractDetails.m_summary; + Contract contract = contractDetails.contract(); return "id = " + reqId + " rank=" + rank + - " symbol=" + contract.m_symbol + - " secType=" + contract.m_secType + - " expiry=" + contract.m_expiry + - " strike=" + contract.m_strike + - " right=" + contract.m_right + - " exchange=" + contract.m_exchange + - " currency=" + contract.m_currency + - " localSymbol=" + contract.m_localSymbol + - " marketName=" + contractDetails.m_marketName + - " tradingClass=" + contract.m_tradingClass + + " symbol=" + contract.symbol() + + " secType=" + contract.getSecType() + + " lastTradeDate=" + contract.lastTradeDateOrContractMonth() + + " strike=" + contract.strike() + + " right=" + contract.getRight() + + " exchange=" + contract.exchange() + + " currency=" + contract.currency() + + " localSymbol=" + contract.localSymbol() + + " marketName=" + contractDetails.marketName() + + " tradingClass=" + contract.tradingClass() + " distance=" + distance + " benchmark=" + benchmark + " projection=" + projection + " legsStr=" + legsStr; } - static public String scannerDataEnd(int reqId) { + public static String scannerDataEnd(int reqId) { return "id = " + reqId + " =============== end ==============="; } - static public String currentTime(long time) { + public static String currentTime(long time) { return "current time = " + time + " (" + DateFormat.getDateTimeInstance().format(new Date(time * 1000)) + ")"; } - static public String fundamentalData(int reqId, String data) { + public static String fundamentalData(int reqId, String data) { return "id = " + reqId + " len = " + data.length() + '\n' + data; } - static public String deltaNeutralValidation(int reqId, UnderComp underComp) { + public static String deltaNeutralValidation(int reqId, DeltaNeutralContract underComp) { return "id = " + reqId - + " underComp.conId =" + underComp.m_conId - + " underComp.delta =" + underComp.m_delta - + " underComp.price =" + underComp.m_price; + + " underComp.conId =" + underComp.conid() + + " underComp.delta =" + underComp.delta() + + " underComp.price =" + underComp.price(); } - static public String tickSnapshotEnd(int tickerId) { + public static String tickSnapshotEnd(int tickerId) { return "id=" + tickerId + " =============== end ==============="; } - static public String marketDataType(int reqId, int marketDataType){ + public static String marketDataType(int reqId, int marketDataType){ return "id=" + reqId + " marketDataType = " + MarketDataType.getField(marketDataType); } - static public String commissionReport( CommissionReport commissionReport) { - String msg = "commission report:" + + public static String commissionReport( CommissionReport commissionReport) { + return "commission report:" + " execId=" + commissionReport.m_execId + " commission=" + Util.DoubleMaxString(commissionReport.m_commission) + " currency=" + commissionReport.m_currency + " realizedPNL=" + Util.DoubleMaxString(commissionReport.m_realizedPNL) + " yield=" + Util.DoubleMaxString(commissionReport.m_yield) + " yieldRedemptionDate=" + Util.IntMaxString(commissionReport.m_yieldRedemptionDate); - return msg; } - static public String position( String account, Contract contract, int position, double avgCost) { - String msg = " ---- Position begin ----\n" + public static String position( String account, Contract contract, double pos, double avgCost) { + return " ---- Position begin ----\n" + "account = " + account + "\n" + contractMsg(contract) - + "position = " + Util.IntMaxString(position) + "\n" + + "position = " + Util.DoubleMaxString(pos) + "\n" + "avgCost = " + Util.DoubleMaxString(avgCost) + "\n" + " ---- Position end ----\n"; - return msg; } - static public String positionEnd() { + public static String positionEnd() { return " =============== end ==============="; } - static public String accountSummary( int reqId, String account, String tag, String value, String currency) { - String msg = " ---- Account Summary begin ----\n" + public static String accountSummary( int reqId, String account, String tag, String value, String currency) { + return " ---- Account Summary begin ----\n" + "reqId = " + reqId + "\n" + "account = " + account + "\n" + "tag = " + tag + "\n" + "value = " + value + "\n" + "currency = " + currency + "\n" + " ---- Account Summary end ----\n"; - return msg; } - static public String accountSummaryEnd( int reqId) { + public static String accountSummaryEnd( int reqId) { return "id=" + reqId + " =============== end ==============="; } -} + public static String positionMulti( int reqId, String account, String modelCode, Contract contract, double pos, double avgCost) { + return " ---- Position begin ----\n" + + "id = " + reqId + "\n" + + "account = " + account + "\n" + + "modelCode = " + modelCode + "\n" + + contractMsg(contract) + + "position = " + Util.DoubleMaxString(pos) + "\n" + + "avgCost = " + Util.DoubleMaxString(avgCost) + "\n" + + " ---- Position end ----\n"; + } + + public static String positionMultiEnd( int reqId) { + return "id = " + reqId + " =============== end ==============="; + } + + public static String accountUpdateMulti( int reqId, String account, String modelCode, String key, String value, String currency) { + return " id = " + reqId + " account = " + account + " modelCode = " + modelCode + + " key = " + key + " value = " + value + " currency = " + currency; + } + + public static String accountUpdateMultiEnd( int reqId) { + return "id = " + reqId + " =============== end ==============="; + } + + public static String securityDefinitionOptionalParameter(int reqId, String exchange, int underlyingConId, String tradingClass, + String multiplier, Set expirations, Set strikes) { + final StringBuilder sb = new StringBuilder(128); + sb.append(" id = ").append(reqId) + .append(" exchange = ").append(exchange) + .append(" underlyingConId = ").append(underlyingConId) + .append(" tradingClass = ").append(tradingClass) + .append(" multiplier = ").append(multiplier) + .append(" expirations: "); + for (String expiration : expirations) { + sb.append(expiration).append(", "); + } + sb.append(" strikes: "); + for (Double strike : strikes) { + sb.append(strike).append(", "); + } + return sb.toString(); + } + + public static String securityDefinitionOptionalParameterEnd( int reqId) { + return "id = " + reqId + " =============== end ==============="; + } + + public static String softDollarTiers(int reqId, SoftDollarTier[] tiers) { + StringBuilder sb = new StringBuilder(); + sb.append("==== Soft Dollar Tiers Begin (total=").append(tiers.length).append(") reqId: ").append(reqId).append(" ====\n"); + for (int i = 0; i < tiers.length; i++) { + sb.append("Soft Dollar Tier [").append(i).append("] - name: ").append(tiers[i].name()) + .append(", value: ").append(tiers[i].value()).append("\n"); + } + sb.append("==== Soft Dollar Tiers End (total=").append(tiers.length).append(") ====\n"); + + return sb.toString(); + } + + public static String familyCodes(FamilyCode[] familyCodes) { + StringBuilder sb = new StringBuilder(256); + sb.append("==== Family Codes Begin (total=").append(familyCodes.length).append(") ====\n"); + for (int i = 0; i < familyCodes.length; i++) { + sb.append("Family Code [").append(i) + .append("] - accountID: ").append(familyCodes[i].accountID()) + .append(", familyCode: ").append(familyCodes[i].familyCodeStr()) + .append("\n"); + } + sb.append("==== Family Codes End (total=").append(familyCodes.length).append(") ====\n"); + + return sb.toString(); + } + + public static String symbolSamples(int reqId, ContractDescription[] contractDescriptions) { + StringBuilder sb = new StringBuilder(256); + sb.append("==== Symbol Samples Begin (total=").append(contractDescriptions.length).append(") reqId: ").append(reqId).append(" ====\n"); + for (int i = 0; i < contractDescriptions.length; i++) { + sb.append("---- Contract Description Begin (").append(i).append(") ----\n"); + sb.append("conId: ").append(contractDescriptions[i].contract().conid()).append("\n"); + sb.append("symbol: ").append(contractDescriptions[i].contract().symbol()).append("\n"); + sb.append("secType: ").append(contractDescriptions[i].contract().secType()).append("\n"); + sb.append("primaryExch: ").append(contractDescriptions[i].contract().primaryExch()).append("\n"); + sb.append("currency: ").append(contractDescriptions[i].contract().currency()).append("\n"); + sb.append("derivativeSecTypes (total=").append(contractDescriptions[i].derivativeSecTypes().length).append("): "); + for (int j = 0; j < contractDescriptions[i].derivativeSecTypes().length; j++){ + sb.append(contractDescriptions[i].derivativeSecTypes()[j]).append(' '); + } + sb.append("\n"); + sb.append("---- Contract Description End (").append(i).append(") ----\n"); + } + sb.append("==== Symbol Samples End (total=").append(contractDescriptions.length).append(") reqId: ").append(reqId).append(" ====\n"); + + return sb.toString(); + } + + public static String mktDepthExchanges(DepthMktDataDescription[] depthMktDataDescriptions) { + StringBuilder sb = new StringBuilder(); + sb.append("==== Market Depth Exchanges Begin (total=").append(depthMktDataDescriptions.length).append(") ====\n"); + for (int i = 0; i < depthMktDataDescriptions.length; i++) { + sb.append("Depth Market Data Description [").append(i).append("] - exchange: ").append(depthMktDataDescriptions[i].exchange()) + .append(", secType: ").append(depthMktDataDescriptions[i].secType()) + .append(", listingExch: ").append(depthMktDataDescriptions[i].listingExch()) + .append(", serviceDataType: ").append(depthMktDataDescriptions[i].serviceDataType()) + .append(", aggGroup: ").append(depthMktDataDescriptions[i].aggGroup() != Integer.MAX_VALUE ? + depthMktDataDescriptions[i].aggGroup() : "").append("\n"); + } + sb.append("==== Market Depth Exchanges End (total=").append(depthMktDataDescriptions.length).append(") ====\n"); + return sb.toString(); + } + + public static String tickNews(int tickerId, long timeStamp, String providerCode, String articleId, String headline, String extraData) { + return "TickNews. tickerId: " + tickerId + ", timeStamp: " + Util.UnixMillisecondsToString(timeStamp, "yyyy-MM-dd HH:mm:ss zzz") + + ", providerCode: " + providerCode + ", articleId: " + articleId + ", headline: " + headline + ", extraData: " + extraData; + } + + public static String newsProviders(NewsProvider[] newsProviders) { + StringBuilder sb = new StringBuilder(); + sb.append("==== News Providers Begin (total=").append(newsProviders.length).append(") ====\n"); + for (int i = 0; i < newsProviders.length; i++) { + sb.append("News Provider [").append(i).append("] - providerCode: ").append(newsProviders[i].providerCode()).append(", providerName: ") + .append(newsProviders[i].providerName()).append("\n"); + } + sb.append("==== News Providers End (total=").append(newsProviders.length).append(") ====\n"); + + return sb.toString(); + } + + public static String error( Exception ex) { return "Error - " + ex;} + public static String error( String str) { return str;} + + public static String error(int id, int errorCode, String errorMsg) { + return id + " | " + errorCode + " | " + errorMsg; + } + + public static String connectionClosed() { + return "Connection Closed"; + } + + public static String softDollarTiers(SoftDollarTier[] tiers) { + StringBuilder sb = new StringBuilder(); + + sb.append("==== Soft Dollar Tiers Begin (total=").append(tiers.length).append(") ====\n"); + + for (SoftDollarTier tier : tiers) { + sb.append(tier).append("\n"); + } + + sb.append("==== Soft Dollar Tiers End (total=").append(tiers.length).append(") ====\n"); + + return sb.toString(); + } + + public static String tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions) { + return "id=" + tickerId + " minTick = " + minTick + " bboExchange = " + bboExchange + " snapshotPermissions = " + snapshotPermissions; + } + + public static String smartComponents(int reqId, Map> theMap) { + StringBuilder sb = new StringBuilder(); + + sb.append("==== Smart Components Begin (total=").append(theMap.entrySet().size()).append(") reqId = ").append(reqId).append("====\n"); + + for (Map.Entry> item : theMap.entrySet()) { + sb.append("bit number: ").append(item.getKey()).append(", exchange: ").append(item.getValue().getKey()).append(", exchange letter: ").append(item.getValue().getValue()).append("\n"); + } + + sb.append("==== Smart Components End (total=").append(theMap.entrySet().size()).append(") reqId = ").append(reqId).append("====\n"); + + return sb.toString(); + } + + public static String newsArticle(int requestId, int articleType, String articleText) { + StringBuilder sb = new StringBuilder(); + sb.append("==== News Article Begin requestId: ").append(requestId).append(" ====\n"); + if (articleType == 0) { + sb.append("---- Article type is text or html ----\n"); + sb.append(articleText).append("\n"); + } else if (articleType == 1) { + sb.append("---- Article type is binary/pdf ----\n"); + sb.append("Binary/pdf article text cannot be displayed\n"); + } + sb.append("==== News Article End requestId: ").append(requestId).append(" ====\n"); + return sb.toString(); + } + + public static String historicalNews(int requestId, String time, String providerCode, String articleId, String headline) { + return "Historical News. RequestId: " + requestId + ", time: " + time + ", providerCode: " + providerCode + + ", articleId: " + articleId + ", headline: " + headline; + } + + public static String historicalNewsEnd( int requestId, boolean hasMore) { + return "Historical News End. RequestId: " + requestId + ", hasMore: " + hasMore; + } + + public static String headTimestamp(int reqId, String headTimestamp) { + return "Head timestamp. Req Id: " + reqId + ", headTimestamp: " + headTimestamp; + } + + public static String histogramData(int reqId, List items) { + StringBuilder sb = new StringBuilder(); + sb.append("Histogram data. Req Id: ").append(reqId).append(", Data (").append(items.size()).append("):\n"); + items.forEach(i -> sb.append("\tPrice: ").append(i.price).append(", Size: ").append(i.size).append("\n")); + return sb.toString(); + } + + public static String rerouteMktDataReq(int reqId, int conId, String exchange) { + return "Re-route market data request. Req Id: " + reqId + ", Con Id: " + conId + ", Exchange: " + exchange; + } + + public static String rerouteMktDepthReq(int reqId, int conId, String exchange) { + return "Re-route market depth request. Req Id: " + reqId + ", Con Id: " + conId + ", Exchange: " + exchange; + } + + public static String marketRule(int marketRuleId, PriceIncrement[] priceIncrements) { + DecimalFormat df = new DecimalFormat("#.#"); + df.setMaximumFractionDigits(340); + StringBuilder sb = new StringBuilder(256); + sb.append("==== Market Rule Begin (marketRuleId=").append(marketRuleId).append(") ====\n"); + for (PriceIncrement priceIncrement : priceIncrements) { + sb.append("Low Edge: ").append(df.format(priceIncrement.lowEdge())); + sb.append(", Increment: ").append(df.format(priceIncrement.increment())); + sb.append("\n"); + } + sb.append("==== Market Rule End (marketRuleId=").append(marketRuleId).append(") ====\n"); + return sb.toString(); + } + + + public static String pnl(int reqId, double dailyPnL, double unrealizedPnL) { + return "Daily PnL. Req Id: " + reqId + ", daily PnL: " + dailyPnL + ", unrealizedPnL: " + unrealizedPnL; + } + + public static String pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double value) { + return "Daily PnL Single. Req Id: " + reqId + ", pos: " + pos + ", daily PnL: " + dailyPnL + ", unrealizedPnL: " + unrealizedPnL + ", value: " + value; + } +} \ No newline at end of file diff --git a/ref/client/Execution.java b/ref/client/Execution.java index c1a1e5b..bf9ef50 100644 --- a/ref/client/Execution.java +++ b/ref/client/Execution.java @@ -4,23 +4,62 @@ package com.ib.client; public class Execution { - public int m_orderId; - public int m_clientId; - public String m_execId; - public String m_time; - public String m_acctNumber; - public String m_exchange; - public String m_side; - public int m_shares; - public double m_price; - public int m_permId; - public int m_liquidation; - public int m_cumQty; - public double m_avgPrice; - public String m_orderRef; - public String m_evRule; - public double m_evMultiplier; + private int m_orderId; + private int m_clientId; + private String m_execId; + private String m_time; + private String m_acctNumber; + private String m_exchange; + private String m_side; + private double m_shares; + private double m_price; + private int m_permId; + private int m_liquidation; + private double m_cumQty; + private double m_avgPrice; + private String m_orderRef; + private String m_evRule; + private double m_evMultiplier; + private String m_modelCode; + // Get + public int orderId() { return m_orderId; } + public int clientId() { return m_clientId; } + public String execId() { return m_execId; } + public String time() { return m_time; } + public String acctNumber() { return m_acctNumber; } + public String exchange() { return m_exchange; } + public String side() { return m_side; } + public double shares() { return m_shares; } + public double price() { return m_price; } + public int permId() { return m_permId; } + public int liquidation() { return m_liquidation; } + public double cumQty() { return m_cumQty; } + public double avgPrice() { return m_avgPrice; } + public String orderRef() { return m_orderRef; } + public String evRule() { return m_evRule; } + public double evMultiplier() { return m_evMultiplier; } + public String modelCode() { return m_modelCode; } + + // Set + public void orderId(int orderId) { m_orderId = orderId; } + public void clientId(int clientId) { m_clientId = clientId; } + public void execId(String execId) { m_execId = execId; } + public void time(String time) { m_time = time; } + public void acctNumber(String acctNumber) { m_acctNumber = acctNumber; } + public void exchange(String exchange) { m_exchange = exchange; } + public void side(String side) { m_side = side; } + public void shares(double shares) { m_shares = shares; } + public void price(double price) { m_price = price; } + public void permId(int permId) { m_permId = permId; } + public void liquidation(int liquidation) { m_liquidation = liquidation; } + public void cumQty(double cumQty) { m_cumQty = cumQty; } + public void avgPrice(double avgPrice) { m_avgPrice = avgPrice; } + public void orderRef(String orderRef) { m_orderRef = orderRef; } + public void evRule(String evRule) { m_evRule = evRule; } + public void evMultiplier(double evMultiplier) { m_evMultiplier = evMultiplier; } + public void modelCode(String modelCode) { m_modelCode = modelCode; } + public Execution() { m_orderId = 0; m_clientId = 0; @@ -36,7 +75,8 @@ public Execution() { public Execution( int p_orderId, int p_clientId, String p_execId, String p_time, String p_acctNumber, String p_exchange, String p_side, int p_shares, double p_price, int p_permId, int p_liquidation, int p_cumQty, - double p_avgPrice, String p_orderRef, String p_evRule, double p_evMultiplier) { + double p_avgPrice, String p_orderRef, String p_evRule, double p_evMultiplier, + String p_modelCode) { m_orderId = p_orderId; m_clientId = p_clientId; m_execId = p_execId; @@ -53,21 +93,24 @@ public Execution( int p_orderId, int p_clientId, String p_execId, String p_time, m_orderRef = p_orderRef; m_evRule = p_evRule; m_evMultiplier = p_evMultiplier; + m_modelCode = p_modelCode; } + @Override public boolean equals(Object p_other) { - boolean l_bRetVal = false; - - if ( p_other == null ) { - l_bRetVal = false; - } - else if ( this == p_other ) { - l_bRetVal = true; + if (this == p_other) { + return true; } - else { - Execution l_theOther = (Execution)p_other; - l_bRetVal = m_execId.equals( l_theOther.m_execId); + if (!(p_other instanceof Execution)) { + return false; } - return l_bRetVal; + Execution l_theOther = (Execution)p_other; + return m_execId.equals(l_theOther.m_execId); + } + + @Override + public int hashCode() { + // Since equals() uses m_execId only, the hashCode should do as well. + return m_execId != null ? m_execId.hashCode() : 0; } } diff --git a/ref/client/ExecutionCondition.java b/ref/client/ExecutionCondition.java new file mode 100644 index 0000000..d8709e4 --- /dev/null +++ b/ref/client/ExecutionCondition.java @@ -0,0 +1,64 @@ +package com.ib.client; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +public class ExecutionCondition extends OrderCondition { + + public static final OrderConditionType conditionType = OrderConditionType.Execution; + + protected ExecutionCondition() { } + + @Override + public void readFrom(ObjectInput in) throws IOException{ + super.readFrom(in); + + m_secType = in.readUTF(); + m_exchange = in.readUTF(); + m_symbol = in.readUTF(); + } + + @Override + public String toString() { + return "trade occurs for " + m_symbol + " symbol on " + m_exchange + " exchange for " + m_secType + " security type"; + } + + @Override + public void writeTo(ObjectOutput out) throws IOException { + super.writeTo(out); + + out.writeUTF(m_secType); + out.writeUTF(m_exchange); + out.writeUTF(m_symbol); + } + + private String m_exchange; + private String m_secType; + private String m_symbol; + + public String exchange() { + return m_exchange; + } + + public void exchange(String m_exchange) { + this.m_exchange = m_exchange; + } + + public String secType() { + return m_secType; + } + + public void secType(String m_secType) { + this.m_secType = m_secType; + } + + public String symbol() { + return m_symbol; + } + + public void symbol(String m_symbol) { + this.m_symbol = m_symbol; + } + +} \ No newline at end of file diff --git a/ref/client/ExecutionFilter.java b/ref/client/ExecutionFilter.java index 462fffd..78ab26d 100644 --- a/ref/client/ExecutionFilter.java +++ b/ref/client/ExecutionFilter.java @@ -4,16 +4,34 @@ package com.ib.client; public class ExecutionFilter{ - public int m_clientId; // zero means no filtering on this field - public String m_acctCode; - public String m_time; - public String m_symbol; - public String m_secType; - public String m_exchange; - public String m_side; + private int m_clientId; // zero means no filtering on this field + private String m_acctCode; + private String m_time; + private String m_symbol; + private String m_secType; + private String m_exchange; + private String m_side; + + // Get + public int clientId() { return m_clientId; } + public String acctCode() { return m_acctCode; } + public String time() { return m_time; } + public String symbol() { return m_symbol; } + public String secType() { return m_secType; } + public String exchange() { return m_exchange; } + public String side() { return m_side; } + + // Set + public void clientId(int clientId) { m_clientId = clientId; } + public void acctCode(String acctCode) { m_acctCode = acctCode; } + public void time(String time) { m_time = time; } + public void symbol(String symbol) { m_symbol = symbol; } + public void secType(String secType) { m_secType = secType; } + public void exchange(String exchange) { m_exchange = exchange; } + public void side(String side) { m_side = side; } public ExecutionFilter() { - m_clientId = 0; + clientId(0); } public ExecutionFilter( int p_clientId, String p_acctCode, String p_time, @@ -27,25 +45,27 @@ public ExecutionFilter( int p_clientId, String p_acctCode, String p_time, m_side = p_side; } + @Override public boolean equals(Object p_other) { - boolean l_bRetVal = false; - - if ( p_other == null ) { - l_bRetVal = false; - } - else if ( this == p_other ) { - l_bRetVal = true; + if (this == p_other) { + return true; } - else { - ExecutionFilter l_theOther = (ExecutionFilter)p_other; - l_bRetVal = (m_clientId == l_theOther.m_clientId && - m_acctCode.equalsIgnoreCase( l_theOther.m_acctCode) && - m_time.equalsIgnoreCase( l_theOther.m_time) && - m_symbol.equalsIgnoreCase( l_theOther.m_symbol) && - m_secType.equalsIgnoreCase( l_theOther.m_secType) && - m_exchange.equalsIgnoreCase( l_theOther.m_exchange) && - m_side.equalsIgnoreCase( l_theOther.m_side) ); + if (!(p_other instanceof ExecutionFilter)) { + return false; } - return l_bRetVal; + ExecutionFilter l_theOther = (ExecutionFilter)p_other; + return m_clientId == l_theOther.m_clientId && + m_acctCode.equalsIgnoreCase( l_theOther.m_acctCode) && + m_time.equalsIgnoreCase( l_theOther.m_time) && + m_symbol.equalsIgnoreCase( l_theOther.m_symbol) && + m_secType.equalsIgnoreCase( l_theOther.m_secType) && + m_exchange.equalsIgnoreCase( l_theOther.m_exchange) && + m_side.equalsIgnoreCase( l_theOther.m_side); + } + + @Override + public int hashCode() { + // Use m_clientId only since other fields are string compared ignoring case and with null checks. + return m_clientId; } } diff --git a/ref/client/FamilyCode.java b/ref/client/FamilyCode.java new file mode 100644 index 0000000..0133be0 --- /dev/null +++ b/ref/client/FamilyCode.java @@ -0,0 +1,25 @@ +/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class FamilyCode { + private String m_accountID; + private String m_familyCodeStr; + + // Get + public String accountID() { return m_accountID; } + public String familyCodeStr() { return m_familyCodeStr; } + + // Set + public void accountID(String accountID) { m_accountID = accountID; } + public void familyCodeStr(String familyCodeStr) { m_familyCodeStr = familyCodeStr; } + + public FamilyCode() { + } + + public FamilyCode(String p_accountID, String p_familyCodeStr) { + m_accountID = p_accountID; + m_familyCodeStr = p_familyCodeStr; + } +} diff --git a/ref/client/HistogramEntry.java b/ref/client/HistogramEntry.java new file mode 100644 index 0000000..7dab27b --- /dev/null +++ b/ref/client/HistogramEntry.java @@ -0,0 +1,50 @@ +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class HistogramEntry implements Comparable { + + public double price; + public long size; + + public HistogramEntry(double price, long size) { + this.price = price; + this.size = size; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || !(o instanceof HistogramEntry)) return false; + HistogramEntry he = (HistogramEntry) o; + return Double.compare(price, he.price) == 0 && size == he.size; + } + + @Override + public int hashCode() { + int result; + long temp; + temp = Double.doubleToLongBits(price); + result = (int) (temp ^ (temp >>> 32)); + result = 31 * result + (int) (size ^ (size >>> 32)); + return result; + } + + @Override + public int compareTo(HistogramEntry he) { + final int d = Double.compare(price, he.price); + if (d != 0) { + return d; + } + return Long.compare(size, he.size); + } + + @Override + public String toString() { + return "HistogramEntry{" + + "price=" + price + + ", size=" + size + + '}'; + } +} diff --git a/ref/client/MarginCondition.java b/ref/client/MarginCondition.java new file mode 100644 index 0000000..5f315b9 --- /dev/null +++ b/ref/client/MarginCondition.java @@ -0,0 +1,34 @@ +package com.ib.client; + +public class MarginCondition extends OperatorCondition { + + public static final OrderConditionType conditionType = OrderConditionType.Margin; + + protected MarginCondition() { } + + @Override + public String toString() { + return "the margin cushion percent" + super.toString(); + } + + private int m_percent; + + public int percent() { + return m_percent; + } + + public void percent(int m_percent) { + this.m_percent = m_percent; + } + + @Override + protected String valueToString() { + return "" + m_percent; + } + + @Override + protected void valueFromString(String v) { + m_percent = Integer.parseInt(v); + } + +} \ No newline at end of file diff --git a/ref/client/MarketDataType.java b/ref/client/MarketDataType.java index 338fee1..de2930c 100644 --- a/ref/client/MarketDataType.java +++ b/ref/client/MarketDataType.java @@ -7,13 +7,34 @@ public class MarketDataType { // constants - market data types public static final int REALTIME = 1; public static final int FROZEN = 2; + public static final int DELAYED = 3; + public static final int DELAYED_FROZEN = 4; + + private static final String REALTIME_STR = "Real-Time"; + private static final String FROZEN_STR = "Frozen"; + private static final String DELAYED_STR = "Delayed"; + private static final String DELAYED_FROZEN_STR = "Delayed-Frozen"; + private static final String UNKNOWN_STR = "Unknown"; public static String getField( int marketDataType) { switch( marketDataType) { - case REALTIME: return "Real-Time"; - case FROZEN: return "Frozen"; + case REALTIME: return REALTIME_STR; + case FROZEN: return FROZEN_STR; + case DELAYED: return DELAYED_STR; + case DELAYED_FROZEN: return DELAYED_FROZEN_STR; + + default: return UNKNOWN_STR; + } + } + + public static int getField( String marketDataTypeStr) { + switch( marketDataTypeStr) { + case REALTIME_STR: return REALTIME; + case FROZEN_STR: return FROZEN; + case DELAYED_STR: return DELAYED; + case DELAYED_FROZEN_STR: return DELAYED_FROZEN; - default: return "Unknown"; + default: return Integer.MAX_VALUE; } } diff --git a/ref/client/NewsProvider.java b/ref/client/NewsProvider.java new file mode 100644 index 0000000..5c4c75e --- /dev/null +++ b/ref/client/NewsProvider.java @@ -0,0 +1,25 @@ +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class NewsProvider { + private String m_providerCode; + private String m_providerName; + + // Get + public String providerCode() { return m_providerCode; } + public String providerName() { return m_providerName; } + + // Set + public void providerCode(String providerCode) { m_providerCode = providerCode; } + public void providerName(String providerName) { m_providerName = providerName; } + + public NewsProvider() { + } + + public NewsProvider(String p_providerCode, String p_providerName) { + m_providerCode = p_providerCode; + m_providerName = p_providerName; + } +} diff --git a/ref/client/OperatorCondition.java b/ref/client/OperatorCondition.java new file mode 100644 index 0000000..8d97d33 --- /dev/null +++ b/ref/client/OperatorCondition.java @@ -0,0 +1,44 @@ +package com.ib.client; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + + +public abstract class OperatorCondition extends OrderCondition { + + private boolean m_isMore; + + protected abstract String valueToString(); + protected abstract void valueFromString(String v); + + + @Override + public void readFrom(ObjectInput in) throws IOException { + super.readFrom(in); + + m_isMore = in.readBoolean(); + + valueFromString(in.readUTF()); + } + + @Override + public String toString() { + return " is " + (isMore() ? ">= " : "<= ") + valueToString(); + } + + @Override + public void writeTo(ObjectOutput out) throws IOException { + super.writeTo(out); + out.writeBoolean(m_isMore); + out.writeUTF(valueToString()); + } + + public boolean isMore() { + return m_isMore; + } + + public void isMore(boolean m_isMore) { + this.m_isMore = m_isMore; + } +} \ No newline at end of file diff --git a/ref/client/Order.java b/ref/client/Order.java index 8b2d2fa..96133f4 100644 --- a/ref/client/Order.java +++ b/ref/client/Order.java @@ -3,7 +3,19 @@ package com.ib.client; -import java.util.Vector; +import java.util.ArrayList; +import java.util.List; + +import com.ib.client.Types.Action; +import com.ib.client.Types.AlgoStrategy; +import com.ib.client.Types.HedgeType; +import com.ib.client.Types.Method; +import com.ib.client.Types.OcaType; +import com.ib.client.Types.ReferencePriceType; +import com.ib.client.Types.Rule80A; +import com.ib.client.Types.TimeInForce; +import com.ib.client.Types.TriggerMethod; +import com.ib.client.Types.VolatilityType; public class Order { final public static int CUSTOMER = 0; @@ -20,156 +32,436 @@ public class Order { final public static int AUCTION_TRANSPARENT = 3; final public static String EMPTY_STR = ""; - // main order fields - public int m_orderId; - public int m_clientId; - public int m_permId; - public String m_action; - public int m_totalQuantity; - public String m_orderType; - public double m_lmtPrice; - public double m_auxPrice; + // order id's + private int m_clientId; + private int m_orderId; + private long m_permId; + private int m_parentId; // Parent order Id, to associate Auto STP or TRAIL orders with the original order. + + // primary attributes + private String m_action = "BUY"; + private double m_totalQuantity; + private int m_displaySize; + private String m_orderType = "LMT"; + private double m_lmtPrice = Double.MAX_VALUE; + private double m_auxPrice = Double.MAX_VALUE; + private String m_tif = "DAY"; // "Time in Force" - DAY, GTC, etc. - // extended order fields - public String m_tif; // "Time in Force" - DAY, GTC, etc. - public String m_activeStartTime; // GTC orders - public String m_activeStopTime; // GTC orders - public String m_ocaGroup; // one cancels all group name - public int m_ocaType; // 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK - public String m_orderRef; - public boolean m_transmit; // if false, order will be created but not transmited - public int m_parentId; // Parent order Id, to associate Auto STP or TRAIL orders with the original order. - public boolean m_blockOrder; - public boolean m_sweepToFill; - public int m_displaySize; - public int m_triggerMethod; // 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point - public boolean m_outsideRth; - public boolean m_hidden; - public String m_goodAfterTime; // FORMAT: 20060505 08:00:00 {time zone} - public String m_goodTillDate; // FORMAT: 20060505 08:00:00 {time zone} - public boolean m_overridePercentageConstraints; - public String m_rule80A; // Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N' - public boolean m_allOrNone; - public int m_minQty; - public double m_percentOffset; // REL orders only; specify the decimal, e.g. .04 not 4 - public double m_trailStopPrice; // for TRAILLIMIT orders only - public double m_trailingPercent; // specify the percentage, e.g. 3, not .03 - - // Financial advisors only - public String m_faGroup; - public String m_faProfile; - public String m_faMethod; - public String m_faPercentage; + // Clearing info + private String m_account; // IB account + private String m_settlingFirm; + private String m_clearingAccount; // True beneficiary of the order + private String m_clearingIntent; // "" (Default), "IB", "Away", "PTA" (PostTrade) + + // secondary attributes + private boolean m_allOrNone; + private boolean m_blockOrder; + private boolean m_hidden; + private boolean m_outsideRth; + private boolean m_sweepToFill; + private double m_percentOffset = Double.MAX_VALUE; // for Relative orders; specify the decimal, e.g. .04 not 4 + private double m_trailingPercent = Double.MAX_VALUE; // for Trailing Stop orders; specify the percentage, e.g. 3, not .03 + private double m_trailStopPrice = Double.MAX_VALUE; // stop price for Trailing Stop orders + private int m_minQty = Integer.MAX_VALUE; + private String m_goodAfterTime; // FORMAT: 20060505 08:00:00 EST + private String m_goodTillDate; // FORMAT: 20060505 08:00:00 EST or 20060505 + private String m_ocaGroup; // one cancels all group name + private String m_orderRef; + private String m_rule80A = ""; + private int m_ocaType = 0; // None + private int m_triggerMethod = 0; // Default + // extended order fields + private String m_activeStartTime; // GTC orders + private String m_activeStopTime; // GTC orders + + // advisor allocation orders + private String m_faGroup; + private String m_faMethod = ""; // None; + private String m_faPercentage; + private String m_faProfile; + + // volatility orders + private double m_volatility = Double.MAX_VALUE; // enter percentage not decimal, e.g. 2 not .02 + private int m_volatilityType = Integer.MAX_VALUE; // None; + private int m_continuousUpdate; + private int m_referencePriceType = Integer.MAX_VALUE; // None; + private String m_deltaNeutralOrderType = ""; // None; + private double m_deltaNeutralAuxPrice = Double.MAX_VALUE; + private int m_deltaNeutralConId; + private String m_deltaNeutralOpenClose; + private boolean m_deltaNeutralShortSale; + private int m_deltaNeutralShortSaleSlot; + private String m_deltaNeutralDesignatedLocation; + + // scale orders + private int m_scaleInitLevelSize = Integer.MAX_VALUE; + private int m_scaleSubsLevelSize = Integer.MAX_VALUE; + private double m_scalePriceIncrement = Double.MAX_VALUE; + private double m_scalePriceAdjustValue = Double.MAX_VALUE; + private int m_scalePriceAdjustInterval = Integer.MAX_VALUE; + private double m_scaleProfitOffset = Double.MAX_VALUE; + private boolean m_scaleAutoReset; + private int m_scaleInitPosition = Integer.MAX_VALUE; + private int m_scaleInitFillQty = Integer.MAX_VALUE; + private boolean m_scaleRandomPercent; + private String m_scaleTable; + + // hedge orders + private String m_hedgeType = ""; + private String m_hedgeParam; // beta value for beta hedge (in range 0-1), ratio for pair hedge + + // algo orders + private String m_algoStrategy = ""; + private List m_algoParams = new ArrayList<>(); + private String m_algoId; + + // combo orders + private List m_smartComboRoutingParams = new ArrayList<>(); + private List m_orderComboLegs = new ArrayList<>(); + + // processing control + private boolean m_whatIf; + private boolean m_transmit = true; // if false, order will be sent to TWS but not transmitted to server + private boolean m_overridePercentageConstraints; + // Institutional orders only - public String m_openClose; // O=Open, C=Close - public int m_origin; // 0=Customer, 1=Firm - public int m_shortSaleSlot; // 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action="SSHORT - public String m_designatedLocation; // set when slot=2 only. - public int m_exemptCode; - + private String m_openClose = "O"; // O=Open, C=Close + private int m_origin; // 0=Customer, 1=Firm + private int m_shortSaleSlot; // 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action="SSHORT + private String m_designatedLocation; // set when slot=2 only. + private int m_exemptCode = -1; + private String m_deltaNeutralSettlingFirm; + private String m_deltaNeutralClearingAccount; + private String m_deltaNeutralClearingIntent; + // SMART routing only - public double m_discretionaryAmt; - public boolean m_eTradeOnly; - public boolean m_firmQuoteOnly; - public double m_nbboPriceCap; - public boolean m_optOutSmartRouting; + private double m_discretionaryAmt = Double.MAX_VALUE; + private boolean m_eTradeOnly; + private boolean m_firmQuoteOnly; + private double m_nbboPriceCap = Double.MAX_VALUE; + private boolean m_optOutSmartRouting; // BOX or VOL ORDERS ONLY - public int m_auctionStrategy; // 1=AUCTION_MATCH, 2=AUCTION_IMPROVEMENT, 3=AUCTION_TRANSPARENT + private int m_auctionStrategy; // 1=AUCTION_MATCH, 2=AUCTION_IMPROVEMENT, 3=AUCTION_TRANSPARENT // BOX ORDERS ONLY - public double m_startingPrice; - public double m_stockRefPrice; - public double m_delta; + private double m_startingPrice; + private double m_stockRefPrice; + private double m_delta = Double.MAX_VALUE; // pegged to stock or VOL orders - public double m_stockRangeLower; - public double m_stockRangeUpper; - - // VOLATILITY ORDERS ONLY - public double m_volatility; // enter percentage not decimal, e.g. 2 not .02 - public int m_volatilityType; // 1=daily, 2=annual - public int m_continuousUpdate; - public int m_referencePriceType; // 1=Bid/Ask midpoint, 2 = BidOrAsk - public String m_deltaNeutralOrderType; - public double m_deltaNeutralAuxPrice; - public int m_deltaNeutralConId; - public String m_deltaNeutralSettlingFirm; - public String m_deltaNeutralClearingAccount; - public String m_deltaNeutralClearingIntent; - public String m_deltaNeutralOpenClose; - public boolean m_deltaNeutralShortSale; - public int m_deltaNeutralShortSaleSlot; - public String m_deltaNeutralDesignatedLocation; + private double m_stockRangeLower; + private double m_stockRangeUpper; // COMBO ORDERS ONLY - public double m_basisPoints; // EFP orders only, download only - public int m_basisPointsType; // EFP orders only, download only - - // SCALE ORDERS ONLY - public int m_scaleInitLevelSize; - public int m_scaleSubsLevelSize; - public double m_scalePriceIncrement; - public double m_scalePriceAdjustValue; - public int m_scalePriceAdjustInterval; - public double m_scaleProfitOffset; - public boolean m_scaleAutoReset; - public int m_scaleInitPosition; - public int m_scaleInitFillQty; - public boolean m_scaleRandomPercent; - public String m_scaleTable; - - // HEDGE ORDERS ONLY - public String m_hedgeType; // 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair - public String m_hedgeParam; // beta value for beta hedge (in range 0-1), ratio for pair hedge - - // Clearing info - public String m_account; // IB account - public String m_settlingFirm; - public String m_clearingAccount; // True beneficiary of the order - public String m_clearingIntent; // "" (Default), "IB", "Away", "PTA" (PostTrade) - - // ALGO ORDERS ONLY - public String m_algoStrategy; - public Vector m_algoParams; - - // What-if - public boolean m_whatIf; + private double m_basisPoints; // EFP orders only, download only + private int m_basisPointsType; // EFP orders only, download only // Not Held - public boolean m_notHeld; - - // Smart combo routing params - public Vector m_smartComboRoutingParams; - - // order combo legs - public Vector m_orderComboLegs = new Vector(); + private boolean m_notHeld; + + // order misc options + private List m_orderMiscOptions; + + //order algo id + private boolean m_solicited; + + private boolean m_randomizeSize; + private boolean m_randomizePrice; + + //VER PEG2BENCH fields: + private int m_referenceContractId; + private double m_peggedChangeAmount; + private boolean m_isPeggedChangeAmountDecrease; + private double m_referenceChangeAmount; + private String m_referenceExchangeId; + private OrderType m_adjustedOrderType; + private double m_triggerPrice = Double.MAX_VALUE; + private double m_adjustedStopPrice = Double.MAX_VALUE; + private double m_adjustedStopLimitPrice = Double.MAX_VALUE; + private double m_adjustedTrailingAmount = Double.MAX_VALUE; + private int m_adjustableTrailingUnit; + private double m_lmtPriceOffset = Double.MAX_VALUE; + + private List m_conditions = new ArrayList<>(); + private boolean m_conditionsCancelOrder; + private boolean m_conditionsIgnoreRth; + + // models + private String m_modelCode; + + private String m_extOperator; + private SoftDollarTier m_softDollarTier; + + // native cash quantity + private double m_cashQty = Double.MAX_VALUE; + + // getters + public Action action() { return Action.get(m_action); } + public String getAction() { return m_action; } + public boolean allOrNone() { return m_allOrNone; } + public boolean blockOrder() { return m_blockOrder; } + public boolean eTradeOnly() { return m_eTradeOnly; } + public boolean firmQuoteOnly() { return m_firmQuoteOnly; } + public boolean hidden() { return m_hidden; } + public boolean outsideRth() { return m_outsideRth; } + public boolean notHeld() { return m_notHeld; } + public boolean solicited() { return m_solicited; } + public boolean optOutSmartRouting() { return m_optOutSmartRouting; } + public boolean scaleAutoReset() { return m_scaleAutoReset; } + public boolean scaleRandomPercent() { return m_scaleRandomPercent; } + public boolean sweepToFill() { return m_sweepToFill; } + public boolean transmit() { return m_transmit; } + public boolean whatIf() { return m_whatIf; } + public double auxPrice() { return m_auxPrice; } + public double delta() { return m_delta; } + public double deltaNeutralAuxPrice() { return m_deltaNeutralAuxPrice; } + public double discretionaryAmt() { return m_discretionaryAmt; } + public double lmtPrice() { return m_lmtPrice; } + public double nbboPriceCap() { return m_nbboPriceCap; } + public double percentOffset() { return m_percentOffset; } + public double scalePriceAdjustValue() { return m_scalePriceAdjustValue; } + public double scalePriceIncrement() { return m_scalePriceIncrement; } + public double scaleProfitOffset() { return m_scaleProfitOffset; } + public double startingPrice() { return m_startingPrice; } + public double stockRangeLower() { return m_stockRangeLower; } + public double stockRangeUpper() { return m_stockRangeUpper; } + public double stockRefPrice() { return m_stockRefPrice; } + public double basisPoints() { return m_basisPoints; } + public int basisPointsType() { return m_basisPointsType; } + public double trailingPercent() { return m_trailingPercent; } + public double trailStopPrice() { return m_trailStopPrice; } + public double volatility() { return m_volatility; } + public int clientId() { return m_clientId; } + public int continuousUpdate() { return m_continuousUpdate; } + public int deltaNeutralConId() { return m_deltaNeutralConId; } + public String deltaNeutralOpenClose() { return m_deltaNeutralOpenClose; } + public boolean deltaNeutralShortSale() { return m_deltaNeutralShortSale; } + public int deltaNeutralShortSaleSlot() { return m_deltaNeutralShortSaleSlot; } + public String deltaNeutralDesignatedLocation() { return m_deltaNeutralDesignatedLocation; } + public int displaySize() { return m_displaySize; } + public int minQty() { return m_minQty; } + public int orderId() { return m_orderId; } + public int parentId() { return m_parentId; } + public int scaleInitFillQty() { return m_scaleInitFillQty; } + public int scaleInitLevelSize() { return m_scaleInitLevelSize; } + public int scaleInitPosition() { return m_scaleInitPosition; } + public int scalePriceAdjustInterval() { return m_scalePriceAdjustInterval; } + public int scaleSubsLevelSize() { return m_scaleSubsLevelSize; } + public double totalQuantity() { return m_totalQuantity; } + public long permId() { return m_permId; } + public Method faMethod() { return Method.get(m_faMethod); } + public String getFaMethod() { return m_faMethod; } + public OcaType ocaType() { return OcaType.get(m_ocaType); } + public int getOcaType() { return m_ocaType; } + public OrderType orderType() { return OrderType.get(m_orderType); } + public String getOrderType() { return m_orderType; } + public Rule80A rule80A() { return Rule80A.get(m_rule80A); } + public String getRule80A() { return m_rule80A; } + public String account() { return m_account; } + public String settlingFirm() { return m_settlingFirm; } + public String clearingAccount() { return m_clearingAccount; } + public String clearingIntent() { return m_clearingIntent; } + public AlgoStrategy algoStrategy() { return AlgoStrategy.get(m_algoStrategy); } + public String getAlgoStrategy() { return m_algoStrategy; } + public String algoId() { return m_algoId; } + public String faGroup() { return m_faGroup; } + public String faPercentage() { return m_faPercentage; } + public String faProfile() { return m_faProfile; } + public String goodAfterTime() { return m_goodAfterTime; } + public String goodTillDate() { return m_goodTillDate; } + public String hedgeParam() { return m_hedgeParam; } + public HedgeType hedgeType() { return HedgeType.get(m_hedgeType); } + public String getHedgeType() { return m_hedgeType; } + public String ocaGroup() { return m_ocaGroup; } + public String orderRef() { return m_orderRef; } + public TimeInForce tif() { return TimeInForce.get(m_tif); } + public String getTif() { return m_tif; } + public String scaleTable() { return m_scaleTable; } + public int auctionStrategy() { return m_auctionStrategy; } + public VolatilityType volatilityType() { return VolatilityType.get(m_volatilityType); } + public int getVolatilityType() { return m_volatilityType; } + public TriggerMethod triggerMethod() { return TriggerMethod.get(m_triggerMethod); } + public int getTriggerMethod() { return m_triggerMethod; } + public String activeStartTime() { return m_activeStartTime; } + public String activeStopTime() { return m_activeStopTime; } + public OrderType deltaNeutralOrderType() { return OrderType.get(m_deltaNeutralOrderType); } + public String getDeltaNeutralOrderType() { return m_deltaNeutralOrderType; } + public List orderComboLegs() { return m_orderComboLegs; } + public boolean overridePercentageConstraints() { return m_overridePercentageConstraints; } + public String openClose() { return m_openClose; } + public int origin() { return m_origin; } + public int shortSaleSlot() { return m_shortSaleSlot; } + public String designatedLocation() { return m_designatedLocation; } + public int exemptCode() { return m_exemptCode; } + public String deltaNeutralSettlingFirm() { return m_deltaNeutralSettlingFirm; } + public String deltaNeutralClearingAccount() { return m_deltaNeutralClearingAccount; } + public String deltaNeutralClearingIntent() { return m_deltaNeutralClearingIntent; } + public ReferencePriceType referencePriceType() { return ReferencePriceType.get(m_referencePriceType); } + public int getReferencePriceType() { return m_referencePriceType; } + public List smartComboRoutingParams() { return m_smartComboRoutingParams; } + public List orderMiscOptions() { return m_orderMiscOptions; } + public boolean randomizeSize() { return m_randomizeSize; } + public boolean randomizePrice() { return m_randomizePrice; } + public int referenceContractId() { return m_referenceContractId; } + public boolean isPeggedChangeAmountDecrease() { return m_isPeggedChangeAmountDecrease; } + public double peggedChangeAmount() { return m_peggedChangeAmount; } + public double referenceChangeAmount() { return m_referenceChangeAmount; } + public String referenceExchangeId() { return m_referenceExchangeId; } + public OrderType adjustedOrderType() { return m_adjustedOrderType; } + public double triggerPrice() { return m_triggerPrice; } + public double adjustedStopPrice() { return m_adjustedStopPrice; } + public double adjustedStopLimitPrice() { return m_adjustedStopLimitPrice; } + public double adjustedTrailingAmount() { return m_adjustedTrailingAmount; } + public int adjustableTrailingUnit() { return m_adjustableTrailingUnit; } + public double lmtPriceOffset() { return m_lmtPriceOffset; } + public List conditions() { return m_conditions; } + public boolean conditionsIgnoreRth() { return m_conditionsIgnoreRth; } + public boolean conditionsCancelOrder() { return m_conditionsCancelOrder; } + public String modelCode() { return m_modelCode; } + public String extOperator() { return m_extOperator; } + public SoftDollarTier softDollarTier() { return m_softDollarTier; } + public double cashQty() { return m_cashQty; } + // setters + public void referenceContractId(int m_referenceContractId) { this.m_referenceContractId = m_referenceContractId; } + public void account(String v) { m_account = v; } + public void settlingFirm(String v) { m_settlingFirm = v; } + public void clearingAccount(String v) { m_clearingAccount = v; } + public void clearingIntent(String v) { m_clearingIntent = v; } + public void action(Action v) { m_action = ( v == null ) ? null : v.getApiString(); } + public void action(String v) { m_action = v; } + public void algoStrategy(AlgoStrategy v) { m_algoStrategy = ( v == null ) ? null : v.getApiString(); } + public void algoStrategy(String v) { m_algoStrategy = v; } + public void algoId(String v) { m_algoId = v; } + public void allOrNone(boolean v) { m_allOrNone = v; } + public void auxPrice(double v) { m_auxPrice = v; } + public void blockOrder(boolean v) { m_blockOrder = v; } + public void clientId(int v) { m_clientId = v; } + public void continuousUpdate(int v) { m_continuousUpdate = v; } + public void delta(double v) { m_delta = v; } + public void deltaNeutralAuxPrice(double v) { m_deltaNeutralAuxPrice = v; } + public void deltaNeutralConId(int v) { m_deltaNeutralConId = v; } + public void deltaNeutralOpenClose(String v) { m_deltaNeutralOpenClose = v; } + public void deltaNeutralShortSale(boolean v) { m_deltaNeutralShortSale = v; } + public void deltaNeutralShortSaleSlot(int v) { m_deltaNeutralShortSaleSlot = v; } + public void deltaNeutralDesignatedLocation(String v) { m_deltaNeutralDesignatedLocation = v; } + public void deltaNeutralOrderType(OrderType v) { m_deltaNeutralOrderType = ( v == null ) ? null : v.getApiString(); } + public void deltaNeutralOrderType(String v) { m_deltaNeutralOrderType = v; } + public void discretionaryAmt(double v) { m_discretionaryAmt = v; } + public void displaySize(int v) { m_displaySize = v; } + public void eTradeOnly(boolean v) { m_eTradeOnly = v; } + public void faGroup(String v) { m_faGroup = v; } + public void faMethod(Method v) { m_faMethod = ( v == null ) ? null : v.getApiString(); } + public void faMethod(String v) { m_faMethod = v; } + public void faPercentage(String v) { m_faPercentage = v; } + public void faProfile(String v) { m_faProfile = v; } + public void firmQuoteOnly(boolean v) { m_firmQuoteOnly = v; } + public void goodAfterTime(String v) { m_goodAfterTime = v; } + public void goodTillDate(String v) { m_goodTillDate = v; } + public void hedgeParam(String v) { m_hedgeParam = v; } + public void hedgeType(HedgeType v) { m_hedgeType = ( v == null ) ? null : v.getApiString(); } + public void hedgeType(String v) { m_hedgeType = v; } + public void hidden(boolean v) { m_hidden = v; } + public void lmtPrice(double v) { m_lmtPrice = v; } + public void minQty(int v) { m_minQty = v; } + public void nbboPriceCap(double v) { m_nbboPriceCap = v; } + public void notHeld(boolean v) { m_notHeld = v; } + public void solicited(boolean v) { m_solicited = v; } + public void ocaGroup(String v) { m_ocaGroup = v; } + public void ocaType(OcaType v) { m_ocaType = ( v == null ) ? 0 : v.ordinal(); } + public void ocaType(int v) { m_ocaType = v; } + public void optOutSmartRouting(boolean v) { m_optOutSmartRouting = v; } + public void orderId(int v) { m_orderId = v; } + public void orderRef(String v) { m_orderRef = v; } + public void orderType(OrderType v) { m_orderType = ( v == null ) ? null : v.getApiString(); } + public void orderType(String v) { m_orderType = v; } + public void outsideRth(boolean v) { m_outsideRth = v; } + public void overridePercentageConstraints(boolean v) { m_overridePercentageConstraints = v; } + public void openClose(String v) { m_openClose = v; } + public void origin(int v) { m_origin = v; } + public void shortSaleSlot(int v) { m_shortSaleSlot = v; } + public void designatedLocation(String v) { m_designatedLocation = v; } + public void exemptCode(int v) { m_exemptCode = v; } + public void parentId(int v) { m_parentId = v; } + public void percentOffset(double v) { m_percentOffset = v; } + public void permId(long v) { m_permId = v; } + public void referencePriceType(ReferencePriceType v) { m_referencePriceType = ( v == null ) ? 0 : v.ordinal(); } + public void referencePriceType(int v) { m_referencePriceType = v; } + public void rule80A(Rule80A v) { m_rule80A = ( v == null ) ? null : v.getApiString(); } + public void rule80A(String v) { m_rule80A = v; } + public void scaleAutoReset(boolean v) { m_scaleAutoReset = v; } + public void scaleInitFillQty(int v) { m_scaleInitFillQty = v; } + public void scaleInitLevelSize(int v) { m_scaleInitLevelSize = v; } + public void scaleInitPosition(int v) { m_scaleInitPosition = v; } + public void scalePriceAdjustInterval(int v) { m_scalePriceAdjustInterval = v; } + public void scalePriceAdjustValue(double v) { m_scalePriceAdjustValue = v; } + public void scalePriceIncrement(double v) { m_scalePriceIncrement = v; } + public void scaleProfitOffset(double v) { m_scaleProfitOffset = v; } + public void scaleRandomPercent(boolean v) { m_scaleRandomPercent = v; } + public void scaleSubsLevelSize(int v) { m_scaleSubsLevelSize = v; } + public void startingPrice(double v) { m_startingPrice = v; } + public void stockRangeLower(double v) { m_stockRangeLower = v; } + public void stockRangeUpper(double v) { m_stockRangeUpper = v; } + public void stockRefPrice(double v) { m_stockRefPrice = v; } + public void basisPoints(double v) { m_basisPoints = v; } + public void basisPointsType(int v) { m_basisPointsType = v; } + public void sweepToFill(boolean v) { m_sweepToFill = v; } + public void tif(TimeInForce v) { m_tif = ( v == null ) ? null : v.getApiString(); } + public void tif(String v) { m_tif = v; } + public void totalQuantity(double v) { m_totalQuantity = v; } + public void trailingPercent(double v) { m_trailingPercent = v; } + public void trailStopPrice(double v) { m_trailStopPrice = v; } + public void transmit(boolean v) { m_transmit = v; } + public void triggerMethod(TriggerMethod v) { m_triggerMethod = ( v == null ) ? 0 : v.val(); } + public void triggerMethod(int v) { m_triggerMethod = v; } + public void activeStartTime(String v) { m_activeStartTime = v; } + public void activeStopTime(String v) { m_activeStopTime = v; } + public void algoParams(List v) { m_algoParams = v; } + public void volatility(double v) { m_volatility = v; } + public void volatilityType(VolatilityType v) { m_volatilityType = ( v == null ) ? 0 : v.ordinal(); } + public void volatilityType(int v) { m_volatilityType = v; } + public void whatIf(boolean v) { m_whatIf = v; } + public void scaleTable(String v) { m_scaleTable = v; } + public void auctionStrategy(int v) { m_auctionStrategy = v; } + public void orderComboLegs(List v) { m_orderComboLegs = v; } + public void deltaNeutralSettlingFirm(String v) { m_deltaNeutralSettlingFirm = v; } + public void deltaNeutralClearingAccount(String v) { m_deltaNeutralClearingAccount = v; } + public void deltaNeutralClearingIntent(String v) { m_deltaNeutralClearingIntent = v; } + public void smartComboRoutingParams(List v) { m_smartComboRoutingParams = v; } + public void orderMiscOptions(List v) { m_orderMiscOptions = v; } + public void randomizeSize(boolean v) { m_randomizeSize = v; } + public void randomizePrice(boolean v) { m_randomizePrice = v; } + public void modelCode(String v) { m_modelCode = v; } + public void isPeggedChangeAmountDecrease(boolean v) { m_isPeggedChangeAmountDecrease = v; } + public void peggedChangeAmount(double m_peggedChangeAmount) { this.m_peggedChangeAmount = m_peggedChangeAmount; } + public void referenceChangeAmount(double m_referenceChangeAmount) { this.m_referenceChangeAmount = m_referenceChangeAmount; } + public void referenceExchangeId(String m_referenceExchangeId) { this.m_referenceExchangeId = m_referenceExchangeId; } + public void adjustedOrderType(OrderType v) { m_adjustedOrderType = v; } + public void triggerPrice(double v) { m_triggerPrice = v; } + public void adjustedStopPrice(double v) { m_adjustedStopPrice = v; } + public void adjustedStopLimitPrice(double v) { m_adjustedStopLimitPrice = v; } + public void adjustedTrailingAmount(double v) { m_adjustedTrailingAmount = v; } + public void adjustableTrailingUnit(int v) { m_adjustableTrailingUnit = v; } + public void lmtPriceOffset(double v) { m_lmtPriceOffset = v; } + public void conditions(List v) { m_conditions = v; } + public void conditionsIgnoreRth(boolean v) { m_conditionsIgnoreRth = v; } + public void conditionsCancelOrder(boolean v) { m_conditionsCancelOrder = v; } + public void extOperator(String v) { m_extOperator = v; } + public void softDollarTier(SoftDollarTier v) { m_softDollarTier = v; } + public void cashQty(double v) { m_cashQty = v; } public Order() { - m_lmtPrice = Double.MAX_VALUE; - m_auxPrice = Double.MAX_VALUE; m_activeStartTime = EMPTY_STR; m_activeStopTime = EMPTY_STR; m_outsideRth = false; - m_openClose = "O"; m_origin = CUSTOMER; - m_transmit = true; m_designatedLocation = EMPTY_STR; - m_exemptCode = -1; - m_minQty = Integer.MAX_VALUE; - m_percentOffset = Double.MAX_VALUE; - m_nbboPriceCap = Double.MAX_VALUE; m_optOutSmartRouting = false; m_startingPrice = Double.MAX_VALUE; m_stockRefPrice = Double.MAX_VALUE; - m_delta = Double.MAX_VALUE; m_stockRangeLower = Double.MAX_VALUE; m_stockRangeUpper = Double.MAX_VALUE; - m_volatility = Double.MAX_VALUE; - m_volatilityType = Integer.MAX_VALUE; - m_deltaNeutralOrderType = EMPTY_STR; - m_deltaNeutralAuxPrice = Double.MAX_VALUE; m_deltaNeutralConId = 0; m_deltaNeutralSettlingFirm = EMPTY_STR; m_deltaNeutralClearingAccount = EMPTY_STR; @@ -178,34 +470,36 @@ public Order() { m_deltaNeutralShortSale = false; m_deltaNeutralShortSaleSlot = 0; m_deltaNeutralDesignatedLocation = EMPTY_STR; - m_referencePriceType = Integer.MAX_VALUE; - m_trailStopPrice = Double.MAX_VALUE; - m_trailingPercent = Double.MAX_VALUE; m_basisPoints = Double.MAX_VALUE; m_basisPointsType = Integer.MAX_VALUE; - m_scaleInitLevelSize = Integer.MAX_VALUE; - m_scaleSubsLevelSize = Integer.MAX_VALUE; - m_scalePriceIncrement = Double.MAX_VALUE; - m_scalePriceAdjustValue = Double.MAX_VALUE; - m_scalePriceAdjustInterval = Integer.MAX_VALUE; - m_scaleProfitOffset = Double.MAX_VALUE; m_scaleAutoReset = false; - m_scaleInitPosition = Integer.MAX_VALUE; - m_scaleInitFillQty = Integer.MAX_VALUE; m_scaleRandomPercent = false; m_scaleTable = EMPTY_STR; m_whatIf = false; m_notHeld = false; + m_algoId = EMPTY_STR; + m_solicited = false; + m_randomizeSize = false; + m_randomizePrice = false; + m_extOperator = EMPTY_STR; + m_softDollarTier = new SoftDollarTier(EMPTY_STR, EMPTY_STR, EMPTY_STR); } - public boolean equals(Object p_other) { + public List algoParams() { + if( m_algoParams == null ) { + m_algoParams = new ArrayList<>(); + } + return m_algoParams; + } - if ( this == p_other ) + @Override + public boolean equals(Object p_other) { + if (this == p_other) { return true; - - if ( p_other == null ) + } + if (!(p_other instanceof Order)) { return false; - + } Order l_theOther = (Order)p_other; if ( m_permId == l_theOther.m_permId ) { @@ -267,7 +561,22 @@ public boolean equals(Object p_other) { m_scaleRandomPercent != l_theOther.m_scaleRandomPercent || m_whatIf != l_theOther.m_whatIf || m_notHeld != l_theOther.m_notHeld || - m_exemptCode != l_theOther.m_exemptCode) { + m_exemptCode != l_theOther.m_exemptCode || + m_randomizePrice != l_theOther.m_randomizePrice || + m_randomizeSize != l_theOther.m_randomizeSize || + m_solicited != l_theOther.m_solicited || + m_referenceContractId != l_theOther.m_referenceContractId || + m_peggedChangeAmount != l_theOther.m_peggedChangeAmount || + m_referenceChangeAmount != l_theOther.m_referenceChangeAmount || + m_adjustedOrderType != l_theOther.m_adjustedOrderType || + m_triggerPrice != l_theOther.m_triggerPrice || + m_adjustedStopPrice != l_theOther.m_adjustedStopPrice || + m_adjustedStopLimitPrice != l_theOther.m_adjustedStopLimitPrice || + m_adjustedTrailingAmount != l_theOther.m_adjustedTrailingAmount || + m_adjustableTrailingUnit != l_theOther.m_adjustableTrailingUnit || + m_lmtPriceOffset != l_theOther.m_lmtPriceOffset || + m_softDollarTier.equals(l_theOther.m_softDollarTier) || + m_cashQty != l_theOther.m_cashQty) { return false; } @@ -300,23 +609,37 @@ public boolean equals(Object p_other) { Util.StringCompare(m_clearingAccount, l_theOther.m_clearingAccount) != 0 || Util.StringCompare(m_clearingIntent, l_theOther.m_clearingIntent) != 0 || Util.StringCompare(m_algoStrategy, l_theOther.m_algoStrategy) != 0 || - Util.StringCompare(m_scaleTable, l_theOther.m_scaleTable) != 0) { + Util.StringCompare(m_algoId, l_theOther.m_algoId) != 0 || + Util.StringCompare(m_scaleTable, l_theOther.m_scaleTable) != 0 || + Util.StringCompare(m_modelCode, l_theOther.m_modelCode) != 0 || + Util.StringCompare(m_referenceExchangeId, l_theOther.m_referenceExchangeId) != 0 || + Util.StringCompare(m_extOperator, l_theOther.m_extOperator) != 0) { return false; } - if (!Util.VectorEqualsUnordered(m_algoParams, l_theOther.m_algoParams)) { + if (!Util.listsEqualUnordered(m_algoParams, l_theOther.m_algoParams)) { return false; } - if (!Util.VectorEqualsUnordered(m_smartComboRoutingParams, l_theOther.m_smartComboRoutingParams)) { + if (!Util.listsEqualUnordered(m_smartComboRoutingParams, l_theOther.m_smartComboRoutingParams)) { return false; } // compare order combo legs - if (!Util.VectorEqualsUnordered(m_orderComboLegs, l_theOther.m_orderComboLegs)) { + if (!Util.listsEqualUnordered(m_orderComboLegs, l_theOther.m_orderComboLegs)) { return false; } - + + if (!Util.listsEqualUnordered(m_conditions, l_theOther.m_conditions)) { + return false; + } + return true; } + + @Override + public int hashCode() { + // Use m_permId only due to the definition of equals. + return (int) (m_permId ^ (m_permId >>> 32)); + } } diff --git a/ref/client/OrderComboLeg.java b/ref/client/OrderComboLeg.java index 5b9afd7..4229e25 100644 --- a/ref/client/OrderComboLeg.java +++ b/ref/client/OrderComboLeg.java @@ -5,9 +5,11 @@ public class OrderComboLeg { + private double m_price; // price per leg - public double m_price; // price per leg - + public double price() { return m_price; } + public void price(double v) { m_price = v; } + public OrderComboLeg() { m_price = Double.MAX_VALUE; } @@ -16,20 +18,23 @@ public OrderComboLeg(double p_price) { m_price = p_price; } + @Override public boolean equals(Object p_other) { - if ( this == p_other ) { + if (this == p_other) { return true; } - else if ( p_other == null ) { + if (!(p_other instanceof OrderComboLeg)) { return false; } OrderComboLeg l_theOther = (OrderComboLeg)p_other; - if (m_price != l_theOther.m_price) { - return false; - } + return m_price == l_theOther.m_price; + } - return true; + @Override + public int hashCode() { + long temp = Double.doubleToLongBits(m_price); + return (int) (temp ^ (temp >>> 32)); } } diff --git a/ref/client/OrderCondition.java b/ref/client/OrderCondition.java new file mode 100644 index 0000000..4660303 --- /dev/null +++ b/ref/client/OrderCondition.java @@ -0,0 +1,72 @@ +package com.ib.client; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + + +public abstract class OrderCondition { + + private OrderConditionType m_type; + private boolean m_isConjunctionConnection; + + public void readFrom(ObjectInput in) throws IOException { + conjunctionConnection(in.readUTF().compareToIgnoreCase("a") == 0); + } + + public void writeTo(ObjectOutput out) throws IOException { + out.writeUTF(conjunctionConnection() ? "a" : "o"); + } + + + @Override + public String toString() { + return conjunctionConnection() ? "" : ""; + } + + public boolean conjunctionConnection() { + return m_isConjunctionConnection; + } + + public void conjunctionConnection(boolean isConjunctionConnection) { + this.m_isConjunctionConnection = isConjunctionConnection; + } + + public OrderConditionType type() { + return m_type; + } + + public static OrderCondition create(OrderConditionType type) { + OrderCondition orderCondition; + switch (type) { + case Execution: + orderCondition = new ExecutionCondition(); + break; + + case Margin: + orderCondition = new MarginCondition(); + break; + + case PercentChange: + orderCondition = new PercentChangeCondition(); + break; + + case Price: + orderCondition = new PriceCondition(); + break; + + case Time: + orderCondition = new TimeCondition(); + break; + + case Volume: + orderCondition = new VolumeCondition(); + break; + + default: + return null; + } + orderCondition.m_type = type; + return orderCondition; + } +} \ No newline at end of file diff --git a/ref/client/OrderConditionType.java b/ref/client/OrderConditionType.java new file mode 100644 index 0000000..bd3294d --- /dev/null +++ b/ref/client/OrderConditionType.java @@ -0,0 +1,28 @@ +package com.ib.client; + +public enum OrderConditionType { + Price(1), + Time(3), + Margin(4), + Execution(5), + Volume(6), + PercentChange(7); + + private int m_val; + + OrderConditionType(int v) { + m_val = v; + } + + public int val() { + return m_val; + } + + public static OrderConditionType fromInt(int n) { + for (OrderConditionType i : OrderConditionType.values()) + if (i.val() == n) + return i; + + throw new NumberFormatException(); + } +} \ No newline at end of file diff --git a/ref/client/OrderState.java b/ref/client/OrderState.java index 9483f1f..50bbe94 100644 --- a/ref/client/OrderState.java +++ b/ref/client/OrderState.java @@ -3,20 +3,41 @@ package com.ib.client; -public class OrderState { - - public String m_status; - - public String m_initMargin; - public String m_maintMargin; - public String m_equityWithLoan; - - public double m_commission; - public double m_minCommission; - public double m_maxCommission; - public String m_commissionCurrency; - public String m_warningText; +public class OrderState { + private String m_status; + private String m_initMargin; + private String m_maintMargin; + private String m_equityWithLoan; + private double m_commission; + private double m_minCommission; + private double m_maxCommission; + private String m_commissionCurrency; + private String m_warningText; + + // Get + public double commission() { return m_commission; } + public double maxCommission() { return m_maxCommission; } + public double minCommission() { return m_minCommission; } + public OrderStatus status() { return OrderStatus.get(m_status); } + public String getStatus() { return m_status; } + public String commissionCurrency() { return m_commissionCurrency; } + public String equityWithLoan() { return m_equityWithLoan; } + public String initMargin() { return m_initMargin; } + public String maintMargin() { return m_maintMargin; } + public String warningText() { return m_warningText; } + + // Set + public void commission(double v) { m_commission = v; } + public void commissionCurrency(String v) { m_commissionCurrency = v; } + public void equityWithLoan(String v) { m_equityWithLoan = v; } + public void initMargin(String v) { m_initMargin = v; } + public void maintMargin(String v) { m_maintMargin = v; } + public void maxCommission(double v) { m_maxCommission = v; } + public void minCommission(double v) { m_minCommission = v; } + public void status(OrderStatus v) { m_status = ( v == null ) ? null : v.name(); } + public void status(String v) { m_status = v; } + public void warningText(String v) { m_warningText = v; } OrderState() { this (null, null, null, null, 0.0, 0.0, 0.0, null, null); @@ -25,8 +46,8 @@ public class OrderState { OrderState(String status, String initMargin, String maintMargin, String equityWithLoan, double commission, double minCommission, double maxCommission, String commissionCurrency, String warningText) { - - m_initMargin = initMargin; + m_status = status; + m_initMargin = initMargin; m_maintMargin = maintMargin; m_equityWithLoan = equityWithLoan; m_commission = commission; @@ -36,14 +57,14 @@ public class OrderState { m_warningText = warningText; } - public boolean equals(Object other) { - - if (this == other) + @Override + public boolean equals(Object other) { + if (this == other) { return true; - - if (other == null) + } + if (!(other instanceof OrderState)) { return false; - + } OrderState state = (OrderState)other; if (m_commission != state.m_commission || @@ -59,7 +80,20 @@ public boolean equals(Object other) { Util.StringCompare(m_commissionCurrency, state.m_commissionCurrency) != 0) { return false; } - return true; } + + @Override + public int hashCode() { + // Use a few fields as a compromise between performance and hashCode quality. + int result; + long temp; + temp = Double.doubleToLongBits(m_commission); + result = (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(m_minCommission); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(m_maxCommission); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } } diff --git a/ref/controller/OrderStatus.java b/ref/client/OrderStatus.java similarity index 65% rename from ref/controller/OrderStatus.java rename to ref/client/OrderStatus.java index 3842e0d..beb4cb1 100644 --- a/ref/controller/OrderStatus.java +++ b/ref/client/OrderStatus.java @@ -1,7 +1,8 @@ /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ -package com.ib.controller; +package com.ib.client; + public enum OrderStatus { ApiPending, @@ -15,9 +16,16 @@ public enum OrderStatus { PendingSubmit, Unknown; + public static OrderStatus get(String apiString) { + for( OrderStatus type : values() ) { + if( type.name().equalsIgnoreCase(apiString) ) { + return type; + } + } + return Unknown; + } + public boolean isActive() { return this == PreSubmitted || this == PendingCancel || this == Submitted || this == PendingSubmit; } } - - diff --git a/ref/controller/OrderType.java b/ref/client/OrderType.java similarity index 85% rename from ref/controller/OrderType.java rename to ref/client/OrderType.java index ea26d2f..b017154 100644 --- a/ref/controller/OrderType.java +++ b/ref/client/OrderType.java @@ -1,9 +1,7 @@ /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ -package com.ib.controller; - -import com.ib.client.IApiEnum; +package com.ib.client; public enum OrderType implements IApiEnum { @@ -31,6 +29,9 @@ public enum OrderType implements IApiEnum { PEG_STK( "PEG STK"), REL_PLUS_LMT( "REL + LMT"), REL_PLUS_MKT( "REL + MKT"), + SNAP_MID( "SNAP MID"), + SNAP_MKT( "SNAP MKT"), + SNAP_PRIM( "SNAP PRIM"), STP_PRT( "STP PRT"), TRAIL_LIMIT( "TRAIL LIMIT"), TRAIL_LIT( "TRAIL LIT"), @@ -38,11 +39,16 @@ public enum OrderType implements IApiEnum { TRAIL_MIT( "TRAIL MIT"), TRAIL_REL_PLUS_MKT( "TRAIL REL + MKT"), VOL( "VOL"), - VWAP( "VWAP"); + VWAP( "VWAP"), + QUOTE("QUOTE"), + PEG_PRIM_VOL("PPV"), + PEG_MID_VOL("PDV"), + PEG_MKT_VOL("PMV"), + PEG_SRF_VOL("PSV"); private String m_apiString; - private OrderType( String apiString) { + OrderType( String apiString) { m_apiString = apiString; } @@ -64,4 +70,5 @@ public static OrderType get(String apiString) { @Override public String getApiString() { return m_apiString; } + } diff --git a/ref/client/PercentChangeCondition.java b/ref/client/PercentChangeCondition.java new file mode 100644 index 0000000..88b9e2a --- /dev/null +++ b/ref/client/PercentChangeCondition.java @@ -0,0 +1,39 @@ +package com.ib.client; + +public class PercentChangeCondition extends ContractCondition { + + public static final OrderConditionType conditionType = OrderConditionType.PercentChange; + + protected PercentChangeCondition() { } + + @Override + public String toString(ContractLookuper lookuper) { + return super.toString(lookuper); + } + + @Override + public String toString() { + return toString(null); + } + + private double m_changePercent = Double.MAX_VALUE; + + public double changePercent() { + return m_changePercent; + } + + public void changePercent(double m_changePercent) { + this.m_changePercent = m_changePercent; + } + + @Override + protected String valueToString() { + return "" + m_changePercent; + } + + @Override + protected void valueFromString(String v) { + m_changePercent = Double.parseDouble(v); + } + +} \ No newline at end of file diff --git a/ref/client/PriceCondition.java b/ref/client/PriceCondition.java new file mode 100644 index 0000000..fd52274 --- /dev/null +++ b/ref/client/PriceCondition.java @@ -0,0 +1,70 @@ +package com.ib.client; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +public class PriceCondition extends ContractCondition { + + public static final OrderConditionType conditionType = OrderConditionType.Price; + + protected PriceCondition() { } + + private double m_price; + private int m_triggerMethod; + private static String[] mthdNames = new String[] { "default", "double bid/ask", "last", "double last", "bid/ask", "", "", "last of bid/ask", "mid-point" }; + + @Override + public String toString() { + return toString(null); + } + + public double price() { + return m_price; + } + + public void price(double m_price) { + this.m_price = m_price; + } + + @Override + public String toString(ContractLookuper lookuper) { + return strTriggerMethod() + " " + super.toString(lookuper); + } + + public int triggerMethod() { + return m_triggerMethod; + } + + String strTriggerMethod() { + return mthdNames[triggerMethod()]; + } + + public void triggerMethod(int m_triggerMethod) { + this.m_triggerMethod = m_triggerMethod; + } + + @Override + protected String valueToString() { + return "" + m_price; + } + + @Override + protected void valueFromString(String v) { + m_price = Double.parseDouble(v); + } + + @Override + public void readFrom(ObjectInput in) throws IOException { + super.readFrom(in); + + m_triggerMethod = in.readInt(); + } + + @Override + public void writeTo(ObjectOutput out) throws IOException { + super.writeTo(out); + out.writeInt(m_triggerMethod); + } + +} \ No newline at end of file diff --git a/ref/client/PriceIncrement.java b/ref/client/PriceIncrement.java new file mode 100644 index 0000000..4ef2377 --- /dev/null +++ b/ref/client/PriceIncrement.java @@ -0,0 +1,22 @@ +package com.ib.client; + +public class PriceIncrement { + private double m_lowEdge; + private double m_increment; + + // Get + public double lowEdge() { return m_lowEdge; } + public double increment() { return m_increment; } + + // Set + public void lowEdge(double lowEdge) { m_lowEdge = lowEdge; } + public void increment(double increment) { m_increment = increment; } + + public PriceIncrement() { + } + + public PriceIncrement(double p_lowEdge, double p_increment) { + m_lowEdge = p_lowEdge; + m_increment = p_increment; + } +} diff --git a/ref/client/SoftDollarTier.java b/ref/client/SoftDollarTier.java new file mode 100644 index 0000000..c01c843 --- /dev/null +++ b/ref/client/SoftDollarTier.java @@ -0,0 +1,78 @@ +package com.ib.client; + +public class SoftDollarTier { + + private String m_name, m_value, m_displayName; + + public SoftDollarTier(String name, String val, String displayName) { + name(name); + value(val); + + m_displayName = displayName; + } + + public String value() { + return m_value; + } + + private void value(String value) { + this.m_value = value; + } + + public String name() { + return m_name; + } + + private void name(String name) { + this.m_name = name; + } + + @Override public int hashCode() { + final int prime = 31; + int result = 1; + + result = prime * result + ((m_name == null) ? 0 : m_name.hashCode()); + result = prime * result + ((m_value == null) ? 0 : m_value.hashCode()); + + return result; + } + + @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (!(obj instanceof SoftDollarTier)) { + return false; + } + + SoftDollarTier other = (SoftDollarTier) obj; + + if (m_name == null) { + if (other.m_name != null) { + return false; + } + } else if (Util.StringCompare(m_name, other.m_name) != 0) { + return false; + } + + if (m_value == null) { + if (other.m_value != null) { + return false; + } + } else if (Util.StringCompare(m_value, other.m_value) != 0) { + return false; + } + + return true; + } + + @Override public String toString() { + return m_displayName; + } + +} diff --git a/ref/client/TagValue.java b/ref/client/TagValue.java index 1b13c5f..9b7d784 100644 --- a/ref/client/TagValue.java +++ b/ref/client/TagValue.java @@ -3,8 +3,7 @@ package com.ib.client; -public class TagValue { - +public final class TagValue { public String m_tag; public String m_value; @@ -16,21 +15,24 @@ public TagValue(String p_tag, String p_value) { m_value = p_value; } - public boolean equals(Object p_other) { - - if( this == p_other) - return true; - - if( p_other == null) - return false; - + @Override + public boolean equals(Object p_other) { + if (this == p_other) { + return true; + } + if(!(p_other instanceof TagValue)) { + return false; + } TagValue l_theOther = (TagValue)p_other; - if( Util.StringCompare(m_tag, l_theOther.m_tag) != 0 || - Util.StringCompare(m_value, l_theOther.m_value) != 0) { - return false; - } + return Util.StringCompare(m_tag, l_theOther.m_tag) == 0 + && Util.StringCompare(m_value, l_theOther.m_value) == 0; + } - return true; + @Override + public int hashCode() { + int result = (m_tag == null || "".equals(m_tag)) ? 0 : m_tag.hashCode(); + result = result * 31 + ((m_value == null || "".equals(m_value)) ? 0 : m_value.hashCode()); + return result; } } diff --git a/ref/client/TickAttr.java b/ref/client/TickAttr.java new file mode 100644 index 0000000..82b9834 --- /dev/null +++ b/ref/client/TickAttr.java @@ -0,0 +1,22 @@ +/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms + * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ + +package com.ib.client; + +public class TickAttr { + private boolean m_canAutoExecute = false; + private boolean m_pastLimit = false; + + public boolean canAutoExecute() { + return m_canAutoExecute; + } + public boolean pastLimit() { + return m_pastLimit; + } + public void canAutoExecute(boolean canAutoExecute) { + this.m_canAutoExecute = canAutoExecute; + } + public void pastLimit(boolean pastLimit) { + this.m_pastLimit = pastLimit; + } +} diff --git a/ref/client/TickType.java b/ref/client/TickType.java index ffdd83d..6389e71 100644 --- a/ref/client/TickType.java +++ b/ref/client/TickType.java @@ -3,130 +3,120 @@ package com.ib.client; -public class TickType { - // constants - tick types - public static final int BID_SIZE = 0; - public static final int BID = 1; - public static final int ASK = 2; - public static final int ASK_SIZE = 3; - public static final int LAST = 4; - public static final int LAST_SIZE = 5; - public static final int HIGH = 6; - public static final int LOW = 7; - public static final int VOLUME = 8; - public static final int CLOSE = 9; - public static final int BID_OPTION = 10; - public static final int ASK_OPTION = 11; - public static final int LAST_OPTION = 12; - public static final int MODEL_OPTION = 13; - public static final int OPEN = 14; - public static final int LOW_13_WEEK = 15; - public static final int HIGH_13_WEEK = 16; - public static final int LOW_26_WEEK = 17; - public static final int HIGH_26_WEEK = 18; - public static final int LOW_52_WEEK = 19; - public static final int HIGH_52_WEEK = 20; - public static final int AVG_VOLUME = 21; - public static final int OPEN_INTEREST = 22; - public static final int OPTION_HISTORICAL_VOL = 23; - public static final int OPTION_IMPLIED_VOL = 24; - public static final int OPTION_BID_EXCH = 25; - public static final int OPTION_ASK_EXCH = 26; - public static final int OPTION_CALL_OPEN_INTEREST = 27; - public static final int OPTION_PUT_OPEN_INTEREST = 28; - public static final int OPTION_CALL_VOLUME = 29; - public static final int OPTION_PUT_VOLUME = 30; - public static final int INDEX_FUTURE_PREMIUM = 31; - public static final int BID_EXCH = 32; - public static final int ASK_EXCH = 33; - public static final int AUCTION_VOLUME = 34; - public static final int AUCTION_PRICE = 35; - public static final int AUCTION_IMBALANCE = 36; - public static final int MARK_PRICE = 37; - public static final int BID_EFP_COMPUTATION = 38; - public static final int ASK_EFP_COMPUTATION = 39; - public static final int LAST_EFP_COMPUTATION = 40; - public static final int OPEN_EFP_COMPUTATION = 41; - public static final int HIGH_EFP_COMPUTATION = 42; - public static final int LOW_EFP_COMPUTATION = 43; - public static final int CLOSE_EFP_COMPUTATION = 44; - public static final int LAST_TIMESTAMP = 45; - public static final int SHORTABLE = 46; - public static final int FUNDAMENTAL_RATIOS = 47; - public static final int RT_VOLUME = 48; - public static final int HALTED = 49; - public static final int BID_YIELD = 50; - public static final int ASK_YIELD = 51; - public static final int LAST_YIELD = 52; - public static final int CUST_OPTION_COMPUTATION = 53; - public static final int TRADE_COUNT = 54; - public static final int TRADE_RATE = 55; - public static final int VOLUME_RATE = 56; - public static final int LAST_RTH_TRADE = 57; - public static final int REGULATORY_IMBALANCE = 61; - public static String getField( int tickType) { - switch( tickType) { - case BID_SIZE: return "bidSize"; - case BID: return "bidPrice"; - case ASK: return "askPrice"; - case ASK_SIZE: return "askSize"; - case LAST: return "lastPrice"; - case LAST_SIZE: return "lastSize"; - case HIGH: return "high"; - case LOW: return "low"; - case VOLUME: return "volume"; - case CLOSE: return "close"; - case BID_OPTION: return "bidOptComp"; - case ASK_OPTION: return "askOptComp"; - case LAST_OPTION: return "lastOptComp"; - case MODEL_OPTION: return "modelOptComp"; - case OPEN: return "open"; - case LOW_13_WEEK: return "13WeekLow"; - case HIGH_13_WEEK: return "13WeekHigh"; - case LOW_26_WEEK: return "26WeekLow"; - case HIGH_26_WEEK: return "26WeekHigh"; - case LOW_52_WEEK: return "52WeekLow"; - case HIGH_52_WEEK: return "52WeekHigh"; - case AVG_VOLUME: return "AvgVolume"; - case OPEN_INTEREST: return "OpenInterest"; - case OPTION_HISTORICAL_VOL: return "OptionHistoricalVolatility"; - case OPTION_IMPLIED_VOL: return "OptionImpliedVolatility"; - case OPTION_BID_EXCH: return "OptionBidExchStr"; - case OPTION_ASK_EXCH: return "OptionAskExchStr"; - case OPTION_CALL_OPEN_INTEREST: return "OptionCallOpenInterest"; - case OPTION_PUT_OPEN_INTEREST: return "OptionPutOpenInterest"; - case OPTION_CALL_VOLUME: return "OptionCallVolume"; - case OPTION_PUT_VOLUME: return "OptionPutVolume"; - case INDEX_FUTURE_PREMIUM: return "IndexFuturePremium"; - case BID_EXCH: return "bidExch"; - case ASK_EXCH: return "askExch"; - case AUCTION_VOLUME: return "auctionVolume"; - case AUCTION_PRICE: return "auctionPrice"; - case AUCTION_IMBALANCE: return "auctionImbalance"; - case MARK_PRICE: return "markPrice"; - case BID_EFP_COMPUTATION: return "bidEFP"; - case ASK_EFP_COMPUTATION: return "askEFP"; - case LAST_EFP_COMPUTATION: return "lastEFP"; - case OPEN_EFP_COMPUTATION: return "openEFP"; - case HIGH_EFP_COMPUTATION: return "highEFP"; - case LOW_EFP_COMPUTATION: return "lowEFP"; - case CLOSE_EFP_COMPUTATION: return "closeEFP"; - case LAST_TIMESTAMP: return "lastTimestamp"; - case SHORTABLE: return "shortable"; - case FUNDAMENTAL_RATIOS: return "fundamentals"; - case RT_VOLUME: return "RTVolume"; - case HALTED: return "halted"; - case BID_YIELD: return "bidYield"; - case ASK_YIELD: return "askYield"; - case LAST_YIELD: return "lastYield"; - case CUST_OPTION_COMPUTATION: return "custOptComp"; - case TRADE_COUNT: return "trades"; - case TRADE_RATE: return "trades/min"; - case VOLUME_RATE: return "volume/min"; - case LAST_RTH_TRADE: return "lastRTHTrade"; - case REGULATORY_IMBALANCE: return "regulatoryImbalance"; - default: return "unknown"; +public enum TickType { + BID_SIZE( 0, "bidSize" ), + BID( 1, "bidPrice" ), + ASK( 2, "askPrice" ), + ASK_SIZE( 3, "askSize" ), + LAST( 4, "lastPrice" ), + LAST_SIZE( 5, "lastSize" ), + HIGH( 6, "high" ), + LOW( 7, "low" ), + VOLUME( 8, "volume" ), + CLOSE( 9, "close" ), + BID_OPTION( 10, "bidOptComp" ), + ASK_OPTION( 11, "askOptComp" ), + LAST_OPTION( 12, "lastOptComp" ), + MODEL_OPTION( 13, "modelOptComp" ), + OPEN( 14, "open" ), + LOW_13_WEEK( 15, "13WeekLow" ), + HIGH_13_WEEK( 16, "13WeekHigh" ), + LOW_26_WEEK( 17, "26WeekLow" ), + HIGH_26_WEEK( 18, "26WeekHigh" ), + LOW_52_WEEK( 19, "52WeekLow" ), + HIGH_52_WEEK( 20, "52WeekHigh" ), + AVG_VOLUME( 21, "AvgVolume" ), + OPEN_INTEREST( 22, "OpenInterest" ), + OPTION_HISTORICAL_VOL( 23, "OptionHistoricalVolatility" ), + OPTION_IMPLIED_VOL( 24, "OptionImpliedVolatility" ), + OPTION_BID_EXCH( 25, "OptionBidExchStr" ), + OPTION_ASK_EXCH( 26, "OptionAskExchStr" ), + OPTION_CALL_OPEN_INTEREST( 27, "OptionCallOpenInterest" ), + OPTION_PUT_OPEN_INTEREST( 28, "OptionPutOpenInterest" ), + OPTION_CALL_VOLUME( 29, "OptionCallVolume" ), + OPTION_PUT_VOLUME( 30, "OptionPutVolume" ), + INDEX_FUTURE_PREMIUM( 31, "IndexFuturePremium" ), + BID_EXCH( 32, "bidExch" ), // string + ASK_EXCH( 33, "askExch" ), // string + AUCTION_VOLUME( 34, "auctionVolume" ), + AUCTION_PRICE( 35, "auctionPrice" ), + AUCTION_IMBALANCE( 36, "auctionImbalance" ), + MARK_PRICE( 37, "markPrice" ), + BID_EFP_COMPUTATION( 38, "bidEFP" ), + ASK_EFP_COMPUTATION( 39, "askEFP" ), + LAST_EFP_COMPUTATION( 40, "lastEFP" ), + OPEN_EFP_COMPUTATION( 41, "openEFP" ), + HIGH_EFP_COMPUTATION( 42, "highEFP" ), + LOW_EFP_COMPUTATION( 43, "lowEFP" ), + CLOSE_EFP_COMPUTATION( 44, "closeEFP" ), + LAST_TIMESTAMP( 45, "lastTimestamp" ), // string + SHORTABLE( 46, "shortable" ), + FUNDAMENTAL_RATIOS( 47, "fundamentals" ), // string + RT_VOLUME( 48, "RTVolume" ), // string + HALTED( 49, "halted" ), + BID_YIELD( 50, "bidYield" ), + ASK_YIELD( 51, "askYield" ), + LAST_YIELD( 52, "lastYield" ), + CUST_OPTION_COMPUTATION( 53, "custOptComp" ), + TRADE_COUNT( 54, "trades" ), + TRADE_RATE( 55, "trades/min" ), + VOLUME_RATE( 56, "volume/min" ), + LAST_RTH_TRADE( 57, "lastRTHTrade" ), + RT_HISTORICAL_VOL( 58, "RTHistoricalVol" ), + IB_DIVIDENDS( 59, "IBDividends" ), + BOND_FACTOR_MULTIPLIER( 60, "bondFactorMultiplier" ), + REGULATORY_IMBALANCE( 61, "regulatoryImbalance" ), + NEWS_TICK( 62, "newsTick" ), + SHORT_TERM_VOLUME_3_MIN( 63, "shortTermVolume3Min"), + SHORT_TERM_VOLUME_5_MIN( 64, "shortTermVolume5Min"), + SHORT_TERM_VOLUME_10_MIN( 65, "shortTermVolume10Min"), + DELAYED_BID( 66, "delayedBid"), + DELAYED_ASK( 67, "delayedAsk"), + DELAYED_LAST( 68, "delayedLast"), + DELAYED_BID_SIZE( 69, "delayedBidSize"), + DELAYED_ASK_SIZE( 70, "delayedAskSize"), + DELAYED_LAST_SIZE( 71, "delayedLastSize"), + DELAYED_HIGH( 72, "delayedHigh"), + DELAYED_LOW( 73, "delayedLow"), + DELAYED_VOLUME( 74, "delayedVolume"), + DELAYED_CLOSE( 75, "delayedClose"), + DELAYED_OPEN( 76, "delayedOpen"), + RT_TRD_VOLUME(77, "rtTrdVolume"), + CREDITMAN_MARK_PRICE(78, "creditmanMarkPrice"), + CREDITMAN_SLOW_MARK_PRICE(79, "creditmanSlowMarkPrice"), + DELAYED_BID_OPTION( 80, "delayedBidOptComp" ), + DELAYED_ASK_OPTION( 81, "delayedAskOptComp" ), + DELAYED_LAST_OPTION( 82, "delayedLastOptComp" ), + DELAYED_MODEL_OPTION( 83, "delayedModelOptComp" ), + LAST_EXCH(84, "lastExchange"), + LAST_REG_TIME(85, "lastRegTime"), + FUTURES_OPEN_INTEREST(86, "futuresOpenInterest"), + + UNKNOWN( Integer.MAX_VALUE , "unknown" ); + + private int m_ndx; + private String m_field; + + // Get + public int index() { return m_ndx; } + public String field() { return m_field; } + + TickType(int ndx, String field) { + m_ndx = ndx; + m_field = field; + } + + public static TickType get(int ndx) { + for( TickType tt : values() ) { + if( tt.m_ndx == ndx) { + return tt; + } } + return UNKNOWN; + } + + public static String getField(int tickType) { + return get(tickType).field(); } } diff --git a/ref/client/TimeCondition.java b/ref/client/TimeCondition.java new file mode 100644 index 0000000..b8a1a4f --- /dev/null +++ b/ref/client/TimeCondition.java @@ -0,0 +1,34 @@ +package com.ib.client; + +public class TimeCondition extends OperatorCondition { + + public static final OrderConditionType conditionType = OrderConditionType.Time; + + protected TimeCondition() { } + + @Override + public String toString() { + return "time" + super.toString(); + } + + private String m_time; + + public String time() { + return m_time; + } + + public void time(String m_time) { + this.m_time = m_time; + } + + @Override + protected String valueToString() { + return m_time; + } + + @Override + protected void valueFromString(String v) { + m_time = v; + } + +} \ No newline at end of file diff --git a/ref/controller/Types.java b/ref/client/Types.java similarity index 53% rename from ref/controller/Types.java rename to ref/client/Types.java index ccef2d7..efa083b 100644 --- a/ref/controller/Types.java +++ b/ref/client/Types.java @@ -1,41 +1,42 @@ /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ -package com.ib.controller; -import static com.ib.controller.Types.AlgoParam.allowPastEndTime; -import static com.ib.controller.Types.AlgoParam.displaySize; -import static com.ib.controller.Types.AlgoParam.endTime; -import static com.ib.controller.Types.AlgoParam.forceCompletion; -import static com.ib.controller.Types.AlgoParam.getDone; -import static com.ib.controller.Types.AlgoParam.maxPctVol; -import static com.ib.controller.Types.AlgoParam.noTakeLiq; -import static com.ib.controller.Types.AlgoParam.noTradeAhead; -import static com.ib.controller.Types.AlgoParam.pctVol; -import static com.ib.controller.Types.AlgoParam.riskAversion; -import static com.ib.controller.Types.AlgoParam.startTime; -import static com.ib.controller.Types.AlgoParam.strategyType; -import static com.ib.controller.Types.AlgoParam.useOddLots; -import static com.ib.controller.Types.AlgoParam.componentSize; -import static com.ib.controller.Types.AlgoParam.timeBetweenOrders; -import static com.ib.controller.Types.AlgoParam.randomizeTime20; -import static com.ib.controller.Types.AlgoParam.randomizeSize55; -import static com.ib.controller.Types.AlgoParam.giveUp; -import static com.ib.controller.Types.AlgoParam.catchUp; -import static com.ib.controller.Types.AlgoParam.waitForFill; - -import com.ib.client.IApiEnum; +package com.ib.client; + +import java.util.Arrays; + +import static com.ib.client.Types.AlgoParam.allowPastEndTime; +import static com.ib.client.Types.AlgoParam.catchUp; +import static com.ib.client.Types.AlgoParam.componentSize; +import static com.ib.client.Types.AlgoParam.displaySize; +import static com.ib.client.Types.AlgoParam.endTime; +import static com.ib.client.Types.AlgoParam.forceCompletion; +import static com.ib.client.Types.AlgoParam.getDone; +import static com.ib.client.Types.AlgoParam.giveUp; +import static com.ib.client.Types.AlgoParam.maxPctVol; +import static com.ib.client.Types.AlgoParam.noTakeLiq; +import static com.ib.client.Types.AlgoParam.noTradeAhead; +import static com.ib.client.Types.AlgoParam.pctVol; +import static com.ib.client.Types.AlgoParam.randomizeSize55; +import static com.ib.client.Types.AlgoParam.randomizeTime20; +import static com.ib.client.Types.AlgoParam.riskAversion; +import static com.ib.client.Types.AlgoParam.startTime; +import static com.ib.client.Types.AlgoParam.strategyType; +import static com.ib.client.Types.AlgoParam.timeBetweenOrders; +import static com.ib.client.Types.AlgoParam.useOddLots; +import static com.ib.client.Types.AlgoParam.waitForFill; public class Types { - public static enum ComboParam { + public enum ComboParam { NonGuaranteed, PriceCondConid, CondPriceMax, CondPriceMin, ChangeToMktTime1, ChangeToMktTime2, DiscretionaryPct, DontLeginNext, LeginPrio, MaxSegSize, } - public static enum AlgoParam { + public enum AlgoParam { startTime, endTime, allowPastEndTime, maxPctVol, pctVol, strategyType, noTakeLiq, riskAversion, forceCompletion, displaySize, getDone, noTradeAhead, useOddLots, componentSize, timeBetweenOrders, randomizeTime20, randomizeSize55, giveUp, catchUp, waitForFill } - public static enum AlgoStrategy implements IApiEnum { + public enum AlgoStrategy implements IApiEnum { None(), Vwap( startTime, endTime, maxPctVol, noTakeLiq, getDone, noTradeAhead, useOddLots), Twap( startTime, endTime, allowPastEndTime, strategyType), @@ -46,14 +47,16 @@ public static enum AlgoStrategy implements IApiEnum { private AlgoParam[] m_params; - public AlgoParam[] params() { return m_params; } + public AlgoParam[] params() { + return Arrays.copyOf(m_params, m_params.length); + } - private AlgoStrategy( AlgoParam... params) { - m_params = params; + AlgoStrategy( AlgoParam... params) { + m_params = Arrays.copyOf(params, params.length); } - public static AlgoStrategy get( String apiString) { - return apiString != null && apiString.length() > 0 ? valueOf( apiString) : None; + public static AlgoStrategy get(String apiString) { + return getValueOf(apiString, values(), None); } @Override public String getApiString() { @@ -61,16 +64,11 @@ public static AlgoStrategy get( String apiString) { } } - public static enum HedgeType implements IApiEnum { + public enum HedgeType implements IApiEnum { None, Delta, Beta, Fx, Pair; - public static HedgeType get( String apiString) { - for (HedgeType type : values() ) { - if (type.getApiString().equals( apiString) ) { - return type; - } - } - return None; + public static HedgeType get(String apiString) { + return getValueOf(apiString, values(), None); } @Override public String getApiString() { @@ -78,7 +76,7 @@ public static HedgeType get( String apiString) { } } - public static enum Right implements IApiEnum { + public enum Right implements IApiEnum { None, Put, Call; public static Right get( String apiString) { @@ -96,7 +94,7 @@ public static Right get( String apiString) { } } - public static enum VolatilityType implements IApiEnum { + public enum VolatilityType implements IApiEnum { None, Daily, Annual; public static VolatilityType get( int ordinal) { @@ -104,11 +102,11 @@ public static VolatilityType get( int ordinal) { } @Override public String getApiString() { - return "" + ordinal(); + return String.valueOf(ordinal()); } } - public static enum ReferencePriceType implements IApiEnum { + public enum ReferencePriceType implements IApiEnum { None, Midpoint, BidOrAsk; public static ReferencePriceType get( int ordinal) { @@ -116,18 +114,18 @@ public static ReferencePriceType get( int ordinal) { } @Override public String getApiString() { - return "" + ordinal(); + return String.valueOf(ordinal()); } } - public static enum TriggerMethod implements IApiEnum { + public enum TriggerMethod implements IApiEnum { Default( 0), DoubleBidAsk( 1), Last( 2), DoubleLast( 3), BidAsk( 4), LastOrBidAsk( 7), Midpoint( 8); int m_val; public int val() { return m_val; } - private TriggerMethod( int val) { + TriggerMethod( int val) { m_val = val; } @@ -141,42 +139,42 @@ public static TriggerMethod get( int val) { } @Override public String getApiString() { - return "" + m_val; + return String.valueOf(m_val); } } - public static enum Action implements IApiEnum { + public enum Action implements IApiEnum { BUY, SELL, SSHORT; - @Override public String getApiString() { + public static Action get(String apiString) { + return getValueOf(apiString, values(), null); + } + + @Override public String getApiString() { return toString(); } } - public static enum Rule80A implements IApiEnum { + public enum Rule80A implements IApiEnum { None(""), IndivArb("J"), IndivBigNonArb("K"), IndivSmallNonArb("I"), INST_ARB("U"), InstBigNonArb("Y"), InstSmallNonArb("A"); private String m_apiString; - private Rule80A( String apiString) { + Rule80A( String apiString) { m_apiString = apiString; } public static Rule80A get( String apiString) { - for (Rule80A val : values() ) { - if (val.m_apiString.equals( apiString) ) { - return val; - } - } - return None; + return getValueOf(apiString, values(), None); } - public String getApiString() { + @Override + public String getApiString() { return m_apiString; } } - public static enum OcaType implements IApiEnum { + public enum OcaType implements IApiEnum { None, CancelWithBlocking, ReduceWithBlocking, ReduceWithoutBlocking; public static OcaType get( int ordinal) { @@ -184,60 +182,91 @@ public static OcaType get( int ordinal) { } @Override public String getApiString() { - return "" + ordinal(); + return String.valueOf(ordinal()); } } - public static enum TimeInForce implements IApiEnum { + public enum TimeInForce implements IApiEnum { DAY, GTC, OPG, IOC, GTD, GTT, AUC, FOK, GTX, DTC; + public static TimeInForce get(String apiString) { + return getValueOf(apiString, values(), null); + } + @Override public String getApiString() { return toString(); } } - public static enum ExerciseType { - None, Exercise, Lapse; + public enum ExerciseType { + None, Exercise, Lapse, } - public static enum FundamentalType { - ReportSnapshot, ReportsFinSummary, ReportRatios, ReportsFinStatements, RESC, CalendarReport; + public enum FundamentalType { + ReportSnapshot("Company overview"), + ReportsFinSummary("Financial summary"), + ReportRatios("Financial ratios"), + ReportsFinStatements("Financial statements"), + RESC("Analyst estimates"), + CalendarReport("Company calendar"); + + private final String description; + + FundamentalType(final String description) { + this.description = description; + } public String getApiString() { return super.toString(); } @Override public String toString() { - switch( this) { - case ReportSnapshot: return "Company overview"; - case ReportsFinSummary: return "Financial summary"; - case ReportRatios: return "Financial ratios"; - case ReportsFinStatements: return "Financial statements"; - case RESC: return "Analyst estimates"; - case CalendarReport: return "Company calendar"; - default: return null; - } + return description; } } - public static enum WhatToShow { + public enum WhatToShow { TRADES, MIDPOINT, BID, ASK, // << only these are valid for real-time bars BID_ASK, HISTORICAL_VOLATILITY, OPTION_IMPLIED_VOLATILITY, YIELD_ASK, YIELD_BID, YIELD_BID_ASK, YIELD_LAST } - public static enum BarSize { - _1_secs, _5_secs, _10_secs, _15_secs, _30_secs, _1_min, _2_mins, _3_mins, _5_mins, _10_mins, _15_mins, _20_mins, _30_mins, _1_hour, _4_hours, _1_day, _1_week; - - public String toString() { - return super.toString().substring( 1).replace( '_', ' '); + public enum BarSize { + _1_secs("1 secs"), + _5_secs("5 secs"), + _10_secs("10 secs"), + _15_secs("15 secs"), + _30_secs("30 secs"), + _1_min("1 min"), + _2_mins("2 mins"), + _3_mins("3 mins"), + _5_mins("5 mins"), + _10_mins("10 mins"), + _15_mins("15 mins"), + _20_mins("20 mins"), + _30_mins("30 mins"), + _1_hour("1 hour"), + _4_hours("4 hours"), + _1_day("1 day"), + _1_week("1 week"), + _1_month("1 month"); + + private final String description; + + BarSize(final String description) { + this.description = description; + } + + @Override + public String toString() { + return description; } } - public static enum DurationUnit { - SECOND, DAY, WEEK, MONTH, YEAR; + public enum DurationUnit { + SECOND, DAY, WEEK, MONTH, YEAR, } - public static enum DeepType { + public enum DeepType { INSERT, UPDATE, DELETE; public static DeepType get( int ordinal) { @@ -245,7 +274,7 @@ public static DeepType get( int ordinal) { } } - public static enum DeepSide { + public enum DeepSide { SELL, BUY; public static DeepSide get( int ordinal) { @@ -256,7 +285,7 @@ public static DeepSide get( int ordinal) { public enum NewsType { UNKNOWN, BBS, LIVE_EXCH, DEAD_EXCH, HTML, POPUP_TEXT, POPUP_HTML; - static NewsType get( int ordinal) { + public static NewsType get( int ordinal) { return getEnum( ordinal, values() ); } } @@ -273,7 +302,7 @@ public enum SecIdType implements IApiEnum { None, CUSIP, SEDOL, ISIN, RIC; public static SecIdType get(String str) { - return str == null || str.length() == 0 ? None : valueOf( str); + return getValueOf(str, values(), None); } @Override public String getApiString() { @@ -282,7 +311,11 @@ public static SecIdType get(String str) { } public enum SecType implements IApiEnum { - None, STK, OPT, FUT, CASH, BOND, CFD, FOP, WAR, IOPT, FWD, BAG, IND, BILL, FUND, FIXED, SLB, NEWS, CMDTY, BSK, ICU, ICS; + None, STK, OPT, FUT, CONTFUT, CASH, BOND, CFD, FOP, WAR, IOPT, FWD, BAG, IND, BILL, FUND, FIXED, SLB, NEWS, CMDTY, BSK, ICU, ICS; + + public static SecType get(String str) { + return getValueOf(str, values(), None); + } @Override public String getApiString() { return this == None ? "" : super.toString(); @@ -290,7 +323,7 @@ public enum SecType implements IApiEnum { } public enum MktDataType { - Unknown, Realtime, Frozen; + Unknown, Realtime, Frozen, Delayed, DelayedFrozen; public static MktDataType get( int ordinal) { return getEnum( ordinal, values() ); @@ -301,7 +334,7 @@ public enum Method implements IApiEnum { None, EqualQuantity, AvailableEquity, NetLiq, PctChange; public static Method get( String str) { - return str == null || str.length() == 0 ? None : valueOf( str); + return getValueOf(str, values(), None); } @Override public String getApiString() { @@ -309,6 +342,15 @@ public static Method get( String str) { } } + public static & IApiEnum> T getValueOf( String v, T[] values, T defaultValue ) { + for( T currentEnum : values ) { + if( currentEnum.getApiString().equals(v) ) { + return currentEnum; + } + } + return defaultValue; + } + /** Lookup enum by ordinal. Use Enum.valueOf() to lookup by string. */ public static > T getEnum(int ordinal, T[] values) { if (ordinal == Integer.MAX_VALUE) { diff --git a/ref/client/UnderComp.java b/ref/client/UnderComp.java deleted file mode 100644 index 348fcca..0000000 --- a/ref/client/UnderComp.java +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.client; - -public class UnderComp { - - public int m_conId; - public double m_delta; - public double m_price; - - public UnderComp() { - m_conId = 0; - m_delta = 0; - m_price = 0; - } - - public boolean equals(Object p_other) { - - if (this == p_other) { - return true; - } - - if (p_other == null || !(p_other instanceof UnderComp)) { - return false; - } - - UnderComp l_theOther = (UnderComp)p_other; - - if (m_conId != l_theOther.m_conId) { - return false; - } - if (m_delta != l_theOther.m_delta) { - return false; - } - if (m_price != l_theOther.m_price) { - return false; - } - - return true; - } -} diff --git a/ref/client/Util.java b/ref/client/Util.java index 311af38..9a33203 100644 --- a/ref/client/Util.java +++ b/ref/client/Util.java @@ -1,12 +1,19 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.client; -import java.util.Vector; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; -public class Util { +import com.ib.controller.ApiController; +import com.ib.controller.ApiController.IContractDetailsHandler; +public class Util { public static boolean StringIsEmpty(String str) { return str == null || str.length() == 0; } @@ -23,8 +30,7 @@ public static int StringCompareIgnCase(String lhs, String rhs) { return NormalizeString(lhs).compareToIgnoreCase(NormalizeString(rhs)); } - public static boolean VectorEqualsUnordered(Vector lhs, Vector rhs) { - + public static boolean listsEqualUnordered(List lhs, List rhs) { if (lhs == rhs) return true; @@ -56,16 +62,50 @@ public static boolean VectorEqualsUnordered(Vector lhs, Vector rhs) { return false; } } - return true; } public static String IntMaxString(int value) { - return (value == Integer.MAX_VALUE) ? "" : "" + value; + return (value == Integer.MAX_VALUE) ? "" : String.valueOf(value); } public static String DoubleMaxString(double value) { - return (value == Double.MAX_VALUE) ? "" : "" + value; + return (value == Double.MAX_VALUE) ? "" : String.valueOf(value); } - + + public static String UnixMillisecondsToString(long milliseconds, String dateFormat){ + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(milliseconds); + return simpleDateFormat.format(calendar.getTime()); + } + + + public static List lookupContract(ApiController controller, Contract contract) { + if (controller == null) { + return new ArrayList<>(); + } + final CompletableFuture> future = new CompletableFuture<>(); + + controller.reqContractDetails(contract, new IContractDetailsHandler() { + + private final List contractDetails = new ArrayList<>(); + + @Override + public void contractDetails(List list) { + contractDetails.addAll(list); + future.complete(contractDetails); + } + }); + try { + return future.get(); + } catch (final InterruptedException e) { + e.printStackTrace(); + Thread.currentThread().interrupt(); + return new ArrayList<>(); + } catch (final ExecutionException e) { + e.printStackTrace(); + return new ArrayList<>(); + } + } } diff --git a/ref/client/VolumeCondition.java b/ref/client/VolumeCondition.java new file mode 100644 index 0000000..5cab623 --- /dev/null +++ b/ref/client/VolumeCondition.java @@ -0,0 +1,39 @@ +package com.ib.client; + +public class VolumeCondition extends ContractCondition { + + public static final OrderConditionType conditionType = OrderConditionType.Volume; + + protected VolumeCondition() { } + + @Override + public String toString() { + return toString(null); + } + + @Override + public String toString(ContractLookuper lookuper) { + return super.toString(lookuper); + } + + private int m_volume; + + public int volume() { + return m_volume; + } + + public void volume(int m_volume) { + this.m_volume = m_volume; + } + + @Override + protected String valueToString() { + return "" + m_volume; + } + + @Override + protected void valueFromString(String v) { + m_volume = Integer.parseInt(v); + } + +} \ No newline at end of file diff --git a/ref/contracts/ComboContract.java b/ref/contracts/ComboContract.java index 3f74b07..259d5ae 100644 --- a/ref/contracts/ComboContract.java +++ b/ref/contracts/ComboContract.java @@ -4,29 +4,21 @@ package com.ib.contracts; import com.ib.client.Contract; +import com.ib.client.Types.SecType; public class ComboContract extends Contract { - - public ComboContract(String symbol) { - m_symbol = symbol; - m_secType = "BAG"; - m_currency = "USD"; - m_exchange = "SMART"; - } - - public ComboContract(String symbol, String currency) { - m_symbol = symbol; - m_secType = "BAG"; - m_currency = currency; - m_exchange = "SMART"; - } - - public ComboContract(String symbol, String currency, String exchange) { - m_symbol = symbol; - m_secType = "BAG"; - m_currency = currency; - m_exchange = exchange; - } + public ComboContract(String symbol) { + this(symbol, "USD", "SMART"); + } + + public ComboContract(String symbol, String currency) { + this(symbol, currency, "SMART"); + } + + public ComboContract(String symbol, String currency, String exchange) { + symbol(symbol); + secType(SecType.BAG.name()); + currency(currency); + exchange(exchange); + } } - - diff --git a/ref/contracts/FutContract.java b/ref/contracts/FutContract.java index f9c7275..b94e534 100644 --- a/ref/contracts/FutContract.java +++ b/ref/contracts/FutContract.java @@ -4,22 +4,21 @@ package com.ib.contracts; import com.ib.client.Contract; +import com.ib.client.Types.SecType; public class FutContract extends Contract { + public FutContract(String symbol, String lastTradeDateOrContractMonth) { + symbol(symbol); + secType(SecType.FUT); + exchange("ONE"); + currency("USD"); + lastTradeDateOrContractMonth(lastTradeDateOrContractMonth); + } - public FutContract(String symbol, String expiry) { - m_symbol = symbol; - m_secType = "FUT"; - m_exchange = "ONE"; - m_currency = "USD"; - m_expiry = expiry; - } - - public FutContract(String symbol, String expiry, String currency) { - m_symbol = symbol; - m_secType = "FUT"; - m_currency = currency; - m_expiry = expiry; - } + public FutContract(String symbol, String lastTradeDateOrContractMonth, String currency) { + symbol(symbol); + secType(SecType.FUT.name()); + currency(currency); + lastTradeDateOrContractMonth(lastTradeDateOrContractMonth); + } } - diff --git a/ref/contracts/OptContract.java b/ref/contracts/OptContract.java index cfdab67..ecb41ce 100644 --- a/ref/contracts/OptContract.java +++ b/ref/contracts/OptContract.java @@ -4,30 +4,20 @@ package com.ib.contracts; import com.ib.client.Contract; +import com.ib.client.Types.SecType; public class OptContract extends Contract { + public OptContract(String symbol, String lastTradeDateOrContractMonth, double strike, String right) { + this(symbol, "SMART", lastTradeDateOrContractMonth, strike, right); + } - public OptContract(String symbol, String expiry, double strike, - String right) { - m_symbol = symbol; - m_secType = "OPT"; - m_exchange = "SMART"; - m_currency = "USD"; - m_expiry = expiry; - m_strike = strike; - m_right = right; - } - - public OptContract(String symbol, String exchange, - String expiry, double strike, String right) { - m_symbol = symbol; - m_secType = "OPT"; - m_exchange = exchange; - m_currency = "USD"; - m_expiry = expiry; - m_strike = strike; - m_right = right; - } - + public OptContract(String symbol, String exchange, String lastTradeDateOrContractMonth, double strike, String right) { + symbol(symbol); + secType(SecType.OPT.name()); + exchange(exchange); + currency("USD"); + lastTradeDateOrContractMonth(lastTradeDateOrContractMonth); + strike(strike); + right(right); + } } - diff --git a/ref/contracts/StkContract.java b/ref/contracts/StkContract.java index 47fa24a..b92209e 100644 --- a/ref/contracts/StkContract.java +++ b/ref/contracts/StkContract.java @@ -4,14 +4,13 @@ package com.ib.contracts; import com.ib.client.Contract; +import com.ib.client.Types.SecType; public class StkContract extends Contract { - - public StkContract(String symbol) { - m_symbol = symbol; - m_secType = "STK"; - m_exchange = "SMART"; - m_currency = "USD"; - } + public StkContract(String symbol) { + symbol(symbol); + secType(SecType.STK.name()); + exchange("SMART"); + currency("USD"); + } } - diff --git a/ref/controller/AdvisorUtil.java b/ref/controller/AdvisorUtil.java index 351d62e..a28c538 100644 --- a/ref/controller/AdvisorUtil.java +++ b/ref/controller/AdvisorUtil.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.controller; @@ -7,15 +7,16 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.List; +import com.ib.client.Types.Method; import com.ib.controller.Profile.Allocation; import com.ib.controller.Profile.Type; -import com.ib.controller.Types.Method; public class AdvisorUtil { - static ArrayList getGroups( String xml) { + static List getGroups( String xml) { try { return getGroups_( xml); } catch (IOException e) { @@ -24,8 +25,8 @@ static ArrayList getGroups( String xml) { } } - static ArrayList getGroups_( String xml) throws IOException { - ArrayList list = new ArrayList(); + static List getGroups_( String xml) throws IOException { + List list = new ArrayList<>(); Group group = null; @@ -86,13 +87,17 @@ else if (line.equals( "")) { group.addAccount( getVal( line) ); } break; + + // should not happen + default: + break; } } return list; } - static ArrayList getProfiles( String xml) { + static List getProfiles( String xml) { try { return getProfiles_( xml); } catch (IOException e) { @@ -101,8 +106,8 @@ static ArrayList getProfiles( String xml) { } } - static ArrayList getProfiles_( String xml) throws IOException { - ArrayList list = new ArrayList(); + static List getProfiles_( String xml) throws IOException { + List list = new ArrayList<>(); Profile profile = null; Allocation alloc = null; @@ -189,13 +194,17 @@ else if (line.equals( "") ) { err( line); } break; + + // should not happen + default: + break; } } return list; } - static ArrayList getAliases( String xml) { + static List getAliases( String xml) { try { return getAliases_( xml); } catch (IOException e) { @@ -204,8 +213,8 @@ static ArrayList getAliases( String xml) { } } - static ArrayList getAliases_( String xml) throws IOException { - ArrayList list = new ArrayList(); + static List getAliases_( String xml) throws IOException { + List list = new ArrayList<>(); Alias alias = null; @@ -253,6 +262,10 @@ else if (line.equals( "")) { err( line); } break; + + // should not happen + default: + break; } } @@ -271,29 +284,25 @@ private static void err(String line) { public static void main(String[] args) { - String str1 = "\n\n \n Group 1\n \n DU109949\n DU109950\n DU110a156\n DU110157\n DU110158\n \n AvailableEquity\n \n \n Group 2\n \n DU109950\n DU110156\n DU110157\n \n AvailableEquity\n \n\n"; - ArrayList groups = getGroups( str1); - - String str2 = "\n\n \n High Risk\n 1\n \n \n DU110157\n 90.0\n O\n \n \n DU110158\n 10.0\n O\n \n \n \n \n Profile\n 2\n \n \n DU109949\n 1.0\n O\n \n \n \n\n"; - ArrayList profiles = getProfiles( str2); + String str = "\n\n \n DF109948\n DF109948\n \n \n DU109949\n DU109949\n \n \n DU109950\n DU109950\n \n \n DU110156\n DU110156\n \n \n DU110157\n DU110157\n \n \n DU110158\n DU110158\n \n\n\n"; + List aliases = getAliases(str); - String str3 = "\n\n \n DF109948\n DF109948\n \n \n DU109949\n DU109949\n \n \n DU109950\n DU109950\n \n \n DU110156\n DU110156\n \n \n DU110157\n DU110157\n \n \n DU110158\n DU110158\n \n\n\n"; - ArrayList aliases = getAliases( str3); - - AdvisorUtil.err( aliases.toString() ); + if (aliases != null) { + AdvisorUtil.err(aliases.toString()); + } } - public static String getGroupsXml(ArrayList groups) { + public static String getGroupsXml(List groups) { StringBuilder buf = new StringBuilder(); buf.append( "\n"); buf.append( "\n"); for( Group group : groups) { buf.append( "\n"); - buf.append( String.format( "%s\n", group.name() ) ); - buf.append( String.format( "%s\n", group.defaultMethod() ) ); + buf.append( String.format( "%s%n", group.name() ) ); + buf.append( String.format( "%s%n", group.defaultMethod() ) ); buf.append( ""); for( String acct : group.accounts() ) { - buf.append( String.format( "%s\n", acct) ); + buf.append( String.format( "%s%n", acct) ); } buf.append( "\n"); buf.append( "\n"); @@ -302,19 +311,19 @@ public static String getGroupsXml(ArrayList groups) { return buf.toString(); } - public static String getProfilesXml(ArrayList profiles) { + public static String getProfilesXml(List profiles) { StringBuilder buf = new StringBuilder(); buf.append( "\n"); buf.append( "\n"); for( Profile profile : profiles) { buf.append( "\n"); - buf.append( String.format( "%s\n", profile.name() ) ); - buf.append( String.format( "%s\n", profile.type().ordinal() ) ); + buf.append( String.format( "%s%n", profile.name() ) ); + buf.append( String.format( "%s%n", profile.type().ordinal() ) ); buf.append( "\n"); for( Allocation alloc : profile.allocations() ) { buf.append( "\n"); - buf.append( String.format( "%s\n", alloc.account() ) ); - buf.append( String.format( "%s\n", alloc.amount() ) ); + buf.append( String.format( "%s%n", alloc.account() ) ); + buf.append( String.format( "%s%n", alloc.amount() ) ); buf.append( "\n"); } buf.append( "\n"); diff --git a/ref/controller/ApiConnection.java b/ref/controller/ApiConnection.java index 1a5a0a7..9dd5446 100644 --- a/ref/controller/ApiConnection.java +++ b/ref/controller/ApiConnection.java @@ -4,24 +4,16 @@ package com.ib.controller; -import java.io.DataInputStream; -import java.io.FilterInputStream; -import java.io.FilterOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.net.Socket; +import java.nio.charset.StandardCharsets; -import com.ib.client.AnyWrapper; -import com.ib.client.Builder; +import com.ib.client.Contract; import com.ib.client.EClientErrors; import com.ib.client.EClientSocket; -import com.ib.client.EReader; -import com.ib.client.TagValue; -import com.ib.controller.Types.AlgoStrategy; -import com.ib.controller.Types.HedgeType; -import com.ib.controller.Types.SecType; +import com.ib.client.EJavaSignal; +import com.ib.client.EMessage; +import com.ib.client.EWrapper; +import com.ib.client.Order; // NOTE: TWS 936 SERVER_VERSION is 67. @@ -35,45 +27,43 @@ public interface ILogger { private final ILogger m_inLogger; private final ILogger m_outLogger; + private static final EJavaSignal m_signal = new EJavaSignal(); - public ApiConnection(AnyWrapper wrapper, ILogger inLogger, ILogger outLogger) { - super( wrapper); + public ApiConnection(EWrapper wrapper, ILogger inLogger, ILogger outLogger) { + super( wrapper, m_signal); m_inLogger = inLogger; m_outLogger = outLogger; } - @Override public synchronized void eConnect(Socket socket, int clientId) throws IOException { - super.eConnect(socket, clientId); + @Override + protected void sendMsg(EMessage msg) throws IOException { + // TODO Auto-generated method stub + super.sendMsg(msg); + + byte[] buf = msg.getRawData(); + + m_outLogger.log(new String(buf, 0, buf.length, StandardCharsets.UTF_8)); + } - // replace the output stream with one that logs all data to m_outLogger - if (isConnected()) { - try { - Field realOsField = FilterOutputStream.class.getDeclaredField( "out"); - realOsField.setAccessible( true); - OutputStream realOs = (OutputStream)realOsField.get( m_dos); - realOsField.set( m_dos, new MyOS( realOs) ); - } - catch( Exception e) { - e.printStackTrace(); - } - } + @Override + public int readInt() throws IOException { + int c = super.readInt(); + + m_inLogger.log( String.valueOf( (char)c) ); + + return c; } - /** Replace the input stream with ont that logs all data to m_inLogger. */ - @Override public EReader createReader(EClientSocket socket, DataInputStream dis) { - try { - Field realIsField = FilterInputStream.class.getDeclaredField( "in"); - realIsField.setAccessible( true); - InputStream realIs = (InputStream)realIsField.get( dis); - realIsField.set( dis, new MyIS( realIs) ); - } - catch( Exception e) { - e.printStackTrace(); - } - return super.createReader(socket, dis); + @Override + public int read(byte[] buf, int off, int len) throws IOException { + int n = super.read(buf, off, len); + + m_inLogger.log(new String(buf, 0, n, StandardCharsets.UTF_8)); + + return n; } - public synchronized void placeOrder(NewContract contract, NewOrder order) { + public synchronized void placeOrder(Contract contract, Order order) { // not connected? if( !isConnected() ) { notConnected(); @@ -86,252 +76,6 @@ public synchronized void placeOrder(NewContract contract, NewOrder order) { return; } - Builder b = new Builder(); - - int VERSION = 41; - - // send place order msg - try { - b.send( PLACE_ORDER); - b.send( VERSION); - b.send( order.orderId() ); - b.send( contract.conid() ); - b.send( contract.symbol()); - b.send( contract.secType() ); - b.send( contract.expiry()); - b.send( contract.strike()); - b.send( contract.right().getApiString() ); - b.send( contract.multiplier() ); - b.send( contract.exchange() ); - b.send( contract.primaryExch() ); - b.send( contract.currency() ); - b.send( contract.localSymbol() ); - if (m_serverVersion >= MIN_SERVER_VER_TRADING_CLASS) { - b.send(contract.tradingClass() ); - } - b.send( contract.secIdType() ); - b.send( contract.secId() ); - b.send( order.action() ); - b.send( order.totalQuantity() ); - b.send( order.orderType() ); - b.send( order.lmtPrice() ); - b.send( order.auxPrice() ); - b.send( order.tif() ); - b.send( order.ocaGroup() ); - b.send( order.account() ); - b.send( ""); // open/close - b.send( ""); // origin - b.send( order.orderRef() ); - b.send( order.transmit() ); - b.send( order.parentId() ); - b.send( order.blockOrder() ); - b.send( order.sweepToFill() ); - b.send( order.displaySize() ); - b.send( order.triggerMethod() ); - b.send( order.outsideRth() ); - b.send( order.hidden() ); - - // send combo legs for BAG orders - if(contract.secType() == SecType.BAG) { - b.send( contract.comboLegs().size()); - - for (NewComboLeg leg : contract.comboLegs() ) { - b.send( leg.conid() ); - b.send( leg.ratio() ); - b.send( leg.action().getApiString() ); - b.send( leg.exchange() ); - b.send( leg.openClose().getApiString() ); - b.send( leg.shortSaleSlot() ); - b.send( leg.designatedLocation() ); - b.send( leg.exemptCode() ); - } - - b.send( order.orderComboLegs().size()); - for (Double orderComboLeg : order.orderComboLegs() ) { - b.send( orderComboLeg); - } - - b.send( order.smartComboRoutingParams().size() ); - for (TagValue tagValue : order.smartComboRoutingParams() ) { - b.send( tagValue.m_tag); - b.send( tagValue.m_value); - } - } - - b.send( ""); // obsolete field - b.send( order.discretionaryAmt() ); - b.send( order.goodAfterTime() ); - b.send( order.goodTillDate() ); - b.send( order.faGroup()); - b.send( order.faMethod() ); - b.send( order.faPercentage() ); - b.send( order.faProfile()); - b.send( 0); // short sale slot - b.send( ""); // designatedLocation - b.send( ""); // exemptCode - b.send( order.ocaType() ); - b.send( order.rule80A() ); - b.send( ""); // settlingFirm - b.send( order.allOrNone() ); - b.send( order.minQty() ); - b.send( order.percentOffset() ); - b.send( order.eTradeOnly() ); - b.send( order.firmQuoteOnly() ); - b.send( order.nbboPriceCap() ); - b.send( order.auctionStrategy() ); - b.send( order.startingPrice() ); - b.send( order.stockRefPrice() ); - b.send( order.delta() ); - b.send( order.stockRangeLower() ); - b.send( order.stockRangeUpper() ); - b.send( order.overridePercentageConstraints() ); - b.send( order.volatility() ); - b.send( order.volatilityType() ); - b.send( order.deltaNeutralOrderType() ); - b.send( order.deltaNeutralAuxPrice() ); - - if (order.deltaNeutralOrderType() != OrderType.None) { - b.send( order.deltaNeutralConId() ); - b.send( ""); //deltaNeutralSettlingFirm - b.send( ""); //deltaNeutralClearingAccount - b.send( ""); //deltaNeutralClearingIntent - b.send( ""); //deltaNeutralOpenClose - b.send( ""); //deltaNeutralShortSale - b.send( ""); //deltaNeutralShortSaleSlot - b.send( ""); //deltaNeutralDesignatedLocation - } - - b.send( order.continuousUpdate() ); - b.send( order.referencePriceType() ); - b.send( order.trailStopPrice() ); - b.send( order.trailingPercent() ); - b.send( order.scaleInitLevelSize() ); - b.send( order.scaleSubsLevelSize() ); - b.send( order.scalePriceIncrement() ); - - if (order.scalePriceIncrement() != 0 && order.scalePriceIncrement() != Double.MAX_VALUE) { - b.send( order.scalePriceAdjustValue() ); - b.send( order.scalePriceAdjustInterval() ); - b.send( order.scaleProfitOffset() ); - b.send( order.scaleAutoReset() ); - b.send( order.scaleInitPosition() ); - b.send( order.scaleInitFillQty() ); - b.send( order.scaleRandomPercent() ); - } - - if (m_serverVersion >= MIN_SERVER_VER_SCALE_TABLE) { - b.send( order.scaleTable() ); - b.send( ""); // active start time - b.send( ""); // active stop time - } - - b.send( order.hedgeType() ); - if (order.hedgeType() != HedgeType.None) { - b.send( order.hedgeParam() ); - } - - b.send( order.optOutSmartRouting() ); - b.send( "");//clearingAccount - b.send( "");//clearingIntent - b.send( order.notHeld() ); - - b.send( contract.underComp() != null); - if (contract.underComp() != null) { - b.send( contract.underComp().conid() ); - b.send( contract.underComp().delta() ); - b.send( contract.underComp().price() ); - } - - b.send( order.algoStrategy() ); - if( order.algoStrategy() != AlgoStrategy.None) { - b.send( order.algoParams().size() ); - for( TagValue tagValue : order.algoParams() ) { - b.send( tagValue.m_tag); - b.send( tagValue.m_value); - } - } - - b.send( order.whatIf() ); - - m_dos.write( b.getBytes() ); - } - catch( Exception e) { - e.printStackTrace(); - error( order.orderId(), 512, "Order sending error - " + e); - close(); - } - } - - /** An output stream that forks all writes to the output logger. */ - private class MyOS extends OutputStream { - final OutputStream m_os; - - MyOS( OutputStream os) { - m_os = os; - } - - @Override public void write(byte[] b) throws IOException { - m_os.write( b); - log( new String( b) ); - } - - @Override public synchronized void write(byte[] b, int off, int len) throws IOException { - m_os.write(b, off, len); - log( new String( b, off, len) ); - } - - @Override public synchronized void write(int b) throws IOException { - m_os.write(b); - log( String.valueOf( (char)b) ); - } - - @Override public void flush() throws IOException { - m_os.flush(); - } - - @Override public void close() throws IOException { - m_os.close(); - m_outLogger.log( ""); - } - - void log( String str) { - m_outLogger.log( str.replace( EOL, LOG_EOL) ); - } - } - - /** An input stream that forks all reads to the input logger. */ - private class MyIS extends InputStream { - InputStream m_is; - - MyIS( InputStream is) { - m_is = is; - } - - @Override public int read() throws IOException { - int c = m_is.read(); - log( String.valueOf( (char)c) ); - return c; - } - - @Override public int read(byte[] b) throws IOException { - int n = m_is.read(b); - log( new String( b, 0, n) ); - return n; - } - - @Override public int read(byte[] b, int off, int len) throws IOException { - int n = m_is.read(b, off, len); - log( new String( b, 0, n) ); - return n; - } - - @Override public void close() throws IOException { - super.close(); - log( ""); - } - - void log( String str) { - m_inLogger.log( str.replace( EOL, LOG_EOL) ); - } - } + placeOrder(order.orderId(), contract, order); + } } diff --git a/ref/controller/ApiController.java b/ref/controller/ApiController.java index 53b01ec..94558e4 100644 --- a/ref/controller/ApiController.java +++ b/ref/controller/ApiController.java @@ -1,35 +1,30 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.controller; +import java.io.IOException; import java.util.ArrayList; -import java.util.Date; +import java.util.Collections; +import java.util.GregorianCalendar; import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.StringTokenizer; -import com.ib.client.CommissionReport; -import com.ib.client.Contract; -import com.ib.client.ContractDetails; -import com.ib.client.EWrapper; -import com.ib.client.Execution; -import com.ib.client.ExecutionFilter; -import com.ib.client.Order; -import com.ib.client.OrderState; -import com.ib.client.ScannerSubscription; -import com.ib.client.UnderComp; +import com.ib.client.*; +import com.ib.client.Types.BarSize; +import com.ib.client.Types.DeepSide; +import com.ib.client.Types.DeepType; +import com.ib.client.Types.DurationUnit; +import com.ib.client.Types.ExerciseType; +import com.ib.client.Types.FADataType; +import com.ib.client.Types.FundamentalType; +import com.ib.client.Types.NewsType; +import com.ib.client.Types.WhatToShow; import com.ib.controller.ApiConnection.ILogger; -import com.ib.controller.Types.BarSize; -import com.ib.controller.Types.DeepSide; -import com.ib.controller.Types.DeepType; -import com.ib.controller.Types.DurationUnit; -import com.ib.controller.Types.ExerciseType; -import com.ib.controller.Types.FADataType; -import com.ib.controller.Types.FundamentalType; -import com.ib.controller.Types.MktDataType; -import com.ib.controller.Types.NewsType; -import com.ib.controller.Types.WhatToShow; public class ApiController implements EWrapper { private ApiConnection m_client; @@ -44,27 +39,47 @@ public class ApiController implements EWrapper { private IScannerHandler m_scannerHandler; private ITimeHandler m_timeHandler; private IBulletinHandler m_bulletinHandler; - private final HashMap m_contractDetailsMap = new HashMap(); - private final HashMap m_optionCompMap = new HashMap(); - private final HashMap m_efpMap = new HashMap(); - private final HashMap m_topMktDataMap = new HashMap(); - private final HashMap m_deepMktDataMap = new HashMap(); - private final HashMap m_scannerMap = new HashMap(); - private final HashMap m_realTimeBarMap = new HashMap(); - private final HashMap m_historicalDataMap = new HashMap(); - private final HashMap m_fundMap = new HashMap(); - private final HashMap m_orderHandlers = new HashMap(); - private final HashMap m_acctSummaryHandlers = new HashMap(); - private final HashMap m_mktValSummaryHandlers = new HashMap(); - private final ConcurrentHashSet m_positionHandlers = new ConcurrentHashSet(); - private final ConcurrentHashSet m_accountHandlers = new ConcurrentHashSet(); - private final ConcurrentHashSet m_liveOrderHandlers = new ConcurrentHashSet(); + private final Map m_contractDetailsMap = new HashMap<>(); + private final Map m_optionCompMap = new HashMap<>(); + private final Map m_efpMap = new HashMap<>(); + private final Map m_topMktDataMap = new HashMap<>(); + private final Map m_deepMktDataMap = new HashMap<>(); + private final Map m_scannerMap = new HashMap<>(); + private final Map m_realTimeBarMap = new HashMap<>(); + private final Map m_historicalDataMap = new HashMap<>(); + private final Map m_headTimestampMap = new HashMap<>(); + private final Map m_histogramDataMap = new HashMap<>(); + private final Map m_fundMap = new HashMap<>(); + private final Map m_orderHandlers = new HashMap<>(); + private final Map m_acctSummaryHandlers = new HashMap<>(); + private final Map m_mktValSummaryHandlers = new HashMap<>(); + private final Set m_positionHandlers = new ConcurrentHashSet<>(); + private final Set m_accountHandlers = new ConcurrentHashSet<>(); + private final Set m_liveOrderHandlers = new ConcurrentHashSet<>(); + private final Map m_positionMultiMap = new HashMap<>(); + private final Map m_accountUpdateMultiMap = new HashMap<>(); + private final Map m_secDefOptParamsReqMap = new HashMap<>(); + private final Map m_softDollarTiersReqMap = new HashMap<>(); + private final Set m_familyCodesHandlers = new ConcurrentHashSet<>(); + private final Map m_symbolSamplesHandlerMap = new HashMap<>(); + private final Set m_mktDepthExchangesHandlers = new ConcurrentHashSet<>(); + private final Map m_tickNewsHandlerMap = new HashMap<>(); + private final Map m_smartComponentsHandler = new HashMap<>(); + private final Set m_newsProvidersHandlers = new ConcurrentHashSet<>(); + private final Map m_newsArticleHandlerMap = new HashMap<>(); + private final Map m_historicalNewsHandlerMap = new HashMap<>(); + private final Set m_marketRuleHandlers = new ConcurrentHashSet<>(); + private final Map m_PnLMap = new HashMap<>(); + private final Map m_PnLSingleMap = new HashMap<>(); + private boolean m_connected = false; + + public ApiConnection client() { return m_client; } // ---------------------------------------- Constructor and Connection handling ---------------------------------------- public interface IConnectionHandler { void connected(); void disconnected(); - void accountList(ArrayList list); + void accountList(List list); void error(Exception e); void message(int id, int errorCode, String errorMsg); void show(String string); @@ -76,20 +91,45 @@ public ApiController( IConnectionHandler handler, ILogger inLogger, ILogger outL m_inLogger = inLogger; m_outLogger = outLogger; } - - public void connect( String host, int port, int clientId) { - m_client.eConnect(host, port, clientId); - sendEOM(); - } + + private void startMsgProcessingThread() { + final EReaderSignal signal = new EJavaSignal(); + final EReader reader = new EReader(client(), signal); + + reader.start(); + + new Thread(() -> { + while (client().isConnected()) { + signal.waitForSignal(); + try { + reader.processMsgs(); + } catch (IOException e) { + error(e); + } + } + }).start(); + } + + public void connect( String host, int port, int clientId, String connectionOpts ) { + if(!m_client.isConnected()){ + m_client.eConnect(host, port, clientId); + startMsgProcessingThread(); + sendEOM(); + } + } public void disconnect() { + if (!checkConnection()) + return; + m_client.eDisconnect(); m_connectionHandler.disconnected(); + m_connected = false; sendEOM(); } @Override public void managedAccounts(String accounts) { - ArrayList list = new ArrayList(); + List list = new ArrayList<>(); for( StringTokenizer st = new StringTokenizer( accounts, ","); st.hasMoreTokens(); ) { list.add( st.nextToken() ); } @@ -100,6 +140,7 @@ public void disconnect() { @Override public void nextValidId(int orderId) { m_orderId = orderId; m_reqId = m_orderId + 10000000; // let order id's not collide with other request id's + m_connected = true; if (m_connectionHandler != null) { m_connectionHandler.connected(); } @@ -134,25 +175,29 @@ public void disconnect() { @Override public void connectionClosed() { m_connectionHandler.disconnected(); + m_connected = false; } // ---------------------------------------- Account and portfolio updates ---------------------------------------- public interface IAccountHandler { - public void accountValue(String account, String key, String value, String currency); - public void accountTime(String timeStamp); - public void accountDownloadEnd(String account); - public void updatePortfolio(Position position); + void accountValue(String account, String key, String value, String currency); + void accountTime(String timeStamp); + void accountDownloadEnd(String account); + void updatePortfolio(Position position); } public void reqAccountUpdates(boolean subscribe, String acctCode, IAccountHandler handler) { - m_accountHandlers.add( handler); + if (!checkConnection()) + return; + + m_accountHandlers.add( handler); m_client.reqAccountUpdates(subscribe, acctCode); sendEOM(); } @Override public void updateAccountValue(String tag, String value, String currency, String account) { - if (tag.equals( "Currency") ) { // ignore this, it is useless + if ("Currency".equals(tag)) { // ignore this, it is useless return; } @@ -176,9 +221,8 @@ public void reqAccountUpdates(boolean subscribe, String acctCode, IAccountHandle recEOM(); } - @Override public void updatePortfolio(Contract contractIn, int positionIn, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, String account) { - NewContract contract = new NewContract( contractIn); - contract.exchange( contractIn.m_primaryExch); + @Override public void updatePortfolio(Contract contract, double positionIn, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, String account) { + contract.exchange( contract.primaryExch()); Position position = new Position( contract, account, positionIn, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL); for( IAccountHandler handler : m_accountHandlers) { @@ -200,6 +244,9 @@ public interface IMarketValueSummaryHandler { /** @param group pass "All" to get data for all accounts */ public void reqAccountSummary(String group, AccountSummaryTag[] tags, IAccountSummaryHandler handler) { + if (!checkConnection()) + return; + StringBuilder sb = new StringBuilder(); for (AccountSummaryTag tag : tags) { if (sb.length() > 0) { @@ -214,7 +261,14 @@ public void reqAccountSummary(String group, AccountSummaryTag[] tags, IAccountSu sendEOM(); } + private boolean isConnected() { + return m_connected; + } + public void cancelAccountSummary(IAccountSummaryHandler handler) { + if (!checkConnection()) + return; + Integer reqId = getAndRemoveKey( m_acctSummaryHandlers, handler); if (reqId != null) { m_client.cancelAccountSummary( reqId); @@ -223,6 +277,9 @@ public void cancelAccountSummary(IAccountSummaryHandler handler) { } public void reqMarketValueSummary(String group, IMarketValueSummaryHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_mktValSummaryHandlers.put( reqId, handler); m_client.reqAccountSummary( reqId, group, "$LEDGER"); @@ -230,6 +287,9 @@ public void reqMarketValueSummary(String group, IMarketValueSummaryHandler handl } public void cancelMarketValueSummary(IMarketValueSummaryHandler handler) { + if (!checkConnection()) + return; + Integer reqId = getAndRemoveKey( m_mktValSummaryHandlers, handler); if (reqId != null) { m_client.cancelAccountSummary( reqId); @@ -238,7 +298,7 @@ public void cancelMarketValueSummary(IMarketValueSummaryHandler handler) { } @Override public void accountSummary( int reqId, String account, String tag, String value, String currency) { - if (tag.equals( "Currency") ) { // ignore this, it is useless + if ("Currency".equals(tag)) { // ignore this, it is useless return; } @@ -271,24 +331,29 @@ public void cancelMarketValueSummary(IMarketValueSummaryHandler handler) { // ---------------------------------------- Position handling ---------------------------------------- public interface IPositionHandler { - void position( String account, NewContract contract, int position, double avgCost); + void position( String account, Contract contract, double pos, double avgCost); void positionEnd(); } public void reqPositions( IPositionHandler handler) { + if (!checkConnection()) + return; + m_positionHandlers.add( handler); m_client.reqPositions(); sendEOM(); } public void cancelPositions( IPositionHandler handler) { - m_positionHandlers.add( handler); + if (!checkConnection()) + return; + + m_positionHandlers.remove( handler); m_client.cancelPositions(); sendEOM(); } - @Override public void position(String account, Contract contractIn, int pos, double avgCost) { - NewContract contract = new NewContract( contractIn); + @Override public void position(String account, Contract contract, double pos, double avgCost) { for (IPositionHandler handler : m_positionHandlers) { handler.position( account, contract, pos, avgCost); } @@ -304,13 +369,16 @@ public void cancelPositions( IPositionHandler handler) { // ---------------------------------------- Contract Details ---------------------------------------- public interface IContractDetailsHandler { - void contractDetails(ArrayList list); + void contractDetails(List list); } - public void reqContractDetails( NewContract contract, final IContractDetailsHandler processor) { - final ArrayList list = new ArrayList(); + public void reqContractDetails( Contract contract, final IContractDetailsHandler processor) { + if (!checkConnection()) + return; + + final List list = new ArrayList<>(); internalReqContractDetails( contract, new IInternalHandler() { - @Override public void contractDetails(NewContractDetails data) { + @Override public void contractDetails(ContractDetails data) { list.add( data); } @Override public void contractDetailsEnd() { @@ -321,21 +389,37 @@ public void reqContractDetails( NewContract contract, final IContractDetailsHand } private interface IInternalHandler { - void contractDetails(NewContractDetails data); + void contractDetails(ContractDetails data); void contractDetailsEnd(); } - private void internalReqContractDetails( NewContract contract, IInternalHandler processor) { + private void internalReqContractDetails( Contract contract, final IInternalHandler processor) { int reqId = m_reqId++; m_contractDetailsMap.put( reqId, processor); - m_client.reqContractDetails(reqId, contract.getContract() ); + m_orderHandlers.put(reqId, new IOrderHandler() { public void handle(int errorCode, String errorMsg) { processor.contractDetailsEnd();} + + @Override + public void orderState(OrderState orderState) { + // TODO Auto-generated method stub + + } + + @Override + public void orderStatus(OrderStatus status, double filled, + double remaining, double avgFillPrice, long permId, + int parentId, double lastFillPrice, int clientId, String whyHeld) { + // TODO Auto-generated method stub + + } }); + + m_client.reqContractDetails(reqId, contract); sendEOM(); } @Override public void contractDetails(int reqId, ContractDetails contractDetails) { IInternalHandler handler = m_contractDetailsMap.get( reqId); if (handler != null) { - handler.contractDetails( new NewContractDetails( contractDetails) ); + handler.contractDetails(contractDetails); } else { show( "Error: no contract details handler for reqId " + reqId); @@ -346,7 +430,7 @@ private void internalReqContractDetails( NewContract contract, IInternalHandler @Override public void bondContractDetails(int reqId, ContractDetails contractDetails) { IInternalHandler handler = m_contractDetailsMap.get( reqId); if (handler != null) { - handler.contractDetails(new NewContractDetails( contractDetails) ); + handler.contractDetails(contractDetails); } else { show( "Error: no bond contract details handler for reqId " + reqId); @@ -367,59 +451,74 @@ private void internalReqContractDetails( NewContract contract, IInternalHandler // ---------------------------------------- Top Market Data handling ---------------------------------------- public interface ITopMktDataHandler { - void tickPrice(NewTickType tickType, double price, int canAutoExecute); - void tickSize(NewTickType tickType, int size); - void tickString(NewTickType tickType, String value); + void tickPrice(TickType tickType, double price, TickAttr attribs); + void tickSize(TickType tickType, int size); + void tickString(TickType tickType, String value); void tickSnapshotEnd(); - void marketDataType(MktDataType marketDataType); + void marketDataType(int marketDataType); + void tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions); } public interface IEfpHandler extends ITopMktDataHandler { - void tickEFP(int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureExpiry, double dividendImpact, double dividendsToExpiry); + void tickEFP(int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate); } public interface IOptHandler extends ITopMktDataHandler { - void tickOptionComputation( NewTickType tickType, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice); + void tickOptionComputation( TickType tickType, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice); } public static class TopMktDataAdapter implements ITopMktDataHandler { - @Override public void tickPrice(NewTickType tickType, double price, int canAutoExecute) { + @Override public void tickPrice(TickType tickType, double price, TickAttr attribs) { } - @Override public void tickSize(NewTickType tickType, int size) { + @Override public void tickSize(TickType tickType, int size) { } - @Override public void tickString(NewTickType tickType, String value) { + @Override public void tickString(TickType tickType, String value) { } @Override public void tickSnapshotEnd() { } - @Override public void marketDataType(MktDataType marketDataType) { + @Override public void marketDataType(int marketDataType) { + } + @Override public void tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions) { } } - public void reqTopMktData(NewContract contract, String genericTickList, boolean snapshot, ITopMktDataHandler handler) { + public void reqTopMktData(Contract contract, String genericTickList, boolean snapshot, boolean regulatorySnapshot, ITopMktDataHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_topMktDataMap.put( reqId, handler); - m_client.reqMktData( reqId, contract.getContract(), genericTickList, snapshot); + m_client.reqMktData( reqId, contract, genericTickList, snapshot, regulatorySnapshot, Collections.emptyList() ); sendEOM(); } - public void reqOptionMktData(NewContract contract, String genericTickList, boolean snapshot, IOptHandler handler) { + public void reqOptionMktData(Contract contract, String genericTickList, boolean snapshot, boolean regulatorySnapshot, IOptHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_topMktDataMap.put( reqId, handler); m_optionCompMap.put( reqId, handler); - m_client.reqMktData( reqId, contract.getContract(), genericTickList, snapshot); + m_client.reqMktData( reqId, contract, genericTickList, snapshot, regulatorySnapshot, Collections.emptyList() ); sendEOM(); } - public void reqEfpMktData(NewContract contract, String genericTickList, boolean snapshot, IEfpHandler handler) { + public void reqEfpMktData(Contract contract, String genericTickList, boolean snapshot, boolean regulatorySnapshot, IEfpHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_topMktDataMap.put( reqId, handler); m_efpMap.put( reqId, handler); - m_client.reqMktData( reqId, contract.getContract(), genericTickList, snapshot); + m_client.reqMktData( reqId, contract, genericTickList, snapshot, regulatorySnapshot, Collections.emptyList() ); sendEOM(); } public void cancelTopMktData( ITopMktDataHandler handler) { - Integer reqId = getAndRemoveKey( m_topMktDataMap, handler); + if (!checkConnection()) + return; + + Integer reqId = getAndRemoveKey( m_topMktDataMap, handler); if (reqId != null) { m_client.cancelMktData( reqId); } @@ -439,15 +538,35 @@ public void cancelEfpMktData( IEfpHandler handler) { getAndRemoveKey( m_efpMap, handler); } - public void reqMktDataType( MktDataType type) { - m_client.reqMarketDataType( type.ordinal() ); + public void reqMktDataType( int mktDataType) { + if (!checkConnection()) + return; + + m_client.reqMarketDataType( mktDataType); sendEOM(); + switch(mktDataType){ + case MarketDataType.REALTIME: + show( "Frozen, Delayed and Delayed-Frozen market data types are disabled"); + break; + case MarketDataType.FROZEN: + show( "Frozen market data type is enabled"); + break; + case MarketDataType.DELAYED: + show( "Delayed market data type is enabled, Delayed-Frozen market data type is disabled"); + break; + case MarketDataType.DELAYED_FROZEN: + show( "Delayed and Delayed-Frozen market data types are enabled"); + break; + default: + show( "Unknown market data type"); + break; + } } - @Override public void tickPrice(int reqId, int tickType, double price, int canAutoExecute) { + @Override public void tickPrice(int reqId, int tickType, double price, TickAttr attribs) { ITopMktDataHandler handler = m_topMktDataMap.get( reqId); if (handler != null) { - handler.tickPrice( NewTickType.get( tickType), price, canAutoExecute); + handler.tickPrice( TickType.get( tickType), price, attribs); } recEOM(); } @@ -455,7 +574,7 @@ public void reqMktDataType( MktDataType type) { @Override public void tickGeneric(int reqId, int tickType, double value) { ITopMktDataHandler handler = m_topMktDataMap.get( reqId); if (handler != null) { - handler.tickPrice( NewTickType.get( tickType), value, 0); + handler.tickPrice( TickType.get( tickType), value, new TickAttr()); } recEOM(); } @@ -463,7 +582,7 @@ public void reqMktDataType( MktDataType type) { @Override public void tickSize(int reqId, int tickType, int size) { ITopMktDataHandler handler = m_topMktDataMap.get( reqId); if (handler != null) { - handler.tickSize( NewTickType.get( tickType), size); + handler.tickSize( TickType.get( tickType), size); } recEOM(); } @@ -471,15 +590,15 @@ public void reqMktDataType( MktDataType type) { @Override public void tickString(int reqId, int tickType, String value) { ITopMktDataHandler handler = m_topMktDataMap.get( reqId); if (handler != null) { - handler.tickString( NewTickType.get( tickType), value); + handler.tickString( TickType.get( tickType), value); } recEOM(); } - @Override public void tickEFP(int reqId, int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureExpiry, double dividendImpact, double dividendsToExpiry) { + @Override public void tickEFP(int reqId, int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate) { IEfpHandler handler = m_efpMap.get( reqId); if (handler != null) { - handler.tickEFP( tickType, basisPoints, formattedBasisPoints, impliedFuture, holdDays, futureExpiry, dividendImpact, dividendsToExpiry); + handler.tickEFP( tickType, basisPoints, formattedBasisPoints, impliedFuture, holdDays, futureLastTradeDate, dividendImpact, dividendsToLastTradeDate); } recEOM(); } @@ -495,7 +614,7 @@ public void reqMktDataType( MktDataType type) { @Override public void marketDataType(int reqId, int marketDataType) { ITopMktDataHandler handler = m_topMktDataMap.get( reqId); if (handler != null) { - handler.marketDataType( MktDataType.get( marketDataType) ); + handler.marketDataType( marketDataType ); } recEOM(); } @@ -506,14 +625,21 @@ public interface IDeepMktDataHandler { void updateMktDepth(int position, String marketMaker, DeepType operation, DeepSide side, double price, int size); } - public void reqDeepMktData( NewContract contract, int numRows, IDeepMktDataHandler handler) { + public void reqDeepMktData( Contract contract, int numRows, IDeepMktDataHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_deepMktDataMap.put( reqId, handler); - m_client.reqMktDepth( reqId, contract.getContract(), numRows); + List mktDepthOptions = new ArrayList<>(); + m_client.reqMktDepth( reqId, contract, numRows, mktDepthOptions); sendEOM(); } public void cancelDeepMktData( IDeepMktDataHandler handler) { + if (!checkConnection()) + return; + Integer reqId = getAndRemoveKey( m_deepMktDataMap, handler); if (reqId != null) { m_client.cancelMktDepth( reqId); @@ -538,21 +664,30 @@ public void cancelDeepMktData( IDeepMktDataHandler handler) { } // ---------------------------------------- Option computations ---------------------------------------- - public void reqOptionVolatility(NewContract c, double optPrice, double underPrice, IOptHandler handler) { + public void reqOptionVolatility(Contract c, double optPrice, double underPrice, IOptHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_optionCompMap.put( reqId, handler); - m_client.calculateImpliedVolatility( reqId, c.getContract(), optPrice, underPrice); + m_client.calculateImpliedVolatility( reqId, c, optPrice, underPrice); sendEOM(); } - public void reqOptionComputation( NewContract c, double vol, double underPrice, IOptHandler handler) { + public void reqOptionComputation( Contract c, double vol, double underPrice, IOptHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_optionCompMap.put( reqId, handler); - m_client.calculateOptionPrice(reqId, c.getContract(), vol, underPrice); + m_client.calculateOptionPrice(reqId, c, vol, underPrice); sendEOM(); } void cancelOptionComp( IOptHandler handler) { + if (!checkConnection()) + return; + Integer reqId = getAndRemoveKey( m_optionCompMap, handler); if (reqId != null) { m_client.cancelCalculateOptionPrice( reqId); @@ -563,7 +698,7 @@ void cancelOptionComp( IOptHandler handler) { @Override public void tickOptionComputation(int reqId, int tickType, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) { IOptHandler handler = m_optionCompMap.get( reqId); if (handler != null) { - handler.tickOptionComputation( NewTickType.get( tickType), impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice); + handler.tickOptionComputation( TickType.get( tickType), impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice); } else { System.out.println( String.format( "not handled %s %s %s %s %s %s %s %s %s", tickType, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice) ); @@ -574,12 +709,15 @@ void cancelOptionComp( IOptHandler handler) { // ---------------------------------------- Trade reports ---------------------------------------- public interface ITradeReportHandler { - void tradeReport(String tradeKey, NewContract contract, Execution execution); + void tradeReport(String tradeKey, Contract contract, Execution execution); void tradeReportEnd(); void commissionReport(String tradeKey, CommissionReport commissionReport); } public void reqExecutions( ExecutionFilter filter, ITradeReportHandler handler) { + if (!checkConnection()) + return; + m_tradeReportHandler = handler; m_client.reqExecutions( m_reqId++, filter); sendEOM(); @@ -587,9 +725,9 @@ public void reqExecutions( ExecutionFilter filter, ITradeReportHandler handler) @Override public void execDetails(int reqId, Contract contract, Execution execution) { if (m_tradeReportHandler != null) { - int i = execution.m_execId.lastIndexOf( '.'); - String tradeKey = execution.m_execId.substring( 0, i); - m_tradeReportHandler.tradeReport( tradeKey, new NewContract( contract), execution); + int i = execution.execId().lastIndexOf( '.'); + String tradeKey = execution.execId().substring( 0, i); + m_tradeReportHandler.tradeReport( tradeKey, contract, execution); } recEOM(); } @@ -612,23 +750,32 @@ public void reqExecutions( ExecutionFilter filter, ITradeReportHandler handler) // ---------------------------------------- Advisor info ---------------------------------------- public interface IAdvisorHandler { - void groups(ArrayList groups); - void profiles(ArrayList profiles); - void aliases(ArrayList aliases); + void groups(List groups); + void profiles(List profiles); + void aliases(List aliases); } public void reqAdvisorData( FADataType type, IAdvisorHandler handler) { + if (!checkConnection()) + return; + m_advisorHandler = handler; m_client.requestFA( type.ordinal() ); sendEOM(); } - public void updateGroups( ArrayList groups) { + public void updateGroups( List groups) { + if (!checkConnection()) + return; + m_client.replaceFA( FADataType.GROUPS.ordinal(), AdvisorUtil.getGroupsXml( groups) ); sendEOM(); } - public void updateProfiles(ArrayList profiles) { + public void updateProfiles(List profiles) { + if (!checkConnection()) + return; + m_client.replaceFA( FADataType.PROFILES.ordinal(), AdvisorUtil.getProfilesXml( profiles) ); sendEOM(); } @@ -642,30 +789,39 @@ public void updateProfiles(ArrayList profiles) { switch( type) { case GROUPS: - ArrayList groups = AdvisorUtil.getGroups( xml); + List groups = AdvisorUtil.getGroups( xml); m_advisorHandler.groups(groups); break; case PROFILES: - ArrayList profiles = AdvisorUtil.getProfiles( xml); + List profiles = AdvisorUtil.getProfiles( xml); m_advisorHandler.profiles(profiles); break; case ALIASES: - ArrayList aliases = AdvisorUtil.getAliases( xml); + List aliases = AdvisorUtil.getAliases( xml); m_advisorHandler.aliases(aliases); break; + + default: + break; } recEOM(); } // ---------------------------------------- Trading and Option Exercise ---------------------------------------- + /** This interface is for receiving events for a specific order placed from the API. + * Compare to ILiveOrderHandler. */ public interface IOrderHandler { - void orderState(NewOrderState orderState); + void orderState(OrderState orderState); + void orderStatus(OrderStatus status, double filled, double remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld); void handle(int errorCode, String errorMsg); } - public void placeOrModifyOrder(NewContract contract, final NewOrder order, final IOrderHandler handler) { + public void placeOrModifyOrder(Contract contract, final Order order, final IOrderHandler handler) { + if (!checkConnection()) + return; + // when placing new order, assign new order id if (order.orderId() == 0) { order.orderId( m_orderId++); @@ -679,17 +835,26 @@ public void placeOrModifyOrder(NewContract contract, final NewOrder order, final } public void cancelOrder(int orderId) { + if (!checkConnection()) + return; + m_client.cancelOrder( orderId); sendEOM(); } public void cancelAllOrders() { + if (!checkConnection()) + return; + m_client.reqGlobalCancel(); sendEOM(); } - public void exerciseOption( String account, NewContract contract, ExerciseType type, int quantity, boolean override) { - m_client.exerciseOptions( m_reqId++, contract.getContract(), type.ordinal(), quantity, account, override ? 1 : 0); + public void exerciseOption( String account, Contract contract, ExerciseType type, int quantity, boolean override) { + if (!checkConnection()) + return; + + m_client.exerciseOptions( m_reqId++, contract, type.ordinal(), quantity, account, override ? 1 : 0); sendEOM(); } @@ -699,26 +864,37 @@ public void removeOrderHandler( IOrderHandler handler) { // ---------------------------------------- Live order handling ---------------------------------------- + /** This interface is for downloading and receiving events for all live orders. + * Compare to IOrderHandler. */ public interface ILiveOrderHandler { - void openOrder(NewContract contract, NewOrder order, NewOrderState orderState); + void openOrder(Contract contract, Order order, OrderState orderState); void openOrderEnd(); - void orderStatus(int orderId, OrderStatus status, int filled, int remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld); + void orderStatus(int orderId, OrderStatus status, double filled, double remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld); void handle(int orderId, int errorCode, String errorMsg); // add permId? } public void reqLiveOrders( ILiveOrderHandler handler) { + if (!checkConnection()) + return; + m_liveOrderHandlers.add( handler); m_client.reqAllOpenOrders(); sendEOM(); } public void takeTwsOrders( ILiveOrderHandler handler) { + if (!checkConnection()) + return; + m_liveOrderHandlers.add( handler); m_client.reqOpenOrders(); sendEOM(); } public void takeFutureTwsOrders( ILiveOrderHandler handler) { + if (!checkConnection()) + return; + m_liveOrderHandlers.add( handler); m_client.reqAutoOpenOrders( true); sendEOM(); @@ -728,17 +904,15 @@ public void removeLiveOrderHandler(ILiveOrderHandler handler) { m_liveOrderHandlers.remove( handler); } - @Override public void openOrder(int orderId, Contract contract, Order orderIn, OrderState orderState) { - NewOrder order = new NewOrder( orderIn); - + @Override public void openOrder(int orderId, Contract contract, Order order, OrderState orderState) { IOrderHandler handler = m_orderHandlers.get( orderId); if (handler != null) { - handler.orderState( new NewOrderState( orderState) ); + handler.orderState(orderState); } if (!order.whatIf() ) { for (ILiveOrderHandler liveHandler : m_liveOrderHandlers) { - liveHandler.openOrder( new NewContract( contract), order, new NewOrderState( orderState) ); + liveHandler.openOrder( contract, order, orderState ); } } recEOM(); @@ -751,9 +925,14 @@ public void removeLiveOrderHandler(ILiveOrderHandler handler) { recEOM(); } - @Override public void orderStatus(int orderId, String status, int filled, int remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld) { - for (ILiveOrderHandler handler : m_liveOrderHandlers) { - handler.orderStatus(orderId, OrderStatus.valueOf( status), filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld); + @Override public void orderStatus(int orderId, String status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld) { + IOrderHandler handler = m_orderHandlers.get( orderId); + if (handler != null) { + handler.orderStatus( OrderStatus.valueOf( status), filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld); + } + + for (ILiveOrderHandler liveOrderHandler : m_liveOrderHandlers) { + liveOrderHandler.orderStatus(orderId, OrderStatus.valueOf( status), filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld); } recEOM(); } @@ -762,24 +941,34 @@ public void removeLiveOrderHandler(ILiveOrderHandler handler) { // ---------------------------------------- Market Scanners ---------------------------------------- public interface IScannerHandler { void scannerParameters(String xml); - void scannerData( int rank, NewContractDetails contractDetails, String legsStr); + void scannerData( int rank, ContractDetails contractDetails, String legsStr); void scannerDataEnd(); } public void reqScannerParameters( IScannerHandler handler) { + if (!checkConnection()) + return; + m_scannerHandler = handler; m_client.reqScannerParameters(); sendEOM(); } public void reqScannerSubscription( ScannerSubscription sub, IScannerHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_scannerMap.put( reqId, handler); - m_client.reqScannerSubscription( reqId, sub); + List scannerSubscriptionOptions = new ArrayList<>(); + m_client.reqScannerSubscription( reqId, sub, scannerSubscriptionOptions); sendEOM(); } public void cancelScannerSubscription( IScannerHandler handler) { + if (!checkConnection()) + return; + Integer reqId = getAndRemoveKey( m_scannerMap, handler); if (reqId != null) { m_client.cancelScannerSubscription( reqId); @@ -795,7 +984,7 @@ public void cancelScannerSubscription( IScannerHandler handler) { @Override public void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, String benchmark, String projection, String legsStr) { IScannerHandler handler = m_scannerMap.get( reqId); if (handler != null) { - handler.scannerData( rank, new NewContractDetails( contractDetails), legsStr); + handler.scannerData( rank, contractDetails, legsStr); } recEOM(); } @@ -811,47 +1000,53 @@ public void cancelScannerSubscription( IScannerHandler handler) { // ----------------------------------------- Historical data handling ---------------------------------------- public interface IHistoricalDataHandler { - void historicalData(Bar bar, boolean hasGaps); + void historicalData(Bar bar); void historicalDataEnd(); } /** @param endDateTime format is YYYYMMDD HH:MM:SS [TMZ] * @param duration is number of durationUnits */ - public void reqHistoricalData( NewContract contract, String endDateTime, int duration, DurationUnit durationUnit, BarSize barSize, WhatToShow whatToShow, boolean rthOnly, IHistoricalDataHandler handler) { + public void reqHistoricalData(Contract contract, String endDateTime, int duration, DurationUnit durationUnit, BarSize barSize, WhatToShow whatToShow, boolean rthOnly, boolean keepUpToDate, IHistoricalDataHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_historicalDataMap.put( reqId, handler); String durationStr = duration + " " + durationUnit.toString().charAt( 0); - m_client.reqHistoricalData(reqId, contract.getContract(), endDateTime, durationStr, barSize.toString(), whatToShow.toString(), rthOnly ? 1 : 0, 2); + m_client.reqHistoricalData(reqId, contract, endDateTime, durationStr, barSize.toString(), whatToShow.toString(), rthOnly ? 1 : 0, 2, keepUpToDate, Collections.emptyList()); sendEOM(); } public void cancelHistoricalData( IHistoricalDataHandler handler) { - Integer reqId = getAndRemoveKey( m_historicalDataMap, handler); + if (!checkConnection()) + return; + + Integer reqId = getAndRemoveKey( m_historicalDataMap, handler); if (reqId != null) { m_client.cancelHistoricalData( reqId); sendEOM(); } } - @Override public void historicalData(int reqId, String date, double open, double high, double low, double close, int volume, int count, double wap, boolean hasGaps) { + @Override public void historicalData(int reqId, com.ib.client.Bar bar) { IHistoricalDataHandler handler = m_historicalDataMap.get( reqId); if (handler != null) { - if (date.startsWith( "finished")) { + if (bar.time().startsWith( "finished")) { handler.historicalDataEnd(); } else { long longDate; - if (date.length() == 8) { - int year = Integer.parseInt( date.substring( 0, 4) ); - int month = Integer.parseInt( date.substring( 4, 6) ); - int day = Integer.parseInt( date.substring( 6) ); - longDate = new Date( year - 1900, month - 1, day).getTime() / 1000; + if (bar.time().length() == 8) { + int year = Integer.parseInt( bar.time().substring( 0, 4) ); + int month = Integer.parseInt( bar.time().substring( 4, 6) ); + int day = Integer.parseInt( bar.time().substring( 6) ); + longDate = new GregorianCalendar( year, month - 1, day).getTimeInMillis() / 1000; } else { - longDate = Long.parseLong( date); + longDate = Long.parseLong( bar.time()); } - Bar bar = new Bar( longDate, high, low, open, close, wap, volume, count); - handler.historicalData(bar, hasGaps); + Bar bar2 = new Bar( longDate, bar.high(), bar.low(), bar.open(), bar.close(), bar.wap(), bar.volume(), bar.count()); + handler.historicalData(bar2); } } recEOM(); @@ -863,14 +1058,21 @@ public interface IRealTimeBarHandler { void realtimeBar(Bar bar); // time is in seconds since epoch } - public void reqRealTimeBars(NewContract contract, WhatToShow whatToShow, boolean rthOnly, IRealTimeBarHandler handler) { + public void reqRealTimeBars(Contract contract, WhatToShow whatToShow, boolean rthOnly, IRealTimeBarHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_realTimeBarMap.put( reqId, handler); - m_client.reqRealTimeBars(reqId, contract.getContract(), 0, whatToShow.toString(), rthOnly); + List realTimeBarsOptions = new ArrayList<>(); + m_client.reqRealTimeBars(reqId, contract, 0, whatToShow.toString(), rthOnly, realTimeBarsOptions); sendEOM(); } public void cancelRealtimeBars( IRealTimeBarHandler handler) { + if (!checkConnection()) + return; + Integer reqId = getAndRemoveKey( m_realTimeBarMap, handler); if (reqId != null) { m_client.cancelRealTimeBars( reqId); @@ -887,16 +1089,18 @@ public void cancelRealtimeBars( IRealTimeBarHandler handler) { recEOM(); } - // ----------------------------------------- Fundamentals handling ---------------------------------------- public interface IFundamentalsHandler { void fundamentals( String str); } - public void reqFundamentals( NewContract contract, FundamentalType reportType, IFundamentalsHandler handler) { + public void reqFundamentals( Contract contract, FundamentalType reportType, IFundamentalsHandler handler) { + if (!checkConnection()) + return; + int reqId = m_reqId++; m_fundMap.put( reqId, handler); - m_client.reqFundamentalData( reqId, contract.getContract(), reportType.getApiString() ); + m_client.reqFundamentalData( reqId, contract, reportType.getApiString()); sendEOM(); } @@ -908,36 +1112,52 @@ public void reqFundamentals( NewContract contract, FundamentalType reportType, I recEOM(); } - // ---------------------------------------- Time handling ---------------------------------------- public interface ITimeHandler { void currentTime(long time); } public void reqCurrentTime( ITimeHandler handler) { + if (!checkConnection()) + return; + m_timeHandler = handler; m_client.reqCurrentTime(); sendEOM(); } + protected boolean checkConnection() { + if (!isConnected()) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED.code(), EClientErrors.NOT_CONNECTED.msg()); + return false; + } + + return true; + } + @Override public void currentTime(long time) { m_timeHandler.currentTime(time); recEOM(); } - // ---------------------------------------- Bulletins handling ---------------------------------------- public interface IBulletinHandler { void bulletin(int msgId, NewsType newsType, String message, String exchange); } public void reqBulletins( boolean allMessages, IBulletinHandler handler) { + if (!checkConnection()) + return; + m_bulletinHandler = handler; m_client.reqNewsBulletins( allMessages); sendEOM(); } public void cancelBulletins() { + if (!checkConnection()) + return; + m_client.cancelNewsBulletins(); } @@ -946,15 +1166,107 @@ public void cancelBulletins() { recEOM(); } + // ---------------------------------------- Position Multi handling ---------------------------------------- + public interface IPositionMultiHandler { + void positionMulti( String account, String modelCode, Contract contract, double pos, double avgCost); + void positionMultiEnd(); + } + + public void reqPositionsMulti( String account, String modelCode, IPositionMultiHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + m_positionMultiMap.put( reqId, handler); + m_client.reqPositionsMulti( reqId, account, modelCode); + sendEOM(); + } + + public void cancelPositionsMulti( IPositionMultiHandler handler) { + if (!checkConnection()) + return; + + Integer reqId = getAndRemoveKey( m_positionMultiMap, handler); + if (reqId != null) { + m_client.cancelPositionsMulti( reqId); + sendEOM(); + } + } + + @Override public void positionMulti( int reqId, String account, String modelCode, Contract contract, double pos, double avgCost) { + IPositionMultiHandler handler = m_positionMultiMap.get( reqId); + if (handler != null) { + handler.positionMulti( account, modelCode, contract, pos, avgCost); + } + recEOM(); + } + + @Override public void positionMultiEnd( int reqId) { + IPositionMultiHandler handler = m_positionMultiMap.get( reqId); + if (handler != null) { + handler.positionMultiEnd(); + } + recEOM(); + } + + // ---------------------------------------- Account Update Multi handling ---------------------------------------- + public interface IAccountUpdateMultiHandler { + void accountUpdateMulti( String account, String modelCode, String key, String value, String currency); + void accountUpdateMultiEnd(); + } + + public void reqAccountUpdatesMulti( String account, String modelCode, boolean ledgerAndNLV, IAccountUpdateMultiHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + m_accountUpdateMultiMap.put( reqId, handler); + m_client.reqAccountUpdatesMulti( reqId, account, modelCode, ledgerAndNLV); + sendEOM(); + } + + public void cancelAccountUpdatesMulti( IAccountUpdateMultiHandler handler) { + if (!checkConnection()) + return; + + Integer reqId = getAndRemoveKey( m_accountUpdateMultiMap, handler); + if (reqId != null) { + m_client.cancelAccountUpdatesMulti( reqId); + sendEOM(); + } + } + + @Override public void accountUpdateMulti( int reqId, String account, String modelCode, String key, String value, String currency) { + IAccountUpdateMultiHandler handler = m_accountUpdateMultiMap.get( reqId); + if (handler != null) { + handler.accountUpdateMulti( account, modelCode, key, value, currency); + } + recEOM(); + } + + @Override public void accountUpdateMultiEnd( int reqId) { + IAccountUpdateMultiHandler handler = m_accountUpdateMultiMap.get( reqId); + if (handler != null) { + handler.accountUpdateMultiEnd(); + } + recEOM(); + } + + @Override public void verifyMessageAPI( String apiData) {} + @Override public void verifyCompleted( boolean isSuccessful, String errorText) {} + @Override public void verifyAndAuthMessageAPI( String apiData, String xyzChallenge) {} + @Override public void verifyAndAuthCompleted( boolean isSuccessful, String errorText) {} + @Override public void displayGroupList(int reqId, String groups) {} + @Override public void displayGroupUpdated(int reqId, String contractInfo) {} // ---------------------------------------- other methods ---------------------------------------- /** Not supported in ApiController. */ - @Override public void deltaNeutralValidation(int reqId, UnderComp underComp) { + @Override public void deltaNeutralValidation(int reqId, DeltaNeutralContract underComp) { show( "RECEIVED DN VALIDATION"); recEOM(); } - private void sendEOM() { + protected void sendEOM() { m_outLogger.log( "\n"); } @@ -966,7 +1278,7 @@ public void show(String string) { m_connectionHandler.show( string); } - private static K getAndRemoveKey( HashMap map, V value) { + private static K getAndRemoveKey( Map map, V value) { for (Entry entry : map.entrySet() ) { if (entry.getValue() == value) { map.remove( entry.getKey() ); @@ -980,4 +1292,466 @@ private static K getAndRemoveKey( HashMap map, V value) { @Override public void error(String str) { throw new RuntimeException(); } + + @Override + public void connectAck() { + if (m_client.isAsyncEConnect()) + m_client.startAPI(); + } + + public void reqSecDefOptParams( String underlyingSymbol, String futFopExchange, /*String currency,*/ String underlyingSecType, int underlyingConId, ISecDefOptParamsReqHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + m_secDefOptParamsReqMap.put( reqId, handler); + m_client.reqSecDefOptParams(reqId, underlyingSymbol, futFopExchange, /*currency,*/ underlyingSecType, underlyingConId); + sendEOM(); + } + + public interface ISecDefOptParamsReqHandler { + void securityDefinitionOptionalParameter(String exchange, int underlyingConId, String tradingClass, + String multiplier, Set expirations, Set strikes); + void securityDefinitionOptionalParameterEnd(int reqId); + } + + @Override + public void securityDefinitionOptionalParameter(int reqId, String exchange, int underlyingConId, String tradingClass, + String multiplier, Set expirations, Set strikes) { + ISecDefOptParamsReqHandler handler = m_secDefOptParamsReqMap.get( reqId); + + if (handler != null) { + handler.securityDefinitionOptionalParameter(exchange, underlyingConId, tradingClass, multiplier, expirations, strikes); + } + } + + @Override + public void securityDefinitionOptionalParameterEnd(int reqId) { + ISecDefOptParamsReqHandler handler = m_secDefOptParamsReqMap.get( reqId); + if (handler != null) { + handler.securityDefinitionOptionalParameterEnd(reqId); + } + } + + + public interface ISoftDollarTiersReqHandler { + void softDollarTiers(SoftDollarTier[] tiers); + } + + public void reqSoftDollarTiers(ISoftDollarTiersReqHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + + m_softDollarTiersReqMap.put(reqId, handler); + m_client.reqSoftDollarTiers(reqId); + sendEOM(); + } + + @Override + public void softDollarTiers(int reqId, SoftDollarTier[] tiers) { + ISoftDollarTiersReqHandler handler = m_softDollarTiersReqMap.get(reqId); + + if (handler != null) { + handler.softDollarTiers(tiers); + } + } + + public interface IFamilyCodesHandler { + void familyCodes(FamilyCode[] familyCodes); + } + + public void reqFamilyCodes(IFamilyCodesHandler handler) { + if (!checkConnection()) + return; + + m_familyCodesHandlers.add(handler); + m_client.reqFamilyCodes(); + sendEOM(); + } + + @Override + public void familyCodes(FamilyCode[] familyCodes) { + for( IFamilyCodesHandler handler : m_familyCodesHandlers) { + handler.familyCodes(familyCodes); + } + recEOM(); + } + + public interface ISymbolSamplesHandler { + void symbolSamples(ContractDescription[] contractDescriptions); + } + + public void reqMatchingSymbols(String pattern, ISymbolSamplesHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + + m_symbolSamplesHandlerMap.put(reqId, handler); + m_client.reqMatchingSymbols(reqId, pattern); + sendEOM(); + } + + @Override + public void symbolSamples(int reqId, ContractDescription[] contractDescriptions) { + ISymbolSamplesHandler handler = m_symbolSamplesHandlerMap.get(reqId); + + if (handler != null) { + handler.symbolSamples(contractDescriptions); + } + recEOM(); + } + + @Override + public void historicalDataEnd(int reqId, String startDateStr, String endDateStr) { + IHistoricalDataHandler handler = m_historicalDataMap.get(reqId); + + if (handler != null) { + handler.historicalDataEnd(); + } + } + + public interface IMktDepthExchangesHandler { + void mktDepthExchanges(DepthMktDataDescription[] depthMktDataDescriptions); + } + + public void reqMktDepthExchanges(IMktDepthExchangesHandler handler) { + if (!checkConnection()) + return; + + m_mktDepthExchangesHandlers.add(handler); + m_client.reqMktDepthExchanges(); + sendEOM(); + } + + @Override + public void mktDepthExchanges(DepthMktDataDescription[] depthMktDataDescriptions) { + for( IMktDepthExchangesHandler handler : m_mktDepthExchangesHandlers) { + handler.mktDepthExchanges(depthMktDataDescriptions); + } + recEOM(); + } + + public interface ITickNewsHandler { + void tickNews(long timeStamp, String providerCode, String articleId, String headline, String extraData); + } + + public void reqNewsTicks(Contract contract, ITickNewsHandler handler) { + if (!checkConnection()) + return; + + int tickerId = m_reqId++; + + m_tickNewsHandlerMap.put(tickerId, handler); + m_client.reqMktData(tickerId, contract, "mdoff,292", false, false, Collections.emptyList()); + sendEOM(); + } + + @Override + public void tickNews(int tickerId, long timeStamp, String providerCode, String articleId, String headline, String extraData) { + ITickNewsHandler handler = m_tickNewsHandlerMap.get(tickerId); + + if (handler != null) { + handler.tickNews(timeStamp, providerCode, articleId, headline, extraData); + } + recEOM(); + } + + public interface ISmartComponentsHandler { + + void smartComponents(int reqId, Map> theMap); + + } + + @Override + public void smartComponents(int reqId, Map> theMap) { + ISmartComponentsHandler handler = m_smartComponentsHandler.get(reqId); + + if (handler != null) { + handler.smartComponents(reqId, theMap); + } + } + + public void reqSmartComponents(String bboExchange, ISmartComponentsHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + + m_smartComponentsHandler.put(reqId, handler); + m_client.reqSmartComponents(reqId, bboExchange); + sendEOM(); + } + + @Override + public void tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions) { + ITopMktDataHandler handler = m_topMktDataMap.get(tickerId); + + if (handler != null) { + handler.tickReqParams(tickerId, minTick, bboExchange, snapshotPermissions); + } + + recEOM(); + } + + public interface INewsProvidersHandler { + void newsProviders(NewsProvider[] newsProviders); + } + + public void reqNewsProviders(INewsProvidersHandler handler) { + if (!checkConnection()) + return; + + m_newsProvidersHandlers.add(handler); + m_client.reqNewsProviders(); + sendEOM(); + } + + @Override + public void newsProviders(NewsProvider[] newsProviders) { + for( INewsProvidersHandler handler : m_newsProvidersHandlers) { + handler.newsProviders(newsProviders); + } + recEOM(); + } + + public interface INewsArticleHandler { + void newsArticle(int articleType, String articleText); + } + + public void reqNewsArticle(String providerCode, String articleId, INewsArticleHandler handler) { + if (!checkConnection()) + return; + + int requestId = m_reqId++; + + m_newsArticleHandlerMap.put(requestId, handler); + m_client.reqNewsArticle(requestId, providerCode, articleId, Collections.emptyList()); + sendEOM(); + } + + @Override + public void newsArticle(int requestId, int articleType, String articleText) { + INewsArticleHandler handler = m_newsArticleHandlerMap.get(requestId); + + if (handler != null) { + handler.newsArticle(articleType, articleText); + } + recEOM(); + } + + public interface IHistoricalNewsHandler { + void historicalNews( String time, String providerCodes, String articleId, String headline); + void historicalNewsEnd( boolean hasMore); + } + + public void reqHistoricalNews( int conId, String providerCodes, String startDateTime, String endDateTime, int totalResults, IHistoricalNewsHandler handler) { + if (!checkConnection()) + return; + + int requestId = m_reqId++; + m_historicalNewsHandlerMap.put( requestId, handler); + m_client.reqHistoricalNews( requestId, conId, providerCodes, startDateTime, endDateTime, totalResults, Collections.emptyList()); + sendEOM(); + } + + @Override public void historicalNews( int requestId, String time, String providerCode, String articleId, String headline) { + IHistoricalNewsHandler handler = m_historicalNewsHandlerMap.get( requestId); + if (handler != null) { + handler.historicalNews( time, providerCode, articleId, headline); + } + recEOM(); + } + + @Override public void historicalNewsEnd( int requestId, boolean hasMore) { + IHistoricalNewsHandler handler = m_historicalNewsHandlerMap.get( requestId); + if (handler != null) { + handler.historicalNewsEnd( hasMore); + } + recEOM(); + } + + public interface IHeadTimestampHandler { + + void headTimestamp(int reqId, long headTimestamp); + + } + + public void reqHeadTimestamp(Contract contract, WhatToShow whatToShow, boolean rthOnly, IHeadTimestampHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + + m_headTimestampMap.put(reqId, handler); + m_client.reqHeadTimestamp(reqId, contract, whatToShow.toString(), rthOnly ? 1 : 0, 2); + } + + @Override + public void headTimestamp(int reqId, String headTimestamp) { + IHeadTimestampHandler handler = m_headTimestampMap.get(reqId); + + if (handler != null) { + handler.headTimestamp(reqId, Long.parseLong(headTimestamp)); + } + + recEOM(); + } + + public interface IHistogramDataHandler { + + void histogramData(int reqId, List items); + + } + + public void reqHistogramData(Contract contract, int duration, DurationUnit durationUnit, boolean rthOnly, IHistogramDataHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + String durationStr = duration + " " + durationUnit.toString().toLowerCase() + "s"; + + m_histogramDataMap.put(reqId, handler); + m_client.reqHistogramData(reqId, contract, rthOnly, durationStr); + } + + public void cancelHistogramData(IHistogramDataHandler handler) { + if (!checkConnection()) + return; + + Integer reqId = getAndRemoveKey(m_histogramDataMap, handler); + + if (reqId != null) { + m_client.cancelHistoricalData(reqId); + sendEOM(); + } + } + + @Override + public void histogramData(int reqId, List items) { + IHistogramDataHandler handler = m_histogramDataMap.get(reqId); + + if (handler != null) { + handler.histogramData(reqId, items); + } + + recEOM(); + } + + @Override + public void historicalDataUpdate(int reqId, com.ib.client.Bar bar) { + historicalData(reqId, bar); + } + + @Override public void rerouteMktDataReq(int reqId, int conId, String exchange) { + show( "Re-route market data request. ReqId: " + reqId + ", ConId: " + conId + ", Exchange: " + exchange); + } + + @Override public void rerouteMktDepthReq(int reqId, int conId, String exchange) { + show( "Re-route market depth request. ReqId: " + reqId + ", ConId: " + conId + ", Exchange: " + exchange); + } + + public interface IMarketRuleHandler { + void marketRule(int marketRuleId, PriceIncrement[] priceIncrements); + } + + public void reqMarketRule(int marketRuleId, IMarketRuleHandler handler) { + if (!checkConnection()) + return; + + m_marketRuleHandlers.add(handler); + m_client.reqMarketRule(marketRuleId); + sendEOM(); + } + + @Override + public void marketRule(int marketRuleId, PriceIncrement[] priceIncrements) { + for( IMarketRuleHandler handler : m_marketRuleHandlers) { + handler.marketRule(marketRuleId, priceIncrements); + } + recEOM(); + } + + + public interface IPnLHandler { + + void pnl(int reqId, double dailyPnL, double unrealizedPnL); + + } + + public void reqPnL(String account, String modelCode, IPnLHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + + m_PnLMap.put(reqId, handler); + + m_client.reqPnL(reqId, account, modelCode); + } + + public void cancelPnL(IPnLHandler handler) { + if (!checkConnection()) + return; + + Integer reqId = getAndRemoveKey(m_PnLMap, handler); + + if (reqId != null) { + m_client.cancelPnL(reqId); + sendEOM(); + } + } + + @Override + public void pnl(int reqId, double dailyPnL, double unrealizedPnL) { + IPnLHandler handler = m_PnLMap.get(reqId); + + if (handler != null) { + handler.pnl(reqId, dailyPnL, unrealizedPnL); + } + + recEOM(); + } + + public interface IPnLSingleHandler { + + void pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double value); + + } + + public void reqPnLSingle(String account, String modelCode, int conId, IPnLSingleHandler handler) { + if (!checkConnection()) + return; + + int reqId = m_reqId++; + + m_PnLSingleMap.put(reqId, handler); + + m_client.reqPnLSingle(reqId, account, modelCode, conId); + } + + public void cancelPnLSingle(IPnLSingleHandler handler) { + if (!checkConnection()) + return; + + Integer reqId = getAndRemoveKey(m_PnLSingleMap, handler); + + if (reqId != null) { + m_client.cancelPnLSingle(reqId); + sendEOM(); + } + } + + @Override + public void pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double value) { + IPnLSingleHandler handler = m_PnLSingleMap.get(reqId); + + if (handler != null) { + handler.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, value); + } + + recEOM(); + } } diff --git a/ref/controller/Bar.java b/ref/controller/Bar.java index 94ce7cb..1e07b36 100644 --- a/ref/controller/Bar.java +++ b/ref/controller/Bar.java @@ -7,7 +7,7 @@ import java.util.Date; public class Bar { - private static final SimpleDateFormat FORMAT = new SimpleDateFormat( "yyyyMMdd HH:mm:ss"); // format for historical query + private static final ThreadLocal FORMAT_CACHE = ThreadLocal.withInitial(() -> new SimpleDateFormat( "yyyyMMdd HH:mm:ss")); private final long m_time; private final double m_high; @@ -44,7 +44,7 @@ public String formattedTime() { /** Format for query. */ public static String format( long ms) { - return FORMAT.format( new Date( ms) ); + return FORMAT_CACHE.get().format( new Date( ms) ); } @Override public String toString() { diff --git a/ref/controller/ConcurrentHashSet.java b/ref/controller/ConcurrentHashSet.java index 17e26d2..4018aaf 100644 --- a/ref/controller/ConcurrentHashSet.java +++ b/ref/controller/ConcurrentHashSet.java @@ -1,43 +1,51 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.controller; import java.util.AbstractSet; import java.util.Iterator; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ConcurrentHashSet extends AbstractSet { - static Object OBJECT = new Object(); + private static final Object OBJECT = new Object(); - private ConcurrentHashMap m_map = new ConcurrentHashMap(16,0.75f,1); // use write concurrency level 1 (last param) to decrease memory consumption by ConcurrentHashMap + private Map m_map = new ConcurrentHashMap<>(16,0.75f,1); // use write concurrency level 1 (last param) to decrease memory consumption by ConcurrentHashMap /** return true if object was added as "first value" for this key */ + @Override public boolean add( Key key) { return m_map.put( key, OBJECT) == null; // null means there was no value for given key previously } + @Override public boolean contains( Object key) { return m_map.containsKey( key); } + @Override public Iterator iterator() { return m_map.keySet().iterator(); } /** return true if key was indeed removed */ + @Override public boolean remove( Object key) { return m_map.remove( key) == OBJECT; // if value not null it was existing in the map } + @Override public boolean isEmpty() { return m_map.isEmpty(); } + @Override public int size() { return m_map.size(); } + @Override public void clear() { m_map.clear(); } diff --git a/ref/controller/DeltaNeutralContract.java b/ref/controller/DeltaNeutralContract.java deleted file mode 100644 index f8b2d3c..0000000 --- a/ref/controller/DeltaNeutralContract.java +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - - -public class DeltaNeutralContract { - private int m_conid; - private double m_delta; - private double m_price; - - public int conid() { return m_conid; } - public double delta() { return m_delta; } - public double price() { return m_price; } - - public DeltaNeutralContract(int conid, double delta, double price) { - m_conid = conid; - m_delta = delta; - m_price = price; - } -} diff --git a/ref/controller/Formats.java b/ref/controller/Formats.java index 3760ce8..91c43e4 100644 --- a/ref/controller/Formats.java +++ b/ref/controller/Formats.java @@ -3,17 +3,24 @@ package com.ib.controller; +import java.text.DateFormat; import java.text.DecimalFormat; import java.text.Format; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.TimeZone; public class Formats { private static final Format FMT2 = new DecimalFormat( "#,##0.00"); private static final Format FMT0 = new DecimalFormat( "#,##0"); private static final Format PCT = new DecimalFormat( "0.0%"); - private static final SimpleDateFormat DATE_TIME = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); // format for display - private static final SimpleDateFormat TIME = new SimpleDateFormat( "HH:mm:ss"); // format for display + private static final ThreadLocal GMT_DATE_TIME_FORMAT_CACHE = ThreadLocal.withInitial(() -> { + final DateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + return format; + }); + private static final ThreadLocal DATE_TIME_FORMAT_CACHE = ThreadLocal.withInitial(() -> new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss")); + private static final ThreadLocal TIME_FORMAT_CACHE = ThreadLocal.withInitial(() -> new SimpleDateFormat( "HH:mm:ss")); /** Format with two decimals. */ public static String fmt( double v) { @@ -37,11 +44,15 @@ public static String fmtPct( double v) { /** Format date/time for display. */ public static String fmtDate( long ms) { - return DATE_TIME.format( new Date( ms) ); + return DATE_TIME_FORMAT_CACHE.get().format( new Date( ms) ); + } + + public static String fmtDateGmt(long ms) { + return GMT_DATE_TIME_FORMAT_CACHE.get().format( new Date( ms) ); } /** Format time for display. */ public static String fmtTime( long ms) { - return TIME.format( new Date( ms) ); + return TIME_FORMAT_CACHE.get().format( new Date( ms) ); } } diff --git a/ref/controller/Group.java b/ref/controller/Group.java index 9fd6b38..04cd391 100644 --- a/ref/controller/Group.java +++ b/ref/controller/Group.java @@ -4,18 +4,19 @@ package com.ib.controller; import java.util.ArrayList; +import java.util.List; import java.util.StringTokenizer; -import com.ib.controller.Types.Method; +import com.ib.client.Types.Method; public class Group { private String m_name; private Method m_defaultMethod; - private ArrayList m_accounts = new ArrayList(); + private List m_accounts = new ArrayList<>(); public String name() { return m_name; } public Method defaultMethod() { return m_defaultMethod; } - public ArrayList accounts() { return m_accounts; } + public List accounts() { return m_accounts; } public void name( String v) { m_name = v; } public void defaultMethod( Method v) { m_defaultMethod = v; } diff --git a/ref/controller/Instrument.java b/ref/controller/Instrument.java index f55a294..55b85aa 100644 --- a/ref/controller/Instrument.java +++ b/ref/controller/Instrument.java @@ -4,25 +4,32 @@ package com.ib.controller; public enum Instrument { - STK, - BOND, - EFP, - FUT_EU, - FUT_HK, - FUT_NA, - FUT_US, - IND_EU, - IND_HK, - IND_US, - PMONITOR, - PMONITORM, - SLB_US, - STOCK_EU, - STOCK_HK, - STOCK_NA, - WAR_EU; + STK("STK"), + BOND("BOND"), + EFP("EFP"), + FUT_EU("FUT.EU"), + FUT_HK("FUT.HK"), + FUT_NA("FUT.NA"), + FUT_US("FUT.US"), + IND_EU("IND.EU"), + IND_HK("IND.HK"), + IND_US("IND.US"), + PMONITOR("PMONITOR"), + PMONITORM("PMONITORM"), + SLB_US("SLB.US"), + STOCK_EU("STOCK.EU"), + STOCK_HK("STOCK.HK"), + STOCK_NA("STOCK.NA"), + WAR_EU("WAR.EU"); - public String toString() { - return super.toString().replace( '_', '.'); - } + private final String code; + + Instrument(final String code) { + this.code = code; + } + + @Override + public String toString() { + return code; + } } diff --git a/ref/controller/LocationCode.java b/ref/controller/LocationCode.java index 19d8316..e2ff12d 100644 --- a/ref/controller/LocationCode.java +++ b/ref/controller/LocationCode.java @@ -3,87 +3,100 @@ package com.ib.controller; -// BOND.US -// EFP -// FUT.ECBOT -// FUT.EU.BELFOX -// FUT.EU.DTB -// FUT.EU.FTA -// FUT.EU.IDEM -// FUT.EU.LIFFE -// FUT.EU.MEFFRV -// FUT.EU.MONEP -// FUT.EU -// FUT.GLOBEX -// FUT.HK.HKFE -// FUT.HK.JAPAN -// FUT.HK.KSE -// FUT.HK.NSE -// FUT.HK.OSE.JPN -// FUT.HK.SGX -// FUT.HK.SNFE -// FUT.HK.TSE.JPN -// FUT.HK -// FUT.IPE -// FUT.NA.CDE -// FUT.NA -// FUT.NYBOT -// FUT.NYMEX -// FUT.NYSELIFFE -// FUT.US -// IND.EU.BELFOX -// IND.EU.DTB -// IND.EU.FTA -// IND.EU.LIFFE -// IND.EU.MONEP -// IND.EU -// IND.HK.HKFE -// IND.HK.JAPAN -// IND.HK.KSE -// IND.HK.NSE -// IND.HK.OSE.JPN -// IND.HK.SGX -// IND.HK.SNFE -// IND.HK.TSE.JPN -// IND.HK -// IND.US -// SLB.AQS -// STK.AMEX -// STK.ARCA -// STK.EU.AEB -// STK.EU.BM -// STK.EU.BVME -// STK.EU.EBS -// STK.EU.IBIS -// STK.EU.IBIS-ETF -// STK.EU.IBIS-EUSTARS -// STK.EU.IBIS-NEWX -// STK.EU.IBIS-USSTARS -// STK.EU.IBIS-XETRA -// STK.EU.LSE -// STK.EU.SBF -// STK.EU.SBVM -// STK.EU.SFB -// STK.EU.SWISS -// STK.EU.VIRTX -// STK.EU -// STK.HK.ASX -// STK.HK.NSE -// STK.HK.SEHK -// STK.HK.SGX -// STK.HK.TSE.JPN -// STK.HK -// STK.NA.CANADA -// STK.NA.TSE -// STK.NA.VENTURE -// STK.NA -// STK.NASDAQ.NMS -// STK.NASDAQ.SCM -// STK.NASDAQ -// STK.NYSE -// STK.OTCBB -// STK.PINK -// STK.US.MAJOR -// STK.US.MINOR -// STK.US -// WAR.EU.ALL +public enum LocationCode { + BOND_US("BOND.US"), + EFP("EFP"), + FUT_ECBOT("FUT.ECBOT"), + FUT_EU_BELFOX("FUT.EU.BELFOX"), + FUT_EU_DTB("FUT.EU.DTB"), + FUT_EU_FTA("FUT.EU.FTA"), + FUT_EU_IDEM("FUT.EU.IDEM"), + FUT_EU_LIFFE("FUT.EU.LIFFE"), + FUT_EU_MEFFRV("FUT.EU.MEFFRV"), + FUT_EU_MONEP("FUT.EU.MONEP"), + FUT_EU("FUT.EU"), + FUT_GLOBEX("FUT.GLOBEX"), + FUT_HK_HKFE("FUT.HK.HKFE"), + FUT_HK_JAPAN("FUT.HK.JAPAN"), + FUT_HK_KSE("FUT.HK.KSE"), + FUT_HK_NSE("FUT.HK.NSE"), + FUT_HK_OSE_JPN("FUT.HK.OSE.JPN"), + FUT_HK_SGX("FUT.HK.SGX"), + FUT_HK_SNFE("FUT.HK.SNFE"), + FUT_HK_TSE_JPN("FUT.HK.TSE.JPN"), + FUT_HK("FUT.HK"), + FUT_IPE("FUT.IPE"), + FUT_NA_CDE("FUT.NA.CDE"), + FUT_NA("FUT.NA"), + FUT_NYBOT("FUT.NYBOT"), + FUT_NYMEX("FUT.NYMEX"), + FUT_NYSELIFFE("FUT.NYSELIFFE"), + FUT_US("FUT.US"), + IND_EU_BELFOX("IND.EU.BELFOX"), + IND_EU_DTB("IND.EU.DTB"), + IND_EU_FTA("IND.EU.FTA"), + IND_EU_LIFFE("IND.EU.LIFFE"), + IND_EU_MONEP("IND.EU.MONEP"), + IND_EU("IND.EU"), + IND_HK_HKFE("IND.HK.HKFE"), + IND_HK_JAPAN("IND.HK.JAPAN"), + IND_HK_KSE("IND.HK.KSE"), + IND_HK_NSE("IND.HK.NSE"), + IND_HK_OSE_JPN("IND.HK.OSE.JPN"), + IND_HK_SGX("IND.HK.SGX"), + IND_HK_SNFE("IND.HK.SNFE"), + IND_HK_TSE_JPN("IND.HK.TSE.JPN"), + IND_HK("IND.HK"), + IND_US("IND.US"), + SLB_AQS("SLB.AQS"), + STK_AMEX("STK.AMEX"), + STK_ARCA("STK.ARCA"), + STK_EU_AEB("STK.EU.AEB"), + STK_EU_BM("STK.EU.BM"), + STK_EU_BVME("STK.EU.BVME"), + STK_EU_EBS("STK.EU.EBS"), + STK_EU_IBIS("STK.EU.IBIS"), + STK_EU_IBIS_ETF("STK.EU.IBIS-ETF"), + STK_EU_IBIS_EUSTARS("STK.EU.IBIS-EUSTARS"), + STK_EU_IBIS_NEWX("STK.EU.IBIS-NEWX"), + STK_EU_IBIS_USSTARS("STK.EU.IBIS-USSTARS"), + STK_EU_IBIS_XETRA("STK.EU.IBIS-XETRA"), + STK_EU_LSE("STK.EU.LSE"), + STK_EU_SBF("STK.EU.SBF"), + STK_EU_SBVM("STK.EU.SBVM"), + STK_EU_SFB("STK.EU.SFB"), + STK_EU_SWISS("STK.EU.SWISS"), + STK_EU_VIRTX("STK.EU.VIRTX"), + STK_EU("STK.EU"), + STK_HK_ASX("STK.HK.ASX"), + STK_HK_NSE("STK.HK.NSE"), + STK_HK_SEHK("STK.HK.SEHK"), + STK_HK_SGX("STK.HK.SGX"), + STK_HK_TSE_JPN("STK.HK.TSE.JPN"), + STK_HK("STK.HK"), + STK_NA_CANADA("STK.NA.CANADA"), + STK_NA_TSE("STK.NA.TSE"), + STK_NA_VENTURE("STK.NA.VENTURE"), + STK_NA("STK.NA"), + STK_NASDAQ_NMS("STK.NASDAQ.NMS"), + STK_NASDAQ_SCM("STK.NASDAQ.SCM"), + STK_NASDAQ("STK.NASDAQ"), + STK_NYSE("STK.NYSE"), + STK_OTCBB("STK.OTCBB"), + STK_PINK("STK.PINK"), + STK_US_MAJOR("STK.US.MAJOR"), + STK_US_MINOR("STK.US.MINOR"), + STK_US("STK.US"), + WAR_EU_ALL("WAR.EU.ALL"); + + private final String code; + + LocationCode(final String code) { + this.code = code; + } + + @Override + public String toString() { + return code; + } +} diff --git a/ref/controller/MarketValueTag.java b/ref/controller/MarketValueTag.java index 9fb75de..320e989 100644 --- a/ref/controller/MarketValueTag.java +++ b/ref/controller/MarketValueTag.java @@ -1,41 +1,47 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms +/* Copyright (C) 2017 Interactive Brokers LLC. All rights reserved. This code is subject to the terms * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ package com.ib.controller; +import com.ib.client.Types; + public enum MarketValueTag { - NetLiquidationByCurrency, - CashBalance, - TotalCashBalance, - AccruedCash, - StockMarketValue, - OptionMarketValue, - FutureOptionValue, - FuturesPNL, - UnrealizedPnL, - RealizedPnL, - ExchangeRate, - FundValue, - NetDividend, - MutualFundValue, - MoneyMarketFundValue, - CorporateBondValue, - TBondValue, - TBillValue, - WarrantValue, - FxCashBalance; + AccountOrGroup("AccountOrGroup"), + RealCurrency("RealCurrency"), + IssuerOptionValue("IssuerOption"), + NetLiquidationByCurrency("Net Liq"), + CashBalance("CashBalance"), + TotalCashBalance("TotalCashBalance"), + AccruedCash("AccruedCash"), + StockMarketValue("Stocks"), + OptionMarketValue("Options"), + FutureOptionValue("Futures"), + FuturesPNL("FuturesPNL"), + UnrealizedPnL("UnrealizedPnL"), + RealizedPnL("RealizedPnL"), + ExchangeRate("ExchangeRate"), + FundValue("Fund"), + NetDividend("NetDividend"), + MutualFundValue("MutualFund"), + MoneyMarketFundValue("MoneyMarketFund"), + CorporateBondValue("CorporateBond"), + TBondValue("TBond"), + TBillValue("TBill"), + WarrantValue("Warrant"), + FxCashBalance("FxCashBalance"); + + private final String description; + + MarketValueTag(final String description) { + this.description = description; + } - public static MarketValueTag get( int i) { - return Types.getEnum( i, values() ); - } + public static MarketValueTag get(int i) { + return Types.getEnum(i, values()); + } - @Override public String toString() { - switch( this) { - case NetLiquidationByCurrency: return "Net Liq"; - case StockMarketValue: return "Stocks"; - case OptionMarketValue: return "Options"; - case FutureOptionValue: return "Futures"; - } - return super.toString().replaceAll("Value", ""); - } + @Override + public String toString() { + return description; + } } diff --git a/ref/controller/NewComboLeg.java b/ref/controller/NewComboLeg.java deleted file mode 100644 index 2187f00..0000000 --- a/ref/controller/NewComboLeg.java +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - -import com.ib.client.ComboLeg; -import com.ib.controller.Types.Action; - -public class NewComboLeg { - enum OpenClose { - Same, Open, Close, Unknown; - - static OpenClose get( int i) { - return Types.getEnum( i, values() ); - } - - String getApiString() { - return "" + ordinal(); - } - } - - private int m_conid; - private int m_ratio; - private Action m_action= Action.BUY; - private String m_exchange; - private OpenClose m_openClose = OpenClose.Same; - public int m_shortSaleSlot; // 1 = clearing broker, 2 = third party - public String m_designatedLocation; - public int m_exemptCode; - - public Action action() { return m_action; } - public int conid() { return m_conid; } - public int exemptCode() { return m_exemptCode; } - public int ratio() { return m_ratio; } - public int shortSaleSlot() { return m_shortSaleSlot; } - public OpenClose openClose() { return m_openClose; } - public String designatedLocation() { return m_designatedLocation; } - public String exchange() { return m_exchange; } - - public void action(Action v) { m_action = v; } - public void conid(int v) { m_conid = v; } - public void designatedLocation(String v) { m_designatedLocation = v; } - public void exchange(String v) { m_exchange = v; } - public void exemptCode(int v) { m_exemptCode = v; } - public void openClose(OpenClose v) { m_openClose = v; } - public void ratio(int v) { m_ratio = v; } - public void shortSaleSlot(int v) { m_shortSaleSlot = v; } - - public NewComboLeg() { - } - - public NewComboLeg( ComboLeg leg) { - m_conid = leg.m_conId; - m_ratio = leg.m_ratio; - m_action = Action.valueOf( leg.m_action); - m_exchange = leg.m_exchange; - m_openClose = OpenClose.get( leg.m_openClose); - m_shortSaleSlot = leg.m_shortSaleSlot; - m_designatedLocation = leg.m_designatedLocation; - m_exemptCode = leg.m_exemptCode; - } - - public ComboLeg getComboLeg() { - ComboLeg leg = new ComboLeg(); - leg.m_conId = m_conid; - leg.m_ratio = m_ratio; - leg.m_action = m_action.toString(); - leg.m_exchange = m_exchange; - leg.m_openClose = m_openClose.ordinal(); - leg.m_shortSaleSlot = m_shortSaleSlot; - leg.m_designatedLocation = m_designatedLocation; - leg.m_exemptCode = m_exemptCode; - return leg; - } - - @Override public String toString() { - return String.format( "%s %s %s", m_action, m_ratio, m_conid); - } -} diff --git a/ref/controller/NewContract.java b/ref/controller/NewContract.java deleted file mode 100644 index 170ee31..0000000 --- a/ref/controller/NewContract.java +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - -import java.util.ArrayList; -import java.util.Vector; - -import com.ib.client.ComboLeg; -import com.ib.client.Contract; -import com.ib.client.UnderComp; -import com.ib.controller.Types.Right; -import com.ib.controller.Types.SecIdType; -import com.ib.controller.Types.SecType; - -public class NewContract implements Cloneable { - private int m_conid; - private String m_symbol; - private SecType m_secType = SecType.None; - private String m_expiry; - private double m_strike; - private Right m_right = Right.None; - private String m_multiplier; // should be double - private String m_exchange; - private String m_currency; - private String m_localSymbol; - private String m_tradingClass; - private String m_primaryExch; - private SecIdType m_secIdType = SecIdType.None; - private String m_secId; - public DeltaNeutralContract m_underComp; // what is this? - private ArrayList m_comboLegs = new ArrayList(); // would be final except for clone - - public double strike() { return m_strike; } - public int conid() { return m_conid; } - public SecIdType secIdType() { return m_secIdType; } - public SecType secType() { return m_secType; } - public String currency() { return m_currency; } - public String exchange() { return m_exchange; } - public String expiry() { return m_expiry; } - public String localSymbol() { return m_localSymbol; } - public String tradingClass() { return m_tradingClass; } - public String multiplier() { return m_multiplier; } - public String primaryExch() { return m_primaryExch; } - public Right right() { return m_right; } - public String secId() { return m_secId; } - public String symbol() { return m_symbol; } - public DeltaNeutralContract underComp() { return m_underComp; } - public ArrayList comboLegs() { return m_comboLegs; } - - public void conid(int v) { m_conid = v; } - public void currency(String v) { m_currency = v; } - public void exchange(String v) { m_exchange = v; } - public void expiry(String v) { m_expiry = v; } - public void localSymbol(String v) { m_localSymbol = v; } - public void tradingClass(String v) { m_tradingClass = v; } - public void multiplier(String v) { m_multiplier = v; } - public void primaryExch(String v) { m_primaryExch = v; } - public void right(Right v) { m_right = v; } - public void secId(String v) { m_secId = v; } - public void secIdType(SecIdType v) { m_secIdType = v; } - public void secType(SecType v) { m_secType = v; } - public void strike(double v) { m_strike = v; } - public void symbol(String v) { m_symbol = v; } - public void underComp( DeltaNeutralContract v) { m_underComp = v; } - - public NewContract() { - m_secType = SecType.None; - m_secIdType = SecIdType.None; - } - - public NewContract( Contract c) { - m_conid = c.m_conId; - m_symbol = c.m_symbol; - m_secType = c.m_secType == null ? SecType.None : SecType.valueOf( c.m_secType); - m_expiry = c.m_expiry == null || c.m_expiry.equals( "0") ? "" : c.m_expiry; - m_strike = c.m_strike; - m_right = Right.get( c.m_right); - m_multiplier = c.m_multiplier; - m_exchange = c.m_exchange; - m_currency = c.m_currency; - m_localSymbol = c.m_localSymbol; - m_tradingClass = c.m_tradingClass; - m_primaryExch = c.m_primaryExch; - m_secIdType = SecIdType.get( c.m_secIdType); - m_secId = c.m_secId; - m_underComp = c.m_underComp != null ? new DeltaNeutralContract( c.m_underComp.m_conId, c.m_underComp.m_delta, c.m_underComp.m_price) : null; - - m_comboLegs.clear(); - if (c.m_comboLegs != null) { - for (ComboLeg leg : c.m_comboLegs) { - m_comboLegs.add( new NewComboLeg( leg) ); - } - } - } - - public Contract getContract() { - Contract c = new Contract(); - c.m_conId = m_conid; - c.m_symbol = m_symbol; - c.m_secType = m_secType.toString(); - c.m_expiry = m_expiry; - c.m_strike = m_strike; - c.m_right = m_right.getApiString(); - c.m_multiplier = m_multiplier; - c.m_exchange = m_exchange; - c.m_currency = m_currency; - c.m_localSymbol = m_localSymbol; - c.m_tradingClass = m_tradingClass; - c.m_primaryExch = m_primaryExch; - c.m_secIdType = m_secIdType.getApiString(); - c.m_secId = m_secId; - - if (m_underComp != null) { - c.m_underComp = new UnderComp(); - c.m_underComp.m_conId = m_underComp.conid(); - c.m_underComp.m_delta = m_underComp.delta(); - c.m_underComp.m_price = m_underComp.price(); - } - - c.m_comboLegs = new Vector(); - for (NewComboLeg leg : m_comboLegs) { - c.m_comboLegs.add( leg.getComboLeg() ); - } - - return c; - } - - /** Returns a text description that can be used for display. */ - public String description() { - StringBuilder sb = new StringBuilder(); - - if (isCombo() ) { - int i = 0; - for (NewComboLeg leg : m_comboLegs) { - if (i++ > 0) { - sb.append( "/"); - } - sb.append( leg.toString() ); - } - } - else { - sb.append( m_symbol); - app( sb, m_secType); - app( sb, m_exchange); - - if (m_exchange != null && m_exchange.equals( "SMART") && m_primaryExch != null) { - app( sb, m_primaryExch); - } - - app( sb, m_expiry); - - if (m_strike != 0) { - app( sb, m_strike); - } - - if (m_right != Right.None) { - app( sb, m_right); - } - } - - return sb.toString(); - } - - private static void app(StringBuilder buf, Object obj) { - if (obj != null) { - buf.append( " "); - buf.append( obj); - } - } - - public boolean isCombo() { - return m_comboLegs.size() > 0; - } - - @Override public String toString() { - StringBuilder sb = new StringBuilder(); - - add( sb, "conid", m_conid); - add( sb, "symbol", m_symbol); - add( sb, "secType", m_secType); - add( sb, "expiry", m_expiry); - add( sb, "strike", m_strike); - add( sb, "right", m_right); - add( sb, "multiplier", m_multiplier); - add( sb, "exchange", m_exchange); - add( sb, "currency", m_currency); - add( sb, "localSymbol", m_localSymbol); - add( sb, "tradingClass", m_tradingClass); - add( sb, "primaryExch", m_primaryExch); - add( sb, "secIdType", m_secIdType); - add( sb, "secId", m_secId); - - return sb.toString(); - } - - public static void add(StringBuilder sb, String tag, Object val) { - if (val == null || val instanceof String && ((String)val).length() == 0) { - return; - } - - sb.append( tag); - sb.append( '\t'); - sb.append( val); - sb.append( '\n'); - } - - @Override public NewContract clone() { - try { - NewContract copy = (NewContract)super.clone(); - copy.m_comboLegs = new ArrayList( copy.m_comboLegs); - return copy; - } - catch (CloneNotSupportedException e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/ref/controller/NewContractDetails.java b/ref/controller/NewContractDetails.java deleted file mode 100644 index 0931951..0000000 --- a/ref/controller/NewContractDetails.java +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - -import static com.ib.controller.NewContract.add; - -import java.util.Vector; - -import com.ib.client.ContractDetails; -import com.ib.client.TagValue; - -public class NewContractDetails { - private NewContract m_contract; - private String m_marketName; - private double m_minTick; - private int m_priceMagnifier; - private String m_orderTypes; - private String m_validExchanges; - private int m_underConid; - private String m_longName; - private String m_contractMonth; - private String m_industry; - private String m_category; - private String m_subcategory; - private String m_timeZoneId; - private String m_tradingHours; - private String m_liquidHours; - private String m_evRule; - private double m_evMultiplier; - private Vector m_secIdList; // CUSIP/ISIN/etc. - - // BOND values - private String m_cusip; - private String m_ratings; - private String m_descAppend; - private String m_bondType; - private String m_couponType; - private boolean m_callable= false; - private boolean m_putable= false; - private double m_coupon= 0; - private boolean m_convertible= false; - private String m_maturity; - private String m_issueDate; - private String m_nextOptionDate; - private String m_nextOptionType; - private boolean m_nextOptionPartial = false; - private String m_notes; - - public int conid() { return m_contract.conid(); } - public NewContract contract() { return m_contract; } - public String marketName() { return m_marketName; } - public double minTick() { return m_minTick; } - public int PripeMagnifier() { return m_priceMagnifier; } - public String orderTypes() { return m_orderTypes; } - public String validExchanges() { return m_validExchanges; } - public int underConid() { return m_underConid; } - public String longName() { return m_longName; } - public String contractMonth() { return m_contractMonth; } - public String industry() { return m_industry; } - public String category() { return m_category; } - public String subcategory() { return m_subcategory; } - public String timeZoneId() { return m_timeZoneId; } - public String tradingHours() { return m_tradingHours; } - public String liquidHours() { return m_liquidHours; } - public String evRule() { return m_evRule; } - public double evMultiplier() { return m_evMultiplier; } - public Vector secIdList() { return m_secIdList; } - public String cusip() { return m_cusip; } - public String ratings() { return m_ratings; } - public String descAppend() { return m_descAppend; } - public String bondType() { return m_bondType; } - public String couponType() { return m_couponType; } - public boolean callable() { return m_callable; } - public boolean putable() { return m_putable; } - public double coupon() { return m_coupon; } - public boolean convertible() { return m_convertible; } - public String maturity() { return m_maturity; } - public String issueDate() { return m_issueDate; } - public String nextOptionDate() { return m_nextOptionDate; } - public String nextOptionType() { return m_nextOptionType; } - public boolean nextOptionPartial() { return m_nextOptionPartial; } - public String notes() { return m_notes; } - - public NewContractDetails( ContractDetails other) { - m_contract = new NewContract( other.m_summary); - m_marketName = other.m_marketName; - m_minTick = other.m_minTick; - m_priceMagnifier = other.m_priceMagnifier; - m_orderTypes = other.m_orderTypes; - m_validExchanges = other.m_validExchanges; - m_underConid = other.m_underConId; - m_longName = other.m_longName; - m_contractMonth = other.m_contractMonth; - m_industry = other.m_industry; - m_category = other.m_category; - m_subcategory = other.m_subcategory; - m_timeZoneId = other.m_timeZoneId; - m_tradingHours = other.m_tradingHours; - m_liquidHours = other.m_liquidHours; - m_evRule = other.m_evRule; - m_evMultiplier = other.m_evMultiplier; - m_secIdList = other.m_secIdList; - m_cusip = other.m_cusip; - m_ratings = other.m_ratings; - m_descAppend = other.m_descAppend; - m_bondType = other.m_bondType; - m_couponType = other.m_couponType; - m_callable = other.m_callable; - m_putable = other.m_putable; - m_coupon = other.m_coupon; - m_convertible = other.m_convertible; - m_maturity = other.m_maturity; - m_issueDate = other.m_issueDate; - m_nextOptionDate = other.m_nextOptionDate; - m_nextOptionType = other.m_nextOptionType; - m_nextOptionPartial = other.m_nextOptionPartial; - m_notes = other.m_notes; - } - - @Override public String toString() { - StringBuilder sb = new StringBuilder( m_contract.toString() ); - - add( sb, "marketName", m_marketName); - add( sb, "minTick", m_minTick); - add( sb, "priceMagnifier", m_priceMagnifier); - add( sb, "orderTypes", m_orderTypes); - add( sb, "validExchanges", m_validExchanges); - add( sb, "underConId", m_underConid); - add( sb, "longName", m_longName); - add( sb, "contractMonth", m_contractMonth); - add( sb, "industry", m_industry); - add( sb, "category", m_category); - add( sb, "subcategory", m_subcategory); - add( sb, "timeZoneId", m_timeZoneId); - add( sb, "tradingHours", m_tradingHours); - add( sb, "liquidHours", m_liquidHours); - add( sb, "evRule", m_evRule); - add( sb, "evMultiplier", m_evMultiplier); - - add( sb, "cusip", m_cusip); - add( sb, "ratings", m_ratings); - add( sb, "descAppend", m_descAppend); - add( sb, "bondType", m_bondType); - add( sb, "couponType", m_couponType); - add( sb, "callable", m_callable); - add( sb, "putable", m_putable); - add( sb, "coupon", m_coupon); - add( sb, "convertible", m_convertible); - add( sb, "maturity", m_maturity); - add( sb, "issueDate", m_issueDate); - add( sb, "nextOptionDate", m_nextOptionDate); - add( sb, "nextOptionType", m_nextOptionType); - add( sb, "nextOptionPartial", m_nextOptionPartial); - add( sb, "notes", m_notes); - - return sb.toString(); - } -} diff --git a/ref/controller/NewOrder.java b/ref/controller/NewOrder.java deleted file mode 100644 index 2c43bfe..0000000 --- a/ref/controller/NewOrder.java +++ /dev/null @@ -1,359 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - -import java.util.ArrayList; -import java.util.List; - -import com.ib.client.Order; -import com.ib.client.TagValue; -import com.ib.controller.Types.Action; -import com.ib.controller.Types.AlgoStrategy; -import com.ib.controller.Types.HedgeType; -import com.ib.controller.Types.Method; -import com.ib.controller.Types.OcaType; -import com.ib.controller.Types.ReferencePriceType; -import com.ib.controller.Types.Rule80A; -import com.ib.controller.Types.TimeInForce; -import com.ib.controller.Types.TriggerMethod; -import com.ib.controller.Types.VolatilityType; - -public class NewOrder { - // order id's - private int m_clientId; - private int m_orderId; - private long m_permId; - private int m_parentId; - - // primary attributes - private String m_account; - private Action m_action = Action.BUY; - private int m_totalQuantity; - private int m_displaySize; - private OrderType m_orderType = OrderType.LMT; - private double m_lmtPrice = Double.MAX_VALUE; - private double m_auxPrice = Double.MAX_VALUE; - private TimeInForce m_tif = TimeInForce.DAY; - - // secondary attributes - private boolean m_allOrNone; - private boolean m_blockOrder; - private boolean m_eTradeOnly; - private boolean m_firmQuoteOnly; - private boolean m_hidden; - private boolean m_notHeld; - private boolean m_optOutSmartRouting; - private boolean m_outsideRth; - private boolean m_sweepToFill; - private double m_delta = Double.MAX_VALUE; - private double m_discretionaryAmt = Double.MAX_VALUE; - private double m_nbboPriceCap = Double.MAX_VALUE; - private double m_percentOffset = Double.MAX_VALUE; // for Relative orders; specify the decimal, e.g. .04 not 4 - private double m_startingPrice = Double.MAX_VALUE; - private double m_stockRangeLower = Double.MAX_VALUE; - private double m_stockRangeUpper = Double.MAX_VALUE; - private double m_stockRefPrice = Double.MAX_VALUE; - private double m_trailingPercent = Double.MAX_VALUE; // for Trailing Stop orders; specify the percentage, e.g. 3, not .03 - private double m_trailStopPrice = Double.MAX_VALUE; // stop price for Trailing Stop orders - private int m_minQty = Integer.MAX_VALUE; - private String m_goodAfterTime; // FORMAT: 20060505 08:00:00 EST - private String m_goodTillDate; // FORMAT: 20060505 08:00:00 EST or 20060505 - private String m_ocaGroup; // one cancels all group name - private String m_orderRef; - private Rule80A m_rule80A = Rule80A.None; - private OcaType m_ocaType = OcaType.None; - private TriggerMethod m_triggerMethod = TriggerMethod.Default; - - // advisor allocation orders - private String m_faGroup; - private Method m_faMethod = Method.None; - private String m_faPercentage; - private String m_faProfile; - - // volatility orders - private double m_volatility = Double.MAX_VALUE; // enter percentage not decimal, e.g. 2 not .02 - private VolatilityType m_volatilityType = VolatilityType.None; - private boolean m_continuousUpdate; - private ReferencePriceType m_referencePriceType = ReferencePriceType.None; - private OrderType m_deltaNeutralOrderType = OrderType.None; - private double m_deltaNeutralAuxPrice = Double.MAX_VALUE; - private int m_deltaNeutralConId; - - // scale orders - private int m_scaleInitLevelSize = Integer.MAX_VALUE; - private int m_scaleSubsLevelSize = Integer.MAX_VALUE; - private double m_scalePriceIncrement = Double.MAX_VALUE; - private double m_scalePriceAdjustValue = Double.MAX_VALUE; - private int m_scalePriceAdjustInterval = Integer.MAX_VALUE; - private double m_scaleProfitOffset = Double.MAX_VALUE; - private boolean m_scaleAutoReset; - private int m_scaleInitPosition = Integer.MAX_VALUE; - private int m_scaleInitFillQty = Integer.MAX_VALUE; - private boolean m_scaleRandomPercent; - private String m_scaleTable; - - // hedge orders - private HedgeType m_hedgeType = HedgeType.None; - private String m_hedgeParam; // beta value for beta hedge (in range 0-1), ratio for pair hedge - - // algo orders - private AlgoStrategy m_algoStrategy = AlgoStrategy.None; - private final ArrayList m_algoParams = new ArrayList(); - - // combo orders - private final ArrayList m_smartComboRoutingParams = new ArrayList(); - private final ArrayList m_orderComboLegs = new ArrayList(); // array of leg prices - - // processing control - private boolean m_whatIf; - private boolean m_transmit = true; // if false, order will be sent to TWS but not transmited to server - private boolean m_overridePercentageConstraints; - - // Institutional/cleared away -// private String m_openClose = "O"; // O=Open, C=Close -// private int m_origin; // 0=Customer, 1=Firm -// private int m_shortSaleSlot; // 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action="SSHORT -// private String m_designatedLocation; // set when slot=2 only. -// private int m_exemptCode = -1; -// private String m_settlingFirm; -// private String m_clearingAccount; // True beneficiary of the order -// private String m_clearingIntent; // "" (Default), "IB", "Away", "PTA" (PostTrade) -// private int m_auctionStrategy; // 1=AUCTION_MATCH, 2=AUCTION_IMPROVEMENT, 3=AUCTION_TRANSPARENT // need type for this. ps -// private String m_deltaNeutralSettlingFirm; -// private String m_deltaNeutralClearingAccount; -// private String m_deltaNeutralClearingIntent; -// private double m_basisPoints; // EFP orders only, download only -// private int m_basisPointsType; // EFP orders only, download only - - - - // getters - public Action action() { return m_action; } - public boolean allOrNone() { return m_allOrNone; } - public boolean blockOrder() { return m_blockOrder; } - public boolean eTradeOnly() { return m_eTradeOnly; } - public boolean firmQuoteOnly() { return m_firmQuoteOnly; } - public boolean hidden() { return m_hidden; } - public boolean notHeld() { return m_notHeld; } - public boolean optOutSmartRouting() { return m_optOutSmartRouting; } - public boolean outsideRth() { return m_outsideRth; } - public boolean overridePercentageConstraints() { return m_overridePercentageConstraints; } - public boolean scaleAutoReset() { return m_scaleAutoReset; } - public boolean scaleRandomPercent() { return m_scaleRandomPercent; } - public boolean sweepToFill() { return m_sweepToFill; } - public boolean transmit() { return m_transmit; } - public boolean whatIf() { return m_whatIf; } - public double auxPrice() { return m_auxPrice; } - public double delta() { return m_delta; } - public double deltaNeutralAuxPrice() { return m_deltaNeutralAuxPrice; } - public double discretionaryAmt() { return m_discretionaryAmt; } - public double lmtPrice() { return m_lmtPrice; } - public double nbboPriceCap() { return m_nbboPriceCap; } - public double percentOffset() { return m_percentOffset; } - public double scalePriceAdjustValue() { return m_scalePriceAdjustValue; } - public double scalePriceIncrement() { return m_scalePriceIncrement; } - public double scaleProfitOffset() { return m_scaleProfitOffset; } - public double startingPrice() { return m_startingPrice; } - public double stockRangeLower() { return m_stockRangeLower; } - public double stockRangeUpper() { return m_stockRangeUpper; } - public double stockRefPrice() { return m_stockRefPrice; } - public double trailingPercent() { return m_trailingPercent; } - public double trailStopPrice() { return m_trailStopPrice; } - public double volatility() { return m_volatility; } - public int clientId() { return m_clientId; } - public boolean continuousUpdate() { return m_continuousUpdate; } - public int deltaNeutralConId() { return m_deltaNeutralConId; } - public int displaySize() { return m_displaySize; } - public int minQty() { return m_minQty; } - public int orderId() { return m_orderId; } - public int parentId() { return m_parentId; } - public int scaleInitFillQty() { return m_scaleInitFillQty; } - public int scaleInitLevelSize() { return m_scaleInitLevelSize; } - public int scaleInitPosition() { return m_scaleInitPosition; } - public int scalePriceAdjustInterval() { return m_scalePriceAdjustInterval; } - public int scaleSubsLevelSize() { return m_scaleSubsLevelSize; } - public int totalQuantity() { return m_totalQuantity; } - public long permId() { return m_permId; } - public Method faMethod() { return m_faMethod; } - public OcaType ocaType() { return m_ocaType; } - public OrderType deltaNeutralOrderType() { return m_deltaNeutralOrderType; } - public OrderType orderType() { return m_orderType; } - public ReferencePriceType referencePriceType() { return m_referencePriceType; } - public Rule80A rule80A() { return m_rule80A; } - public String account() { return m_account; } - public AlgoStrategy algoStrategy() { return m_algoStrategy; } - public String faGroup() { return m_faGroup; } - public String faPercentage() { return m_faPercentage; } - public String faProfile() { return m_faProfile; } - public String goodAfterTime() { return m_goodAfterTime; } - public String goodTillDate() { return m_goodTillDate; } - public String hedgeParam() { return m_hedgeParam; } - public HedgeType hedgeType() { return m_hedgeType; } - public String ocaGroup() { return m_ocaGroup; } - public String orderRef() { return m_orderRef; } - public TimeInForce tif() { return m_tif; } - public VolatilityType volatilityType() { return m_volatilityType; } - public ArrayList smartComboRoutingParams() { return m_smartComboRoutingParams; } - public TriggerMethod triggerMethod() { return m_triggerMethod; } - public ArrayList algoParams() { return m_algoParams; } - public ArrayList orderComboLegs() { return m_orderComboLegs; } - public String scaleTable() { return m_scaleTable; } - - // setters - public void account(String v) { m_account = v; } - public void action(Action v) { m_action = v; } - public void algoStrategy(AlgoStrategy v) { m_algoStrategy = v; } - public void allOrNone(boolean v) { m_allOrNone = v; } - public void auxPrice(double v) { m_auxPrice = v; } - public void blockOrder(boolean v) { m_blockOrder = v; } - public void clientId(int v) { m_clientId = v; } - public void continuousUpdate(boolean v) { m_continuousUpdate = v; } - public void delta(double v) { m_delta = v; } - public void deltaNeutralAuxPrice(double v) { m_deltaNeutralAuxPrice = v; } - public void deltaNeutralConId(int v) { m_deltaNeutralConId = v; } - public void deltaNeutralOrderType(OrderType v) { m_deltaNeutralOrderType = v; } - public void discretionaryAmt(double v) { m_discretionaryAmt = v; } - public void displaySize(int v) { m_displaySize = v; } - public void eTradeOnly(boolean v) { m_eTradeOnly = v; } - public void faGroup(String v) { m_faGroup = v; } - public void faMethod(Method v) { m_faMethod = v; } - public void faPercentage(String v) { m_faPercentage = v; } - public void faProfile(String v) { m_faProfile = v; } - public void firmQuoteOnly(boolean v) { m_firmQuoteOnly = v; } - public void goodAfterTime(String v) { m_goodAfterTime = v; } - public void goodTillDate(String v) { m_goodTillDate = v; } - public void hedgeParam(String v) { m_hedgeParam = v; } - public void hedgeType(HedgeType v) { m_hedgeType = v; } - public void hidden(boolean v) { m_hidden = v; } - public void lmtPrice(double v) { m_lmtPrice = v; } - public void minQty(int v) { m_minQty = v; } - public void nbboPriceCap(double v) { m_nbboPriceCap = v; } - public void notHeld(boolean v) { m_notHeld = v; } - public void ocaGroup(String v) { m_ocaGroup = v; } - public void ocaType(OcaType v) { m_ocaType = v; } - public void optOutSmartRouting(boolean v) { m_optOutSmartRouting = v; } - public void orderId(int v) { m_orderId = v; } - public void orderRef(String v) { m_orderRef = v; } - public void orderType(OrderType v) { m_orderType = v; } - public void outsideRth(boolean v) { m_outsideRth = v; } - public void overridePercentageConstraints(boolean v) { m_overridePercentageConstraints = v; } - public void parentId(int v) { m_parentId = v; } - public void percentOffset(double v) { m_percentOffset = v; } - public void permId(long v) { m_permId = v; } - public void referencePriceType(ReferencePriceType v) { m_referencePriceType = v; } - public void rule80A(Rule80A v) { m_rule80A = v; } - public void scaleAutoReset(boolean v) { m_scaleAutoReset = v; } - public void scaleInitFillQty(int v) { m_scaleInitFillQty = v; } - public void scaleInitLevelSize(int v) { m_scaleInitLevelSize = v; } - public void scaleInitPosition(int v) { m_scaleInitPosition = v; } - public void scalePriceAdjustInterval(int v) { m_scalePriceAdjustInterval = v; } - public void scalePriceAdjustValue(double v) { m_scalePriceAdjustValue = v; } - public void scalePriceIncrement(double v) { m_scalePriceIncrement = v; } - public void scaleProfitOffset(double v) { m_scaleProfitOffset = v; } - public void scaleRandomPercent(boolean v) { m_scaleRandomPercent = v; } - public void scaleSubsLevelSize(int v) { m_scaleSubsLevelSize = v; } - public void startingPrice(double v) { m_startingPrice = v; } - public void stockRangeLower(double v) { m_stockRangeLower = v; } - public void stockRangeUpper(double v) { m_stockRangeUpper = v; } - public void stockRefPrice(double v) { m_stockRefPrice = v; } - public void sweepToFill(boolean v) { m_sweepToFill = v; } - public void tif(TimeInForce v) { m_tif = v; } - public void totalQuantity(int v) { m_totalQuantity = v; } - public void trailingPercent(double v) { m_trailingPercent = v; } - public void trailStopPrice(double v) { m_trailStopPrice = v; } - public void transmit(boolean v) { m_transmit = v; } - public void triggerMethod(TriggerMethod v) { m_triggerMethod = v; } - public void volatility(double v) { m_volatility = v; } - public void volatilityType(VolatilityType v) { m_volatilityType = v; } - public void whatIf(boolean v) { m_whatIf = v; } - public void scaleTable(String v) { m_scaleTable = v; } - - public int auctionStrategy() { return 0; } - - public NewOrder() { - } - - public NewOrder( Order order) { - m_clientId = order.m_clientId; - m_orderId = order.m_orderId; - m_permId = order.m_permId; - m_parentId = order.m_parentId; - m_account = order.m_account; - m_action = Action.valueOf( order.m_action); - m_totalQuantity = order.m_totalQuantity; - m_displaySize = order.m_displaySize; - m_orderType = OrderType.get( order.m_orderType); - m_lmtPrice = order.m_lmtPrice; - m_auxPrice = order.m_auxPrice; - m_tif = TimeInForce.valueOf( order.m_tif); - m_allOrNone = order.m_allOrNone; - m_blockOrder = order.m_blockOrder; - m_eTradeOnly = order.m_eTradeOnly; - m_firmQuoteOnly = order.m_firmQuoteOnly; - m_hidden = order.m_hidden; - m_notHeld = order.m_notHeld; - m_optOutSmartRouting = order.m_optOutSmartRouting; - m_outsideRth = order.m_outsideRth; - m_sweepToFill = order.m_sweepToFill; - m_delta = order.m_delta; - m_discretionaryAmt = order.m_discretionaryAmt; - m_nbboPriceCap = order.m_nbboPriceCap; - m_percentOffset = order.m_percentOffset; - m_startingPrice = order.m_startingPrice; - m_stockRangeLower = order.m_stockRangeLower; - m_stockRangeUpper = order.m_stockRangeUpper; - m_stockRefPrice = order.m_stockRefPrice; - m_trailingPercent = order.m_trailingPercent; - m_trailStopPrice = order.m_trailStopPrice; - m_minQty = order.m_minQty; - m_goodAfterTime = order.m_goodAfterTime; - m_goodTillDate = order.m_goodTillDate; - m_ocaGroup = order.m_ocaGroup; - m_orderRef = order.m_orderRef; - m_rule80A = Rule80A.get( order.m_rule80A); - m_ocaType = OcaType.get( order.m_ocaType); - m_triggerMethod = TriggerMethod.get( order.m_triggerMethod); - m_faGroup = order.m_faGroup; - m_faMethod = Method.get( order.m_faMethod); - m_faPercentage = order.m_faPercentage; - m_faProfile = order.m_faProfile; - m_volatility = order.m_volatility; - m_volatilityType = VolatilityType.get( order.m_volatilityType); - m_continuousUpdate = order.m_continuousUpdate == 1; - m_referencePriceType = ReferencePriceType.get( order.m_referencePriceType); - m_deltaNeutralOrderType = OrderType.get( order.m_deltaNeutralOrderType); - m_deltaNeutralAuxPrice = order.m_deltaNeutralAuxPrice; - m_deltaNeutralConId = order.m_deltaNeutralConId; - m_scaleInitLevelSize = order.m_scaleInitLevelSize; - m_scaleSubsLevelSize = order.m_scaleSubsLevelSize; - m_scalePriceIncrement = order.m_scalePriceIncrement; - m_scalePriceAdjustValue = order.m_scalePriceAdjustValue; - m_scalePriceAdjustInterval = order.m_scalePriceAdjustInterval; - m_scaleProfitOffset = order.m_scaleProfitOffset; - m_scaleAutoReset = order.m_scaleAutoReset; - m_scaleInitPosition = order.m_scaleInitPosition; - m_scaleInitFillQty = order.m_scaleInitFillQty; - m_scaleRandomPercent = order.m_scaleRandomPercent; - m_hedgeType = HedgeType.get( order.m_hedgeType); - m_hedgeParam = order.m_hedgeParam; - m_algoStrategy = AlgoStrategy.get( order.m_algoStrategy); - m_whatIf = order.m_whatIf; - m_transmit = order.m_transmit; - m_overridePercentageConstraints = order.m_overridePercentageConstraints; - - fill( m_smartComboRoutingParams, order.m_smartComboRoutingParams); - fill( m_orderComboLegs, order.m_orderComboLegs); - fill( m_algoParams, order.m_algoParams); - } - - public static void fill(List list1, List list2) { - list1.clear(); - - if (list2 != null) { - for( Object obj : list2) { - list1.add( obj); - } - } - } -} diff --git a/ref/controller/NewOrderState.java b/ref/controller/NewOrderState.java deleted file mode 100644 index c912e0f..0000000 --- a/ref/controller/NewOrderState.java +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - -import com.ib.client.OrderState; - -public class NewOrderState { - private OrderStatus m_status; - private String m_initMargin; - private String m_maintMargin; - private String m_equityWithLoan; - private double m_commission; - private double m_minCommission; - private double m_maxCommission; - private String m_commissionCurrency; - private String m_warningText; - - public double commission() { return m_commission; } - public double maxCommission() { return m_maxCommission; } - public double minCommission() { return m_minCommission; } - public OrderStatus status() { return m_status; } - public String commissionCurrency() { return m_commissionCurrency; } - public String equityWithLoan() { return m_equityWithLoan; } - public String initMargin() { return m_initMargin; } - public String maintMargin() { return m_maintMargin; } - public String warningText() { return m_warningText; } - - public void commission(double v) { m_commission = v; } - public void commissionCurrency(String v) { m_commissionCurrency = v; } - public void equityWithLoan(String v) { m_equityWithLoan = v; } - public void initMargin(String v) { m_initMargin = v; } - public void maintMargin(String v) { m_maintMargin = v; } - public void maxCommission(double v) { m_maxCommission = v; } - public void minCommission(double v) { m_minCommission = v; } - public void status(OrderStatus v) { m_status = v; } - public void warningText(String v) { m_warningText = v; } - - public NewOrderState(OrderState orderState) { - m_status = OrderStatus.valueOf( orderState.m_status); - m_initMargin = orderState.m_initMargin; - m_maintMargin = orderState.m_maintMargin; - m_equityWithLoan = orderState.m_equityWithLoan; - m_commission = orderState.m_commission; - m_minCommission = orderState.m_minCommission; - m_maxCommission = orderState.m_maxCommission; - m_commissionCurrency = orderState.m_commissionCurrency; - m_warningText = orderState.m_warningText; - } -} diff --git a/ref/controller/NewTickType.java b/ref/controller/NewTickType.java deleted file mode 100644 index 0842464..0000000 --- a/ref/controller/NewTickType.java +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - - -public enum NewTickType { - BID_SIZE, - BID, - ASK, - ASK_SIZE, - LAST, - LAST_SIZE, - HIGH, - LOW, - VOLUME, - CLOSE, - BID_OPTION, - ASK_OPTION, - LAST_OPTION, - MODEL_OPTION, - OPEN, - LOW_13_WEEK, - HIGH_13_WEEK, - LOW_26_WEEK, - HIGH_26_WEEK, - LOW_52_WEEK, - HIGH_52_WEEK, - AVG_VOLUME, - OPEN_INTEREST, - OPTION_HISTORICAL_VOL, - OPTION_IMPLIED_VOL, - OPTION_BID_EXCH, - OPTION_ASK_EXCH, - OPTION_CALL_OPEN_INTEREST, - OPTION_PUT_OPEN_INTEREST, - OPTION_CALL_VOLUME, - OPTION_PUT_VOLUME, - INDEX_FUTURE_PREMIUM, - BID_EXCH, // string - ASK_EXCH, // string - AUCTION_VOLUME, - AUCTION_PRICE, - AUCTION_IMBALANCE, - MARK_PRICE, - BID_EFP_COMPUTATION, - ASK_EFP_COMPUTATION, - LAST_EFP_COMPUTATION, - OPEN_EFP_COMPUTATION, - HIGH_EFP_COMPUTATION, - LOW_EFP_COMPUTATION, - CLOSE_EFP_COMPUTATION, - LAST_TIMESTAMP, // string - SHORTABLE, - FUNDAMENTAL_RATIOS, // string - RT_VOLUME, // string - HALTED, - BID_YIELD, - ASK_YIELD, - LAST_YIELD, - CUST_OPTION_COMPUTATION, - TRADE_COUNT, - TRADE_RATE, - VOLUME_RATE, - LAST_RTH_TRADE, - RT_HISTORICAL_VOL; - - public static NewTickType get( int ordinal) { - return Types.getEnum( ordinal, values() ); - } - - public static String getField( int ordinal) { - NewTickType tickType = get( ordinal); - return tickType.toString(); - } -} diff --git a/ref/controller/PairPanel.java b/ref/controller/PairPanel.java deleted file mode 100644 index 60d50c4..0000000 --- a/ref/controller/PairPanel.java +++ /dev/null @@ -1,6 +0,0 @@ -/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms - * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ - -package com.ib.controller; - - diff --git a/ref/controller/Position.java b/ref/controller/Position.java index 819fe93..5819689 100644 --- a/ref/controller/Position.java +++ b/ref/controller/Position.java @@ -3,24 +3,27 @@ package com.ib.controller; +import com.ib.client.Contract; + + public class Position { - private NewContract m_contract; + private Contract m_contract; private String m_account; - private int m_position; + private double m_position; private double m_marketPrice; private double m_marketValue; private double m_averageCost; private double m_unrealPnl; private double m_realPnl; - public NewContract contract() { return m_contract; } + public Contract contract() { return m_contract; } public int conid() { return m_contract.conid(); } public double averageCost() { return m_averageCost;} public double marketPrice() { return m_marketPrice;} public double marketValue() { return m_marketValue;} public double realPnl() { return m_realPnl;} public double unrealPnl() { return m_unrealPnl;} - public int position() { return m_position;} + public double position() { return m_position;} public String account() { return m_account;} // public void account(String v) { m_account = v;} @@ -31,7 +34,7 @@ public class Position { // public void realPnl(double v) { m_realPnl = v;} // public void unrealPnl(double v) { m_unrealPnl = v;} - public Position( NewContract contract, String account, int position, double marketPrice, double marketValue, double averageCost, double unrealPnl, double realPnl) { + public Position( Contract contract, String account, double position, double marketPrice, double marketValue, double averageCost, double unrealPnl, double realPnl) { m_contract = contract; m_account = account; m_position = position; diff --git a/ref/controller/Profile.java b/ref/controller/Profile.java index 1a87223..4e0c92f 100644 --- a/ref/controller/Profile.java +++ b/ref/controller/Profile.java @@ -4,18 +4,21 @@ package com.ib.controller; import java.util.ArrayList; +import java.util.List; import java.util.StringTokenizer; +import com.ib.client.Types; + public class Profile { static final String SEP = "/"; private String m_name; private Type m_type; - private ArrayList m_allocations = new ArrayList(); + private List m_allocations = new ArrayList<>(); public String name() { return m_name; } public Type type() { return m_type; } - public ArrayList allocations() { return m_allocations; } + public List allocations() { return m_allocations; } public void name( String v) { m_name = v; } public void type( Type v) { m_type = v; } @@ -37,13 +40,13 @@ public void setAllocations(String val) { } } - public static enum Type { + public enum Type { NONE, Percents, Ratios, Shares; public static Type get( int ordinal) { return Types.getEnum( ordinal, values() ); } - }; + } public static class Allocation { private String m_account;