summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2018-08-24 16:35:43 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2018-08-24 16:35:43 +0200
commit8a1ce9788b314deddde505567ca5cfaed75d0c27 (patch)
treee01bd956dfff21613102edd9ac7a95c03faffb20
parent945b392f1ae7051d1fab5b5273a7b52fa958c886 (diff)
downloadtwstest-8a1ce9788b314deddde505567ca5cfaed75d0c27.tar.gz
twstest-8a1ce9788b314deddde505567ca5cfaed75d0c27.tar.bz2
initial import and fix of Java API 9.73.07
-rw-r--r--README20
-rwxr-xr-xapi/com/ib/client/Bar.java60
-rwxr-xr-xapi/com/ib/client/BitMask.java42
-rwxr-xr-xapi/com/ib/client/Builder.java173
-rwxr-xr-xapi/com/ib/client/ComboLeg.java129
-rwxr-xr-xapi/com/ib/client/CommissionReport.java39
-rwxr-xr-xapi/com/ib/client/Contract.java280
-rwxr-xr-xapi/com/ib/client/ContractCondition.java65
-rwxr-xr-xapi/com/ib/client/ContractDescription.java56
-rwxr-xr-xapi/com/ib/client/ContractDetails.java232
-rwxr-xr-xapi/com/ib/client/ContractLookuper.java10
-rwxr-xr-xapi/com/ib/client/DefaultEWrapper.java526
-rwxr-xr-xapi/com/ib/client/DeltaNeutralContract.java69
-rwxr-xr-xapi/com/ib/client/DepthMktDataDescription.java37
-rwxr-xr-xapi/com/ib/client/EClient.java3783
-rwxr-xr-xapi/com/ib/client/EClientErrors.java107
-rwxr-xr-xapi/com/ib/client/EClientMsgSink.java9
-rwxr-xr-xapi/com/ib/client/EClientSocket.java240
-rwxr-xr-xapi/com/ib/client/EClientSocketSSL.java92
-rwxr-xr-xapi/com/ib/client/EDecoder.java2291
-rwxr-xr-xapi/com/ib/client/EJavaSignal.java33
-rwxr-xr-xapi/com/ib/client/EMessage.java34
-rwxr-xr-xapi/com/ib/client/EReader.java188
-rwxr-xr-xapi/com/ib/client/EReaderSignal.java9
-rwxr-xr-xapi/com/ib/client/ESocket.java40
-rwxr-xr-xapi/com/ib/client/ETransport.java11
-rwxr-xr-xapi/com/ib/client/EWrapper.java107
-rwxr-xr-xapi/com/ib/client/EWrapperMsgGenerator.java833
-rwxr-xr-xapi/com/ib/client/Execution.java154
-rwxr-xr-xapi/com/ib/client/ExecutionCondition.java67
-rwxr-xr-xapi/com/ib/client/ExecutionFilter.java71
-rwxr-xr-xapi/com/ib/client/FamilyCode.java25
-rwxr-xr-xapi/com/ib/client/HistogramEntry.java50
-rwxr-xr-xapi/com/ib/client/HistoricalTick.java28
-rwxr-xr-xapi/com/ib/client/HistoricalTickBidAsk.java47
-rwxr-xr-xapi/com/ib/client/HistoricalTickLast.java46
-rwxr-xr-xapi/com/ib/client/IApiEnum.java8
-rwxr-xr-xapi/com/ib/client/MarginCondition.java37
-rwxr-xr-xapi/com/ib/client/MarketDataType.java49
-rwxr-xr-xapi/com/ib/client/NewsProvider.java25
-rwxr-xr-xapi/com/ib/client/OperatorCondition.java47
-rwxr-xr-xapi/com/ib/client/Order.java672
-rwxr-xr-xapi/com/ib/client/OrderComboLeg.java40
-rwxr-xr-xapi/com/ib/client/OrderCondition.java75
-rwxr-xr-xapi/com/ib/client/OrderConditionType.java31
-rwxr-xr-xapi/com/ib/client/OrderState.java132
-rwxr-xr-xapi/com/ib/client/OrderStatus.java31
-rwxr-xr-xapi/com/ib/client/OrderType.java74
-rwxr-xr-xapi/com/ib/client/PercentChangeCondition.java42
-rwxr-xr-xapi/com/ib/client/PriceCondition.java73
-rwxr-xr-xapi/com/ib/client/PriceIncrement.java25
-rwxr-xr-xapi/com/ib/client/ScannerSubscription.java76
-rwxr-xr-xapi/com/ib/client/SoftDollarTier.java81
-rwxr-xr-xapi/com/ib/client/TagValue.java38
-rwxr-xr-xapi/com/ib/client/TickAttr.java50
-rwxr-xr-xapi/com/ib/client/TickByTick.java102
-rwxr-xr-xapi/com/ib/client/TickType.java124
-rwxr-xr-xapi/com/ib/client/TimeCondition.java37
-rwxr-xr-xapi/com/ib/client/Types.java372
-rwxr-xr-xapi/com/ib/client/Util.java118
-rwxr-xr-xapi/com/ib/client/VolumeCondition.java42
-rwxr-xr-xapi/com/ib/contracts/ComboContract.java24
-rwxr-xr-xapi/com/ib/contracts/FutContract.java24
-rwxr-xr-xapi/com/ib/contracts/OptContract.java23
-rwxr-xr-xapi/com/ib/contracts/StkContract.java16
-rwxr-xr-xapi/com/ib/controller/AccountSummaryTag.java46
-rwxr-xr-xapi/com/ib/controller/AdvisorUtil.java335
-rwxr-xr-xapi/com/ib/controller/Alias.java19
-rwxr-xr-xapi/com/ib/controller/ApiConnection.java81
-rwxr-xr-xapi/com/ib/controller/ApiController.java1898
-rwxr-xr-xapi/com/ib/controller/Bar.java53
-rwxr-xr-xapi/com/ib/controller/ConcurrentHashSet.java52
-rwxr-xr-xapi/com/ib/controller/Formats.java58
-rwxr-xr-xapi/com/ib/controller/Group.java34
-rwxr-xr-xapi/com/ib/controller/Instrument.java35
-rwxr-xr-xapi/com/ib/controller/LocationCode.java102
-rwxr-xr-xapi/com/ib/controller/MarketValueTag.java47
-rwxr-xr-xapi/com/ib/controller/Position.java39
-rwxr-xr-xapi/com/ib/controller/Profile.java65
-rwxr-xr-xapi/com/ib/controller/ScanCode.java111
-rwxr-xr-xapi/com/ib/controller/TradeId.java18
-rwxr-xr-xapi/pom.xml26
82 files changed, 15493 insertions, 17 deletions
diff --git a/README b/README
index 746d58d..0b52239 100644
--- a/README
+++ b/README
@@ -6,13 +6,11 @@ https://www.interactivebrokers.com/en/index.php?f=5041&ns=T
Java
----
-twsapi_macunix.971.01.jar
+Official TWAPI for Windows
-enthaelt C++ und Java-Code.
+API_Version=9.73.07 (git 85a935366658cf31aac9fa37a27ac1f9d5146b85)
-Der C++-Code macht nur Sinn, wenn man ein Php-Binding
-oder ein CLI hat (system ''), das Buildenvironment
-ist wohl zu haarig.
+TODO from here:
jar xvf twsapi_macunix.971.01.jar
cd IBJts/source/JavaClient
@@ -29,15 +27,3 @@ javac -cp ../../javaclient.jar TestJavaClient/Main.java TestJavaClient/SampleFra
# keine chance, praedikat Katastrophe!
# Packaging-Regeln werden verletzt:
#package TestJavaClient;
-
-c++
----
-
-https://github.com/rudimeier/twsapi
-https://github.com/rudimeier/twstools
-
-CLI
-
-Soweit keine PHP-Bindings gefunden.
-
-Der autoconf-Support tut allerdings gar nicht.
diff --git a/api/com/ib/client/Bar.java b/api/com/ib/client/Bar.java
new file mode 100755
index 0000000..bbd56c5
--- /dev/null
+++ b/api/com/ib/client/Bar.java
@@ -0,0 +1,60 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/BitMask.java b/api/com/ib/client/BitMask.java
new file mode 100755
index 0000000..b2cf197
--- /dev/null
+++ b/api/com/ib/client/BitMask.java
@@ -0,0 +1,42 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/Builder.java b/api/com/ib/client/Builder.java
new file mode 100755
index 0000000..db4b847
--- /dev/null
+++ b/api/com/ib/client/Builder.java
@@ -0,0 +1,173 @@
+/* Copyright (C) 2018 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;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/** This class is used to build messages so the entire message can be
+ * sent to the socket in a single write. */
+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;
+
+ 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) );
+ }
+
+ public void send( boolean a) {
+ send( a ? 1 : 0);
+ }
+
+ public void send( IApiEnum a) {
+ send( a == null ? null : a.getApiString() );
+ }
+
+ public void send( String a) {
+ if (a != null) {
+ byte[] buffer = a.getBytes(StandardCharsets.UTF_8);
+ m_sb.write( buffer, 0, buffer.length );
+ }
+ m_sb.write( SEP);
+ }
+
+ public void send( byte[] bytes ) {
+ if ( bytes != null ) {
+ m_sb.write( bytes, 0, bytes.length );
+ }
+ }
+
+ public void send(List<TagValue> miscOptions) {
+ String miscOptionsString = Optional.ofNullable(miscOptions).orElse(new ArrayList<TagValue>()).stream().
+ map(option -> option.m_tag + "=" + option.m_value + ";").reduce("", (sum, option) -> sum + option);
+
+ send(miscOptionsString);
+ }
+
+ public void send(Contract contract) {
+ send(contract.conid());
+ send(contract.symbol());
+ send(contract.getSecType());
+ send(contract.lastTradeDateOrContractMonth());
+ send(contract.strike());
+ send(contract.getRight());
+ send(contract.multiplier());
+ send(contract.exchange());
+ send(contract.primaryExch());
+ send(contract.currency());
+ send(contract.localSymbol());
+ send(contract.tradingClass());
+ send(contract.includeExpired() ? 1 : 0);
+ }
+
+ 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 );
+ }
+ }
+
+ @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/api/com/ib/client/ComboLeg.java b/api/com/ib/client/ComboLeg.java
new file mode 100755
index 0000000..6184b37
--- /dev/null
+++ b/api/com/ib/client/ComboLeg.java
@@ -0,0 +1,129 @@
+/* Copyright (C) 2018 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 com.ib.client.Types.Action;
+
+public class ComboLeg {
+ public enum OpenClose implements IApiEnum {
+ Same, Open, Close, Unknown;
+
+ static OpenClose get( int i) {
+ return Types.getEnum( i, values() );
+ }
+
+ @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
+ 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,
+ /* exchange */ null, /* openClose */ 0,
+ /* shortSaleSlot */ 0, /* designatedLocation*/ null, /* exemptCode */ -1);
+ }
+
+ public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange, int p_openClose) {
+ this(p_conId, p_ratio, p_action, p_exchange, p_openClose,
+ /* shortSaleSlot */ 0, /* designatedLocation*/ null, /* exemptCode */ -1);
+
+ }
+
+ public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange,
+ int p_openClose, int p_shortSaleSlot, String p_designatedLocation) {
+ this(p_conId, p_ratio, p_action, p_exchange, p_openClose, p_shortSaleSlot, p_designatedLocation,
+ /* exemptCode */ -1);
+
+ }
+
+ 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_ratio = p_ratio;
+ m_action = p_action;
+ m_exchange = p_exchange;
+ m_openClose = p_openClose;
+ m_shortSaleSlot = p_shortSaleSlot;
+ m_designatedLocation = p_designatedLocation;
+ m_exemptCode = p_exemptCode;
+ }
+
+ @Override
+ public boolean equals(Object p_other) {
+ if (this == p_other) {
+ return true;
+ }
+ if (!(p_other instanceof ComboLeg)) {
+ return false;
+ }
+
+ ComboLeg l_theOther = (ComboLeg)p_other;
+
+ 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 ||
+ m_exemptCode != l_theOther.m_exemptCode) {
+ return false;
+ }
+
+ if (Util.StringCompareIgnCase(m_action, l_theOther.m_action) != 0 ||
+ Util.StringCompareIgnCase(m_exchange, l_theOther.m_exchange) != 0 ||
+ Util.StringCompareIgnCase(m_designatedLocation, l_theOther.m_designatedLocation) != 0) {
+ return false;
+ }
+
+ 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/api/com/ib/client/CommissionReport.java b/api/com/ib/client/CommissionReport.java
new file mode 100755
index 0000000..ca776d6
--- /dev/null
+++ b/api/com/ib/client/CommissionReport.java
@@ -0,0 +1,39 @@
+/* Copyright (C) 2018 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 CommissionReport {
+
+ public String m_execId;
+ public double m_commission;
+ public String m_currency;
+ public double m_realizedPNL;
+ public double m_yield;
+ public int m_yieldRedemptionDate; // YYYYMMDD format
+
+ public CommissionReport() {
+ m_commission = 0;
+ m_realizedPNL = 0;
+ m_yield = 0;
+ m_yieldRedemptionDate = 0;
+ }
+
+ @Override
+ public boolean equals(Object p_other) {
+ if (this == p_other) {
+ return true;
+ }
+ if (!(p_other instanceof CommissionReport)) {
+ return false;
+ }
+ 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/api/com/ib/client/Contract.java b/api/com/ib/client/Contract.java
new file mode 100755
index 0000000..ef7c281
--- /dev/null
+++ b/api/com/ib/client/Contract.java
@@ -0,0 +1,280 @@
+/* Copyright (C) 2018 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.ArrayList;
+import java.util.List;
+
+import com.ib.client.Types.Right;
+import com.ib.client.Types.SecIdType;
+import com.ib.client.Types.SecType;
+
+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_deltaNeutralContract;
+ private boolean m_includeExpired; // can not be set to true for orders
+ // COMBOS
+ private String m_comboLegsDescrip; // received in open order version 14 and up for all combos
+ private List<ComboLeg> 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 deltaNeutralContract() { return m_deltaNeutralContract; }
+ public List<ComboLeg> comboLegs() { return m_comboLegs; }
+ public String comboLegsDescrip() { return m_comboLegsDescrip; }
+
+ // 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 deltaNeutralContract(DeltaNeutralContract v) { m_deltaNeutralContract = v; }
+ public void includeExpired(boolean v) { m_includeExpired = v; }
+ public void comboLegs(List<ComboLeg> v) { m_comboLegs = v; }
+ public void comboLegsDescrip(String v) { m_comboLegsDescrip = v; }
+
+ public Contract() {
+ m_conid = 0;
+ m_strike = 0;
+ m_includeExpired = false;
+ }
+
+ @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_lastTradeDateOrContractMonth,
+ double p_strike, String p_right, String p_multiplier,
+ String p_exchange, String p_currency, String p_localSymbol, String p_tradingClass,
+ List<ComboLeg> p_comboLegs, String p_primaryExch, boolean p_includeExpired,
+ String p_secIdType, String p_secId) {
+ m_conid = p_conId;
+ m_symbol = p_symbol;
+ m_secType = p_secType;
+ m_lastTradedateOrContractMonth = p_lastTradeDateOrContractMonth;
+ m_strike = p_strike;
+ m_right = p_right;
+ m_multiplier = p_multiplier;
+ m_exchange = p_exchange;
+ m_currency = p_currency;
+ m_includeExpired = p_includeExpired;
+ m_localSymbol = p_localSymbol;
+ m_tradingClass = p_tradingClass;
+ m_comboLegs = p_comboLegs;
+ m_primaryExch = p_primaryExch;
+ m_secIdType = p_secIdType;
+ m_secId = p_secId ;
+ }
+
+ @Override
+ public boolean equals(Object p_other) {
+ if (this == p_other) {
+ return true;
+ }
+
+ if (p_other == null || !(p_other instanceof Contract)) {
+ return false;
+ }
+
+ Contract l_theOther = (Contract)p_other;
+
+ if (m_conid != l_theOther.m_conid) {
+ return false;
+ }
+
+ if (Util.StringCompare(m_secType, l_theOther.m_secType) != 0) {
+ return false;
+ }
+
+ if (Util.StringCompare(m_symbol, l_theOther.m_symbol) != 0 ||
+ Util.StringCompare(m_exchange, l_theOther.m_exchange) != 0 ||
+ Util.StringCompare(m_primaryExch, l_theOther.m_primaryExch) != 0 ||
+ Util.StringCompare(m_currency, l_theOther.m_currency) != 0) {
+ return false;
+ }
+
+ if (!"BOND".equals(m_secType)) {
+
+ if (m_strike != l_theOther.m_strike) {
+ return false;
+ }
+
+ 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 ||
+ Util.StringCompare(m_tradingClass, l_theOther.m_tradingClass) != 0) {
+ return false;
+ }
+ }
+
+ if (Util.StringCompare(m_secIdType, l_theOther.m_secIdType) != 0) {
+ return false;
+ }
+
+ if (Util.StringCompare(m_secId, l_theOther.m_secId) != 0) {
+ return false;
+ }
+
+ // compare combo legs
+ if (!Util.listsEqualUnordered(m_comboLegs, l_theOther.m_comboLegs)) {
+ return false;
+ }
+
+ if (m_deltaNeutralContract != l_theOther.m_deltaNeutralContract) {
+ if (m_deltaNeutralContract == null || l_theOther.m_deltaNeutralContract == null) {
+ return false;
+ }
+ if (!m_deltaNeutralContract.equals(l_theOther.m_deltaNeutralContract)) {
+ 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/api/com/ib/client/ContractCondition.java b/api/com/ib/client/ContractCondition.java
new file mode 100755
index 0000000..a10b828
--- /dev/null
+++ b/api/com/ib/client/ContractCondition.java
@@ -0,0 +1,65 @@
+/* Copyright (C) 2018 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.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<ContractDetails> 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/api/com/ib/client/ContractDescription.java b/api/com/ib/client/ContractDescription.java
new file mode 100755
index 0000000..bcc7992
--- /dev/null
+++ b/api/com/ib/client/ContractDescription.java
@@ -0,0 +1,56 @@
+/* Copyright (C) 2018 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/api/com/ib/client/ContractDetails.java b/api/com/ib/client/ContractDetails.java
new file mode 100755
index 0000000..b31ba28
--- /dev/null
+++ b/api/com/ib/client/ContractDetails.java
@@ -0,0 +1,232 @@
+/* Copyright (C) 2018 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;
+
+public class ContractDetails {
+ 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<TagValue> m_secIdList; // CUSIP/ISIN/etc.
+ private int m_aggGroup;
+ private String m_underSymbol;
+ private String m_underSecType;
+ private String m_marketRuleIds;
+ private String m_realExpirationDate;
+ private String m_lastTradeTime;
+
+ // 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;
+
+ // 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<TagValue> 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 realExpirationDate() { return m_realExpirationDate; }
+ public String lastTradeTime() { return m_lastTradeTime; }
+
+ 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<TagValue> 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 realExpirationDate(String realExpirationDate) { m_realExpirationDate = realExpirationDate; }
+ public void lastTradeTime(String lastTradeTime) { m_lastTradeTime = lastTradeTime; }
+
+ 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_contract = new Contract();
+ m_minTick = 0;
+ m_underConid = 0;
+ m_evMultiplier = 0;
+ }
+
+ 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, int p_mdSizeMultiplier, int p_aggGroup,
+ String p_underSymbol, String p_underSecType, String p_marketRuleIds, String p_realExpirationDate, String p_lastTradeTime) {
+ 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_longName = p_longName;
+ m_contractMonth = p_contractMonth;
+ m_industry = p_industry;
+ m_category = p_category;
+ m_subcategory = p_subcategory;
+ m_timeZoneId = p_timeZoneId;
+ m_tradingHours = p_tradingHours;
+ 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;
+ m_realExpirationDate = p_realExpirationDate;
+ m_lastTradeTime = p_lastTradeTime;
+ }
+
+ @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, "realExpirationDate", m_realExpirationDate);
+ add( sb, "lastTradeTime", m_lastTradeTime);
+
+ 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/api/com/ib/client/ContractLookuper.java b/api/com/ib/client/ContractLookuper.java
new file mode 100755
index 0000000..614c24d
--- /dev/null
+++ b/api/com/ib/client/ContractLookuper.java
@@ -0,0 +1,10 @@
+/* Copyright (C) 2018 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;
+
+public interface ContractLookuper {
+ List<ContractDetails> lookupContract(Contract contract);
+} \ No newline at end of file
diff --git a/api/com/ib/client/DefaultEWrapper.java b/api/com/ib/client/DefaultEWrapper.java
new file mode 100755
index 0000000..1ea609f
--- /dev/null
+++ b/api/com/ib/client/DefaultEWrapper.java
@@ -0,0 +1,526 @@
+/* Copyright (C) 2018 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;
+
+public 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, double mktCapPrice) {
+ // 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 deltaNeutralContract) {
+ // 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<String> expirations, Set<Double> 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<Integer, Entry<String, Character>> 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<HistogramEntry> 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, double realizedPnL) {
+ // 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 realizedPnL, double value) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void historicalTicks(int reqId, List<HistoricalTick> ticks, boolean last) {
+ // TODO Auto-generated method stub
+
+ }
+
+
+ @Override
+ public void historicalTicksBidAsk(int reqId, List<HistoricalTickBidAsk> ticks, boolean done) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void historicalTicksLast(int reqId, List<HistoricalTickLast> ticks, boolean done) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void tickByTickAllLast(int reqId, int tickType, long time, double price, int size, TickAttr attribs,
+ String exchange, String specialConditions) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, int bidSize, int askSize,
+ TickAttr attribs) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void tickByTickMidPoint(int reqId, long time, double midPoint) {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/api/com/ib/client/DeltaNeutralContract.java b/api/com/ib/client/DeltaNeutralContract.java
new file mode 100755
index 0000000..bccada4
--- /dev/null
+++ b/api/com/ib/client/DeltaNeutralContract.java
@@ -0,0 +1,69 @@
+/* Copyright (C) 2018 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/api/com/ib/client/DepthMktDataDescription.java b/api/com/ib/client/DepthMktDataDescription.java
new file mode 100755
index 0000000..f6f9901
--- /dev/null
+++ b/api/com/ib/client/DepthMktDataDescription.java
@@ -0,0 +1,37 @@
+/* Copyright (C) 2018 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/api/com/ib/client/EClient.java b/api/com/ib/client/EClient.java
new file mode 100755
index 0000000..73a261c
--- /dev/null
+++ b/api/com/ib/client/EClient.java
@@ -0,0 +1,3783 @@
+/* Copyright (C) 2018 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.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+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 deltaNeutralContract 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 REQ_HISTORICAL_TICKS = 96;
+ private static final int REQ_TICK_BY_TICK_DATA = 97;
+ private static final int CANCEL_TICK_BY_TICK_DATA = 98;
+
+ 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_DELTA_NEUTRAL = 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;
+ protected static final int MIN_SERVER_VER_HISTORICAL_TICKS = 130;
+ protected static final int MIN_SERVER_VER_MARKET_CAP_PRICE = 131;
+ protected static final int MIN_SERVER_VER_PRE_OPEN_BID_ASK = 132;
+ protected static final int MIN_SERVER_VER_REAL_EXPIRATION_DATE = 134;
+ protected static final int MIN_SERVER_VER_REALIZED_PNL = 135;
+ protected static final int MIN_SERVER_VER_LAST_LIQUIDITY = 136;
+ protected static final int MIN_SERVER_VER_TICK_BY_TICK = 137;
+ protected static final int MIN_SERVER_VER_DECISION_MAKER = 138;
+ protected static final int MIN_SERVER_VER_MIFID_EXECUTION = 139;
+ protected static final int MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE = 140;
+ protected static final int MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE = 141;
+ protected static final int MIN_SERVER_VER_WHAT_IF_EXT_FIELDS = 142;
+
+ public static final int MIN_VERSION = 100; // envelope encoding, applicable to useV100Plus mode only
+ public static final int MAX_VERSION = MIN_SERVER_VER_WHAT_IF_EXT_FIELDS; // 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 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<TagValue> 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) {
+ b.send(scannerSubscriptionOptions);
+ }
+
+ 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<TagValue> 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_DELTA_NEUTRAL) {
+ if (contract.deltaNeutralContract() != 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_DELTA_NEUTRAL) {
+ if (contract.deltaNeutralContract() != null) {
+ DeltaNeutralContract deltaNeutralContract = contract.deltaNeutralContract();
+
+ b.send(true);
+ b.send(deltaNeutralContract.conid());
+ b.send(deltaNeutralContract.delta());
+ b.send(deltaNeutralContract.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) {
+ b.send(mktDataOptions);
+ }
+
+ 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<TagValue> 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) {
+ b.send(chartOptions);
+ }
+
+ 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);
+ 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<TagValue> 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) {
+ b.send(realTimeBarsOptions);
+ }
+
+ 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<TagValue> 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) {
+ b.send(mktDepthOptions);
+ }
+
+ 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_DELTA_NEUTRAL) {
+ if (contract.deltaNeutralContract() != 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;
+ }
+ }
+
+ if (m_serverVersion < MIN_SERVER_VER_DECISION_MAKER
+ && (!IsEmpty(order.mifid2DecisionMaker())
+ || !IsEmpty(order.mifid2DecisionAlgo()))) {
+ error(id, EClientErrors.UPDATE_TWS,
+ " It does not support MIFID II decision maker parameters");
+ return;
+ }
+
+ if (m_serverVersion < MIN_SERVER_VER_MIFID_EXECUTION
+ && (!IsEmpty(order.mifid2ExecutionTrader())
+ || !IsEmpty(order.mifid2ExecutionAlgo()))) {
+ error(id, EClientErrors.UPDATE_TWS,
+ " It does not support MIFID II execution parameters");
+ return;
+ }
+
+ if (m_serverVersion < MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE
+ && order.dontUseAutoPriceForHedge()) {
+ error(id, EClientErrors.UPDATE_TWS,
+ " It does not support don't use auto price for hedge 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<TagValue> 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_DELTA_NEUTRAL) {
+ if (contract.deltaNeutralContract() != null) {
+ DeltaNeutralContract deltaNeutralContract = contract.deltaNeutralContract();
+ b.send( true);
+ b.send( deltaNeutralContract.conid());
+ b.send( deltaNeutralContract.delta());
+ b.send( deltaNeutralContract.price());
+ }
+ else {
+ b.send( false);
+ }
+ }
+
+ if (m_serverVersion >= MIN_SERVER_VER_ALGO_ORDERS) {
+ b.send( order.getAlgoStrategy());
+ if( !IsEmpty(order.getAlgoStrategy())) {
+ List<TagValue> 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) {
+ b.send(order.orderMiscOptions());
+ }
+
+ 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());
+ }
+
+ if (m_serverVersion >= MIN_SERVER_VER_DECISION_MAKER) {
+ b.send(order.mifid2DecisionMaker());
+ b.send(order.mifid2DecisionAlgo());
+ }
+
+ if (m_serverVersion >= MIN_SERVER_VER_MIFID_EXECUTION) {
+ b.send(order.mifid2ExecutionTrader());
+ b.send(order.mifid2ExecutionAlgo());
+ }
+
+ if (m_serverVersion >= MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE) {
+ b.send(order.dontUseAutoPriceForHedge());
+ }
+
+ 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,
+ //reserved for future use, must be blank
+ List<TagValue> fundamentalDataOptions) {
+ // 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);
+
+ if (m_serverVersion >= MIN_SERVER_VER_LINKING) {
+ b.send(fundamentalDataOptions);
+ }
+
+ 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,
+ //reserved for future use, must be blank
+ List<TagValue> impliedVolatilityOptions) {
+
+ // 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);
+
+ if (m_serverVersion >= MIN_SERVER_VER_LINKING) {
+ b.send(impliedVolatilityOptions);
+ }
+
+ 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,
+ //reserved for future use, must be blank
+ List<TagValue> optionPriceOptions) {
+
+ // 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);
+
+ if (m_serverVersion >= MIN_SERVER_VER_LINKING) {
+ b.send(optionPriceOptions);
+ }
+
+ 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<TagValue> 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) {
+ b.send(newsArticleOptions);
+ }
+
+ 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<TagValue> 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) {
+ b.send(historicalNewsOptions);
+ }
+
+ 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);
+ 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();
+ }
+ }
+
+ public synchronized void reqHistoricalTicks(int reqId, Contract contract, String startDateTime,
+ String endDateTime, int numberOfTicks, String whatToShow, int useRth, boolean ignoreSize,
+ List<TagValue> miscOptions) {
+ if (!isConnected()) {
+ notConnected();
+ return;
+ }
+
+ if (m_serverVersion < MIN_SERVER_VER_HISTORICAL_TICKS) {
+ error(reqId, EClientErrors.UPDATE_TWS,
+ " It does not support historical ticks request.");
+ return;
+ }
+
+ try {
+ Builder b = prepareBuffer();
+
+ b.send(REQ_HISTORICAL_TICKS);
+ b.send(reqId);
+ b.send(contract);
+ b.send(startDateTime);
+ b.send(endDateTime);
+ b.send(numberOfTicks);
+ b.send(whatToShow);
+ b.send(useRth);
+ b.send(ignoreSize);
+ b.send(miscOptions);
+
+ closeAndSend(b);
+ } catch(Exception e) {
+ error(reqId, EClientErrors.FAIL_SEND_HISTORICAL_TICK, e.toString());
+ close();
+ }
+ }
+
+ public synchronized void reqTickByTickData(int reqId, Contract contract, String tickType, int numberOfTicks, boolean ignoreSize) {
+ // not connected?
+ if( !isConnected()) {
+ notConnected();
+ return;
+ }
+
+ if (m_serverVersion < MIN_SERVER_VER_TICK_BY_TICK) {
+ error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS,
+ " It does not support tick-by-tick data requests.");
+ return;
+ }
+
+ if (m_serverVersion < MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE) {
+ if (numberOfTicks != 0 || ignoreSize) {
+ error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS,
+ " It does not support ignoreSize and numberOfTicks parameters in tick-by-tick data requests.");
+ return;
+ }
+ }
+
+ try {
+ Builder b = prepareBuffer();
+
+ b.send(REQ_TICK_BY_TICK_DATA);
+ b.send(reqId);
+ 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(tickType);
+ if (m_serverVersion >= MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE) {
+ b.send(numberOfTicks);
+ b.send(ignoreSize);
+ }
+
+ closeAndSend(b);
+ }
+ catch( Exception e) {
+ error( EClientErrors.NO_VALID_ID,
+ EClientErrors.FAIL_SEND_REQTICKBYTICK, e.toString());
+ close();
+ }
+ }
+
+ public synchronized void cancelTickByTickData(int reqId) {
+ // not connected?
+ if( !isConnected()) {
+ notConnected();
+ return;
+ }
+
+ if (m_serverVersion < MIN_SERVER_VER_TICK_BY_TICK) {
+ error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS,
+ " It does not support tick-by-tick data cancels.");
+ return;
+ }
+
+ try {
+ Builder b = prepareBuffer();
+
+ b.send(CANCEL_TICK_BY_TICK_DATA);
+ b.send(reqId);
+
+ closeAndSend(b);
+ }
+ catch( Exception e) {
+ error( EClientErrors.NO_VALID_ID,
+ EClientErrors.FAIL_SEND_CANTICKBYTICK, 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/api/com/ib/client/EClientErrors.java b/api/com/ib/client/EClientErrors.java
new file mode 100755
index 0000000..777cbf1
--- /dev/null
+++ b/api/com/ib/client/EClientErrors.java
@@ -0,0 +1,107 @@
+/* Copyright (C) 2018 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 EClientErrors {
+ public static final int NO_VALID_ID = -1;
+ 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 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 - ");
+ static final CodeMsgPair FAIL_SEND_ACCT = new CodeMsgPair(513, "Account Update Request Sending Error -");
+ static final CodeMsgPair FAIL_SEND_EXEC = new CodeMsgPair(514, "Request For Executions Sending Error -");
+ static final CodeMsgPair FAIL_SEND_CORDER = new CodeMsgPair(515, "Cancel Order Sending Error -");
+ static final CodeMsgPair FAIL_SEND_OORDER = new CodeMsgPair(516, "Request Open Order Sending Error -");
+ static final CodeMsgPair UNKNOWN_CONTRACT = new CodeMsgPair(517, "Unknown contract. Verify the contract details supplied.");
+ static final CodeMsgPair FAIL_SEND_REQCONTRACT = new CodeMsgPair(518, "Request Contract Data Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQMKTDEPTH = new CodeMsgPair(519, "Request Market Depth Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANMKTDEPTH = new CodeMsgPair(520, "Cancel Market Depth Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_SERVER_LOG_LEVEL = new CodeMsgPair(521, "Set Server Log Level Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_FA_REQUEST = new CodeMsgPair(522, "FA Information Request Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_FA_REPLACE = new CodeMsgPair(523, "FA Information Replace Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQSCANNER = new CodeMsgPair(524, "Request Scanner Subscription Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANSCANNER = new CodeMsgPair(525, "Cancel Scanner Subscription Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQSCANNERPARAMETERS = new CodeMsgPair(526, "Request Scanner Parameter Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQHISTDATA = new CodeMsgPair(527, "Request Historical Data Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANHISTDATA = new CodeMsgPair(528, "Request Historical Data Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQRTBARS = new CodeMsgPair(529, "Request Real-time Bar Data Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANRTBARS = new CodeMsgPair(530, "Cancel Real-time Bar Data Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQCURRTIME = new CodeMsgPair(531, "Request Current Time Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQFUNDDATA = new CodeMsgPair(532, "Request Fundamental Data Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANFUNDDATA = new CodeMsgPair(533, "Cancel Fundamental Data Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQCALCIMPLIEDVOLAT = new CodeMsgPair(534, "Request Calculate Implied Volatility Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQCALCOPTIONPRICE = new CodeMsgPair(535, "Request Calculate Option Price Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANCALCIMPLIEDVOLAT = new CodeMsgPair(536, "Cancel Calculate Implied Volatility Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANCALCOPTIONPRICE = new CodeMsgPair(537, "Cancel Calculate Option Price Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQGLOBALCANCEL = new CodeMsgPair(538, "Request Global Cancel Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQMARKETDATATYPE = new CodeMsgPair(539, "Request Market Data Type Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQPOSITIONS = new CodeMsgPair(540, "Request Positions Sending Error - ");
+ 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 - ");
+ static final CodeMsgPair FAIL_SEND_HISTORICAL_TICK = new CodeMsgPair(569, "Request Historical Ticks Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_REQTICKBYTICK = new CodeMsgPair(570, "Request Tick-By-Tick Sending Error - ");
+ static final CodeMsgPair FAIL_SEND_CANTICKBYTICK = new CodeMsgPair(571, "Cancel Tick-By-Tick Sending Error - ");
+
+ public EClientErrors() {
+ }
+
+ static public class CodeMsgPair {
+
+ // members vars
+ int m_errorCode;
+ String m_errorMsg;
+
+ // Get/Set methods
+ public int code() { return m_errorCode; }
+ public String msg() { return m_errorMsg; }
+
+ /** Constructor */
+ public CodeMsgPair(int i, String errString) {
+ m_errorCode = i;
+ m_errorMsg = errString;
+ }
+ }
+}
diff --git a/api/com/ib/client/EClientMsgSink.java b/api/com/ib/client/EClientMsgSink.java
new file mode 100755
index 0000000..776396a
--- /dev/null
+++ b/api/com/ib/client/EClientMsgSink.java
@@ -0,0 +1,9 @@
+/* Copyright (C) 2018 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;
+
+interface EClientMsgSink {
+ void serverVersion(int version, String time);
+ void redirect(String host);
+}
diff --git a/api/com/ib/client/EClientSocket.java b/api/com/ib/client/EClientSocket.java
new file mode 100755
index 0000000..97a7627
--- /dev/null
+++ b/api/com/ib/client/EClientSocket.java
@@ -0,0 +1,240 @@
+/* Copyright (C) 2018 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.FilterInputStream;
+import java.io.IOException;
+import java.net.Socket;
+
+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() {
+ 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/api/com/ib/client/EClientSocketSSL.java b/api/com/ib/client/EClientSocketSSL.java
new file mode 100755
index 0000000..b60ebf5
--- /dev/null
+++ b/api/com/ib/client/EClientSocketSSL.java
@@ -0,0 +1,92 @@
+/* Copyright (C) 2018 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.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/api/com/ib/client/EDecoder.java b/api/com/ib/client/EDecoder.java
new file mode 100755
index 0000000..133ae00
--- /dev/null
+++ b/api/com/ib/client/EDecoder.java
@@ -0,0 +1,2291 @@
+/* Copyright (C) 2018 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;
+ private static final int HISTORICAL_TICKS = 96;
+ private static final int HISTORICAL_TICKS_BID_ASK = 97;
+ private static final int HISTORICAL_TICKS_LAST = 98;
+ private static final int TICK_BY_TICK = 99;
+
+
+ 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;
+
+ case HISTORICAL_TICKS:
+ processHistoricalTicks();
+ break;
+
+ case HISTORICAL_TICKS_BID_ASK:
+ processHistoricalTicksBidAsk();
+ break;
+
+ case HISTORICAL_TICKS_LAST:
+ processHistoricalTicksLast();
+ break;
+
+ case TICK_BY_TICK:
+ processTickByTickMsg();
+ 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 processHistoricalTicksLast() throws IOException {
+ int reqId = readInt(),
+ tickCount = readInt();
+
+ List<HistoricalTickLast> ticks = new ArrayList<>();
+
+ for (int i = 0; i < tickCount; i++) {
+ long time = readLong();
+ int mask = readInt();
+ double price = readDouble();
+ long size = readLong();
+ String exchange = readStr(),
+ specialConditions = readStr();
+
+ ticks.add(new HistoricalTickLast(time, mask, price, size, exchange, specialConditions));
+ }
+
+ boolean done = readBoolean();
+
+ m_EWrapper.historicalTicksLast(reqId, ticks, done);
+ }
+
+ private void processHistoricalTicksBidAsk() throws IOException {
+ int reqId = readInt(),
+ tickCount = readInt();
+
+ List<HistoricalTickBidAsk> ticks = new ArrayList<>();
+
+ for (int i = 0; i < tickCount; i++) {
+ long time = readLong();
+ int mask = readInt();
+ double priceBid = readDouble(),
+ priceAsk = readDouble();
+ long sizeBid = readLong(),
+ sizeAsk = readLong();
+
+ ticks.add(new HistoricalTickBidAsk(time, mask, priceBid, priceAsk, sizeBid, sizeAsk));
+ }
+
+ boolean done = readBoolean();
+
+ m_EWrapper.historicalTicksBidAsk(reqId, ticks, done);
+ }
+
+ private void processHistoricalTicks() throws IOException {
+ int reqId = readInt(),
+ tickCount = readInt();
+
+ List<HistoricalTick> ticks = new ArrayList<>();
+
+ for (int i = 0; i < tickCount; i++) {
+ long time = readLong();
+ readInt();//for consistency
+ double price = readDouble();
+ long size = readLong();
+
+ ticks.add(new HistoricalTick(time, price, size));
+ }
+
+ boolean done = readBoolean();
+
+ m_EWrapper.historicalTicks(reqId, ticks, done);
+ }
+
+ 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;
+ double realizedPnL = Double.MAX_VALUE;
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_UNREALIZED_PNL) {
+ unrealizedPnL = readDouble();
+ }
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_REALIZED_PNL) {
+ realizedPnL = readDouble();
+ }
+
+ double value = readDouble();
+
+ m_EWrapper.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value);
+ }
+
+ private void processPnLMsg() throws IOException {
+ int reqId = readInt();
+ double dailyPnL = readDouble();
+ double unrealizedPnL = Double.MAX_VALUE;
+ double realizedPnL = Double.MAX_VALUE;
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_UNREALIZED_PNL) {
+ unrealizedPnL = readDouble();
+ }
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_REALIZED_PNL) {
+ realizedPnL = readDouble();
+ }
+
+ m_EWrapper.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL);
+ }
+
+ private void processHistogramDataMsg() throws IOException {
+ int reqId = readInt();
+ int n = readInt();
+ List<HistogramEntry> 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<String> expirations = new HashSet<>();
+ Set<Double> 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 deltaNeutralContract = new DeltaNeutralContract(readInt(), readDouble(), readDouble());
+ m_EWrapper.deltaNeutralValidation( reqId, deltaNeutralContract);
+ }
+
+ 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 = m_serverVersion;
+
+ if (m_serverVersion < EClient.MIN_SERVER_VER_LAST_LIQUIDITY) {
+ 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());
+ }
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_LAST_LIQUIDITY) {
+ exec.lastLiquidity(readInt());
+ }
+
+
+ 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());
+ readLastTradeDate(contract, true);
+ 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());
+ readLastTradeDate(contract, false);
+ 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());
+ }
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_REAL_EXPIRATION_DATE) {
+ contract.realExpirationDate(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 deltaNeutralContract = new DeltaNeutralContract();
+ deltaNeutralContract.conid(readInt());
+ deltaNeutralContract.delta(readDouble());
+ deltaNeutralContract.price(readDouble());
+ contract.deltaNeutralContract(deltaNeutralContract);
+ }
+ }
+
+ 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());
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_WHAT_IF_EXT_FIELDS) {
+ orderState.initMarginBefore(readStr());
+ orderState.maintMarginBefore(readStr());
+ orderState.equityWithLoanBefore(readStr());
+ orderState.initMarginChange(readStr());
+ orderState.maintMarginChange(readStr());
+ orderState.equityWithLoanChange(readStr());
+ }
+
+ orderState.initMarginAfter(readStr());
+ orderState.maintMarginAfter(readStr());
+ orderState.equityWithLoanAfter(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());
+ }
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE) {
+ order.dontUseAutoPriceForHedge(readBoolFromInt());
+ }
+
+ 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 = m_serverVersion >= EClient.MIN_SERVER_VER_MARKET_CAP_PRICE ? Integer.MAX_VALUE : 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();
+ }
+
+ double mktCapPrice = Double.MAX_VALUE;
+
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_MARKET_CAP_PRICE) {
+ mktCapPrice = readDouble();
+ }
+
+ m_EWrapper.orderStatus( id, status, filled, remaining, avgFillPrice,
+ permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice);
+ }
+
+ 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 (Double.compare(impliedVol, -1) == 0) { // -1 is the "not yet computed" indicator
+ impliedVol = Double.MAX_VALUE;
+ }
+
+ double delta = readDouble();
+ if (Double.compare(delta, -2) == 0) { // -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 (Double.compare(optPrice, -1) == 0) { // -1 is the "not yet computed" indicator
+ optPrice = Double.MAX_VALUE;
+ }
+ pvDividend = readDouble();
+ if (Double.compare(pvDividend, -1) == 0) { // -1 is the "not yet computed" indicator
+ pvDividend = Double.MAX_VALUE;
+ }
+ }
+ if (version >= 6) {
+ gamma = readDouble();
+ if (Double.compare(gamma, -2) == 0) { // -2 is the "not yet computed" indicator
+ gamma = Double.MAX_VALUE;
+ }
+ vega = readDouble();
+ if (Double.compare(vega, -2) == 0) { // -2 is the "not yet computed" indicator
+ vega = Double.MAX_VALUE;
+ }
+ theta = readDouble();
+ if (Double.compare(theta, -2) == 0) { // -2 is the "not yet computed" indicator
+ theta = Double.MAX_VALUE;
+ }
+ undPrice = readDouble();
+ if (Double.compare(undPrice, -1) == 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));
+ if (m_serverVersion >= EClient.MIN_SERVER_VER_PRE_OPEN_BID_ASK) {
+ attribs.preOpen(mask.get(2));
+ }
+ }
+ }
+
+
+ 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<Integer, Entry<String, Character>> 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 void processTickByTickMsg() throws IOException {
+ int reqId = readInt();
+ int tickType = readInt();
+ long time = readLong();
+
+ BitMask mask;
+ TickAttr attribs;
+ switch(tickType){
+ case 0: // None
+ break;
+ case 1: // Last
+ case 2: // AllLast
+ double price = readDouble();
+ int size = readInt();
+ mask = new BitMask(readInt());
+ attribs = new TickAttr();
+ attribs.pastLimit(mask.get(0));
+ attribs.unreported(mask.get(1));
+ String exchange = readStr();
+ String specialConditions = readStr();
+ m_EWrapper.tickByTickAllLast(reqId, tickType, time, price, size, attribs, exchange, specialConditions);
+ break;
+ case 3: // BidAsk
+ double bidPrice = readDouble();
+ double askPrice = readDouble();
+ int bidSize = readInt();
+ int askSize = readInt();
+ mask = new BitMask(readInt());
+ attribs = new TickAttr();
+ attribs.bidPastLow(mask.get(0));
+ attribs.askPastHigh(mask.get(1));
+ m_EWrapper.tickByTickBidAsk(reqId, time, bidPrice, askPrice, bidSize, askSize, attribs);
+ break;
+ case 4: // MidPoint
+ double midPoint = readDouble();
+ m_EWrapper.tickByTickMidPoint(reqId, time, midPoint);
+ break;
+ }
+ }
+
+ private void readLastTradeDate(ContractDetails contract, boolean isBond) throws IOException {
+ String lastTradeDateOrContractMonth = readStr();
+ if (lastTradeDateOrContractMonth != null) {
+ String[] splitted = lastTradeDateOrContractMonth.split("\\s+");
+ if (splitted.length > 0) {
+ if (isBond) {
+ contract.maturity(splitted[0]);
+ } else {
+ contract.contract().lastTradeDateOrContractMonth(splitted[0]);
+ }
+ }
+ if (splitted.length > 1) {
+ contract.lastTradeTime(splitted[1]);
+ }
+ if (isBond && splitted.length > 2) {
+ contract.timeZoneId(splitted[2]);
+ }
+ }
+ }
+
+ 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/api/com/ib/client/EJavaSignal.java b/api/com/ib/client/EJavaSignal.java
new file mode 100755
index 0000000..488b73e
--- /dev/null
+++ b/api/com/ib/client/EJavaSignal.java
@@ -0,0 +1,33 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/EMessage.java b/api/com/ib/client/EMessage.java
new file mode 100755
index 0000000..3e6bcc6
--- /dev/null
+++ b/api/com/ib/client/EMessage.java
@@ -0,0 +1,34 @@
+/* Copyright (C) 2018 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.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/api/com/ib/client/EReader.java b/api/com/ib/client/EReader.java
new file mode 100755
index 0000000..7a519f5
--- /dev/null
+++ b/api/com/ib/client/EReader.java
@@ -0,0 +1,188 @@
+/* Copyright (C) 2018 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.EOFException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.LinkedList;
+
+
+
+/**
+ * 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<EMessage> 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()) {
+ if (!putMessageToQueue())
+ break;
+ }
+ }
+ 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);
+ }
+
+ parent().eDisconnect();
+ //}
+ }
+
+ m_signal.issueSignal();
+ }
+
+ 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;
+
+ private static class InvalidMessageLengthException extends IOException {
+ private static final long serialVersionUID = 1L;
+
+ InvalidMessageLengthException(String message) {
+ super(message);
+ }
+ }
+
+ public void processMsgs() throws IOException {
+ EMessage msg = getMsg();
+
+ while (msg != null && m_processMsgsDecoder.processMsg(msg) > 0) {
+ msg = getMsg();
+ }
+ }
+
+ 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/api/com/ib/client/EReaderSignal.java b/api/com/ib/client/EReaderSignal.java
new file mode 100755
index 0000000..fcd9a20
--- /dev/null
+++ b/api/com/ib/client/EReaderSignal.java
@@ -0,0 +1,9 @@
+/* Copyright (C) 2018 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 EReaderSignal {
+ void issueSignal();
+ void waitForSignal();
+}
diff --git a/api/com/ib/client/ESocket.java b/api/com/ib/client/ESocket.java
new file mode 100755
index 0000000..3de5112
--- /dev/null
+++ b/api/com/ib/client/ESocket.java
@@ -0,0 +1,40 @@
+/* Copyright (C) 2018 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.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/api/com/ib/client/ETransport.java b/api/com/ib/client/ETransport.java
new file mode 100755
index 0000000..7c2ed4d
--- /dev/null
+++ b/api/com/ib/client/ETransport.java
@@ -0,0 +1,11 @@
+/* Copyright (C) 2018 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.IOException;
+
+public interface ETransport extends Closeable {
+ void send(EMessage msg) throws IOException;
+}
diff --git a/api/com/ib/client/EWrapper.java b/api/com/ib/client/EWrapper.java
new file mode 100755
index 0000000..38fc08b
--- /dev/null
+++ b/api/com/ib/client/EWrapper.java
@@ -0,0 +1,107 @@
+/* Copyright (C) 2018 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;
+
+public interface EWrapper {
+ ///////////////////////////////////////////////////////////////////////
+ // Interface methods
+ ///////////////////////////////////////////////////////////////////////
+ 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,
+ double gamma, double vega, double theta, double undPrice);
+ void tickGeneric(int tickerId, int tickType, double value);
+ void tickString(int tickerId, int tickType, String value);
+ void tickEFP(int tickerId, int tickType, double basisPoints,
+ String formattedBasisPoints, double impliedFuture, int holdDays,
+ 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, double mktCapPrice);
+ 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, double position, double marketPrice, double marketValue,
+ double averageCost, double unrealizedPNL, double realizedPNL, String accountName);
+ void updateAccountTime(String timeStamp);
+ void accountDownloadEnd(String accountName);
+ void nextValidId( int orderId);
+ void contractDetails(int reqId, ContractDetails contractDetails);
+ void bondContractDetails(int reqId, ContractDetails contractDetails);
+ void contractDetailsEnd(int reqId);
+ void execDetails( int reqId, Contract contract, Execution execution);
+ void execDetailsEnd( int reqId);
+ void updateMktDepth( int tickerId, int position, int operation, int side, double price, int size);
+ void updateMktDepthL2( int tickerId, int position, String marketMaker, int operation,
+ int side, double price, int size);
+ void updateNewsBulletin( int msgId, int msgType, String message, String origExchange);
+ void managedAccounts( String accountsList);
+ void receiveFA(int faDataType, String xml);
+ 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);
+ void scannerDataEnd(int reqId);
+ 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, DeltaNeutralContract deltaNeutralContract);
+ void tickSnapshotEnd(int reqId);
+ void marketDataType(int reqId, int marketDataType);
+ void commissionReport(CommissionReport commissionReport);
+ 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<String> expirations, Set<Double> 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<Integer, Entry<String, Character>> 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<HistogramEntry> 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, double realizedPnL);
+ void pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value);
+ void historicalTicks(int reqId, List<HistoricalTick> ticks, boolean done);
+ void historicalTicksBidAsk(int reqId, List<HistoricalTickBidAsk> ticks, boolean done);
+ void historicalTicksLast(int reqId, List<HistoricalTickLast> ticks, boolean done);
+ void tickByTickAllLast(int reqId, int tickType, long time, double price, int size, TickAttr attribs, String exchange, String specialConditions);
+ void tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, int bidSize, int askSize, TickAttr attribs);
+ void tickByTickMidPoint(int reqId, long time, double midPoint);
+}
+
diff --git a/api/com/ib/client/EWrapperMsgGenerator.java b/api/com/ib/client/EWrapperMsgGenerator.java
new file mode 100755
index 0000000..0374edb
--- /dev/null
+++ b/api/com/ib/client/EWrapperMsgGenerator.java
@@ -0,0 +1,833 @@
+/* Copyright (C) 2018 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 static com.ib.controller.Formats.fmt;
+
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class EWrapperMsgGenerator {
+ public static final String SCANNER_PARAMETERS = "SCANNER PARAMETERS:";
+ public static final String FINANCIAL_ADVISOR = "FA:";
+
+ public static String tickPrice( int tickerId, int field, double price, TickAttr attribs) {
+ return "id=" + tickerId + " " + TickType.getField( field) + "=" + price + " " +
+ (attribs.canAutoExecute() ? " canAutoExecute" : " noAutoExecute") + " pastLimit = " + attribs.pastLimit() +
+ (field == TickType.BID.index() || field == TickType.ASK.index() ? " preOpen = " + attribs.preOpen() : "");
+ }
+
+ public static String tickSize( int tickerId, int field, int size) {
+ return "id=" + tickerId + " " + TickType.getField( field) + "=" + size;
+ }
+
+ public static String tickOptionComputation( int tickerId, int field, double impliedVol,
+ double delta, double optPrice, double pvDividend,
+ double gamma, double vega, double theta, double undPrice) {
+ return "id=" + tickerId + " " + TickType.getField( field) +
+ ": impliedVol = " + Util.maxDoubleToString(impliedVol) +
+ " delta = " + Util.maxDoubleToString(delta) +
+ " gamma = " + Util.maxDoubleToString(gamma) +
+ " vega = " + Util.maxDoubleToString(vega) +
+ " theta = " + Util.maxDoubleToString(theta) +
+ " optPrice = " + Util.maxDoubleToString(optPrice) +
+ " pvDividend = " + Util.maxDoubleToString(pvDividend) +
+ " undPrice = " + Util.maxDoubleToString(undPrice);
+ }
+
+ public static String tickGeneric(int tickerId, int tickType, double value) {
+ return "id=" + tickerId + " " + TickType.getField( tickType) + "=" + value;
+ }
+
+ public static String tickString(int tickerId, int tickType, String value) {
+ return "id=" + tickerId + " " + TickType.getField( tickType) + "=" + value;
+ }
+
+ public static String tickEFP(int tickerId, int tickType, double basisPoints,
+ String formattedBasisPoints, double impliedFuture, int holdDays,
+ String futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate) {
+ return "id=" + tickerId + " " + TickType.getField(tickType)
+ + ": basisPoints = " + basisPoints + "/" + formattedBasisPoints
+ + " impliedFuture = " + impliedFuture + " holdDays = " + holdDays +
+ " futureLastTradeDate = " + futureLastTradeDate + " dividendImpact = " + dividendImpact +
+ " dividends to expiry = " + dividendsToLastTradeDate;
+ }
+
+ public static String orderStatus( int orderId, String status, double filled, double remaining,
+ double avgFillPrice, int permId, int parentId, double lastFillPrice,
+ int clientId, String whyHeld, double mktCapPrice) {
+ return "order status: orderId=" + orderId + " clientId=" + clientId + " permId=" + permId +
+ " status=" + status + " filled=" + filled + " remaining=" + remaining +
+ " avgFillPrice=" + avgFillPrice + " lastFillPrice=" + lastFillPrice +
+ " parent Id=" + parentId + " whyHeld=" + whyHeld + " mktCapPrice=" + mktCapPrice;
+ }
+
+ 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())
+ .append(" dontUseAutoPriceForHedge=").append(order.dontUseAutoPriceForHedge());
+
+
+ if ("BAG".equals(contract.getSecType())) {
+ if (contract.comboLegsDescrip() != null) {
+ sb.append(" comboLegsDescrip=").append(contract.comboLegsDescrip());
+ }
+
+ 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()));
+ }
+ sb.append(';');
+ }
+ }
+ sb.append('}');
+
+ if (order.basisPoints() != Double.MAX_VALUE) {
+ sb.append(" basisPoints=").append(Util.DoubleMaxString(order.basisPoints()))
+ .append(" basisPointsType=").append(Util.IntMaxString(order.basisPointsType()));
+ }
+ }
+
+ if (contract.deltaNeutralContract() != null) {
+ DeltaNeutralContract deltaNeutralContract = contract.deltaNeutralContract();
+ sb.append(" deltaNeutralContract.conId=").append(deltaNeutralContract.conid())
+ .append(" deltaNeutralContract.delta=").append(deltaNeutralContract.delta())
+ .append(" deltaNeutralContract.price=").append(deltaNeutralContract.price());
+ }
+
+ 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);
+ }
+ }
+ sb.append('}');
+ }
+
+ 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);
+ }
+ }
+ sb.append('}');
+ }
+
+ sb.append(" status=").append(orderState.getStatus())
+ .append(" initMarginBefore=").append(orderState.initMarginBefore() != null ? fmt(Double.parseDouble(orderState.initMarginBefore())) : "")
+ .append(" maintMarginBefore=").append(orderState.maintMarginBefore() != null ? fmt(Double.parseDouble(orderState.maintMarginBefore())) : "")
+ .append(" equityWithLoanBefore=").append(orderState.equityWithLoanBefore() != null ? fmt(Double.parseDouble(orderState.equityWithLoanBefore())) : "")
+ .append(" initMarginChange=").append(orderState.initMarginChange() != null ? fmt(Double.parseDouble(orderState.initMarginChange())) : "")
+ .append(" maintMarginChange=").append(orderState.maintMarginChange() != null ? fmt(Double.parseDouble(orderState.maintMarginChange())) : "")
+ .append(" equityWithLoanChange=").append(orderState.equityWithLoanChange() != null ? fmt(Double.parseDouble(orderState.equityWithLoanChange())) : "")
+ .append(" initMarginAfter=").append(fmt(Double.parseDouble(orderState.initMarginAfter())))
+ .append(" maintMarginAfter=").append(fmt(Double.parseDouble(orderState.maintMarginAfter())))
+ .append(" equityWithLoanAfter=").append(fmt(Double.parseDouble(orderState.equityWithLoanAfter())))
+ .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 sb.toString();
+ }
+
+ public static String openOrderEnd() {
+ return " =============== end ===============";
+ }
+
+ public static String updateAccountValue(String key, String value, String currency, String accountName) {
+ return "updateAccountValue: " + key + " " + value + " " + currency + " " + accountName;
+ }
+
+ public static String updatePortfolio(Contract contract, double position, double marketPrice,
+ double marketValue, double averageCost, double unrealizedPNL,
+ double realizedPNL, String accountName) {
+ return "updatePortfolio: "
+ + contractMsg(contract)
+ + position + " " + marketPrice + " " + marketValue + " " + averageCost + " " + unrealizedPNL + " " + realizedPNL + " " + accountName;
+ }
+
+ public static String updateAccountTime(String timeStamp) {
+ return "updateAccountTime: " + timeStamp;
+ }
+
+ public static String accountDownloadEnd(String accountName) {
+ return "accountDownloadEnd: " + accountName;
+ }
+
+ public static String nextValidId( int orderId) {
+ return "Next Valid Order ID: " + orderId;
+ }
+
+ 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) {
+ 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"
+ + "realExpirationDate = " + contractDetails.realExpirationDate() + "\n"
+ + "lastTradeTime = " + contractDetails.lastTradeTime() + "\n"
+ + contractDetailsSecIdList(contractDetails);
+ }
+
+ 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";
+ }
+
+ public static String bondContractDetails(int reqId, ContractDetails contractDetails) {
+ Contract contract = contractDetails.contract();
+ return "reqId = " + reqId + " ===================================\n"
+ + " ---- Bond Contract Details begin ----\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"
+ + "timeZoneId = " + contractDetails.timeZoneId() + "\n"
+ + "lastTradeTime = " + contractDetails.lastTradeTime() + "\n"
+ + contractDetailsSecIdList(contractDetails)
+ + " ---- Bond Contract Details End ----\n";
+ }
+
+ 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);
+ }
+ }
+ sb.append("}\n");
+ return sb.toString();
+ }
+
+ public static String contractDetailsEnd(int reqId) {
+ return "reqId = " + reqId + " =============== end ===============";
+ }
+
+ public static String execDetails( int reqId, Contract contract, Execution execution) {
+ return " ---- Execution Details begin ----\n"
+ + "reqId = " + reqId + "\n"
+ + "orderId = " + execution.orderId() + "\n"
+ + "clientId = " + execution.clientId() + "\n"
+ + contractMsg(contract)
+ + "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"
+ + "lastLiquidity = " + execution.lastLiquidity() + "\n"
+ + " ---- Execution Details end ----\n";
+ }
+
+ public static String execDetailsEnd(int reqId) {
+ return "reqId = " + reqId + " =============== end ===============";
+ }
+
+ public static String updateMktDepth( int tickerId, int position, int operation, int side,
+ double price, int size) {
+ return "updateMktDepth: " + tickerId + " " + position + " " + operation + " " + side + " " + price + " " + size;
+ }
+
+ 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;
+ }
+
+ public static String updateNewsBulletin( int msgId, int msgType, String message, String origExchange) {
+ return "MsgId=" + msgId + " :: MsgType=" + msgType + " :: Origin=" + origExchange + " :: Message=" + message;
+ }
+
+ public static String managedAccounts( String accountsList) {
+ return "Connected : The list of managed accounts are : [" + accountsList + "]";
+ }
+
+ public static String receiveFA(int faDataType, String xml) {
+ return FINANCIAL_ADVISOR + " " + EClient.faMsgTypeName(faDataType) + " " + xml;
+ }
+
+ 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 +
+ " high=" + high +
+ " low=" + low +
+ " close=" + close +
+ " volume=" + volume +
+ " count=" + count +
+ " 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 +
+ " time = " + time +
+ " open=" + open +
+ " high=" + high +
+ " low=" + low +
+ " close=" + close +
+ " volume=" + volume +
+ " count=" + count +
+ " WAP=" + wap;
+ }
+
+ public static String scannerParameters(String xml) {
+ return SCANNER_PARAMETERS + "\n" + xml;
+ }
+
+ public static String scannerData(int reqId, int rank, ContractDetails contractDetails,
+ String distance, String benchmark, String projection,
+ String legsStr) {
+ Contract contract = contractDetails.contract();
+ return "id = " + reqId +
+ " rank=" + rank +
+ " 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;
+ }
+
+ public static String scannerDataEnd(int reqId) {
+ return "id = " + reqId + " =============== end ===============";
+ }
+
+ public static String currentTime(long time) {
+ return "current time = " + time +
+ " (" + DateFormat.getDateTimeInstance().format(new Date(time * 1000)) + ")";
+ }
+
+ public static String fundamentalData(int reqId, String data) {
+ return "id = " + reqId + " len = " + data.length() + '\n' + data;
+ }
+
+ public static String deltaNeutralValidation(int reqId, DeltaNeutralContract deltaNeutralContract) {
+ return "id = " + reqId
+ + " deltaNeutralContract.conId =" + deltaNeutralContract.conid()
+ + " deltaNeutralContract.delta =" + deltaNeutralContract.delta()
+ + " deltaNeutralContract.price =" + deltaNeutralContract.price();
+ }
+ public static String tickSnapshotEnd(int tickerId) {
+ return "id=" + tickerId + " =============== end ===============";
+ }
+
+ public static String marketDataType(int reqId, int marketDataType){
+ return "id=" + reqId + " marketDataType = " + MarketDataType.getField(marketDataType);
+ }
+
+ 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);
+ }
+
+ public static String position( String account, Contract contract, double pos, double avgCost) {
+ return " ---- Position begin ----\n"
+ + "account = " + account + "\n"
+ + contractMsg(contract)
+ + "position = " + Util.DoubleMaxString(pos) + "\n"
+ + "avgCost = " + Util.DoubleMaxString(avgCost) + "\n"
+ + " ---- Position end ----\n";
+ }
+
+ public static String positionEnd() {
+ return " =============== end ===============";
+ }
+
+ 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";
+ }
+
+ 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<String> expirations, Set<Double> 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<Integer, Entry<String, Character>> theMap) {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("==== Smart Components Begin (total=").append(theMap.entrySet().size()).append(") reqId = ").append(reqId).append("====\n");
+
+ for (Map.Entry<Integer, Entry<String, Character>> 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<HistogramEntry> 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, double realizedPnL) {
+ return "Daily PnL. Req Id: " + reqId + ", daily PnL: " + dailyPnL + ", unrealizedPnL: " + unrealizedPnL + ", realizedPnL: " + realizedPnL;
+ }
+
+ public static String pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value) {
+ return "Daily PnL Single. Req Id: " + reqId + ", pos: " + pos + ", daily PnL: " + dailyPnL + ", unrealizedPnL: " + unrealizedPnL + ", realizedPnL: " + realizedPnL + ", value: " + value;
+ }
+
+ public static String historicalTick(int reqId, long time, double price, long size) {
+ return "Historical Tick. Req Id: " + reqId + ", time: " + Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss zzz") + ", price: " + price + ", size: "
+ + size;
+ }
+
+ public static String historicalTickBidAsk(int reqId, long time, int mask, double priceBid, double priceAsk,
+ long sizeBid, long sizeAsk) {
+ return "Historical Tick Bid/Ask. Req Id: " + reqId + ", time: " + Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss zzz") + ", bid price: " + priceBid
+ + ", ask price: " + priceAsk + ", bid size: " + sizeBid + ", ask size: " + sizeAsk;
+ }
+
+ public static String historicalTickLast(int reqId, long time, int mask, double price, long size, String exchange,
+ String specialConditions) {
+ return "Historical Tick Last. Req Id: " + reqId + ", time: " + Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss zzz") + ", price: " + price + ", size: "
+ + size + ", exchange: " + exchange + ", special conditions:" + specialConditions;
+ }
+
+ public static String tickByTickAllLast(int reqId, int tickType, long time, double price, int size, TickAttr attribs,
+ String exchange, String specialConditions){
+ return (tickType == 1 ? "Last." : "AllLast.") +
+ " Req Id: " + reqId + " Time: " + Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss zzz") + " Price: " + price + " Size: " + size +
+ " Exch: " + exchange + " Spec Cond: " + specialConditions + (attribs.pastLimit() ? " pastLimit" : "") +
+ (tickType == 1 ? "" : (attribs.unreported() ? " unreported" : ""));
+ }
+
+ public static String tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, int bidSize, int askSize,
+ TickAttr attribs){
+ return "BidAsk. Req Id: " + reqId + " Time: " + Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss zzz") + " BidPrice: " + bidPrice +
+ " AskPrice: " + askPrice + " BidSize: " + bidSize + " AskSize: " + askSize +
+ (attribs.bidPastLow() ? " bidPastLow" : "") + (attribs.askPastHigh() ? " askPastHigh" : "");
+ }
+
+ public static String tickByTickMidPoint(int reqId, long time, double midPoint){
+ return "MidPoint. Req Id: " + reqId + " Time: " + Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss zzz") + " MidPoint: " + midPoint;
+ }
+} \ No newline at end of file
diff --git a/api/com/ib/client/Execution.java b/api/com/ib/client/Execution.java
new file mode 100755
index 0000000..3784d7f
--- /dev/null
+++ b/api/com/ib/client/Execution.java
@@ -0,0 +1,154 @@
+/* Copyright (C) 2018 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;
+
+enum Liquidities {
+ None,
+ Added("Added Liquidity"),
+ Removed("Removed Liquidity"),
+ RoudedOut("Liquidity Routed Out");
+
+ private String m_text;
+
+ Liquidities(String text) {
+ m_text = text;
+ }
+
+ Liquidities() {
+ m_text = "None";
+ }
+
+ @Override
+ public String toString() {
+ return m_text;
+ }
+
+ public static Liquidities fromInt(int n) {
+ if (n < 0 || n > Liquidities.values().length) {
+ return Liquidities.None;
+ }
+
+ return Liquidities.values()[n];
+ }
+
+ public static int toInt(Liquidities l) {
+ return l.ordinal();
+ }
+}
+
+public class Execution {
+ 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;
+ private Liquidities m_lastLiquidity;
+
+ // 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; }
+ public Liquidities lastLiquidity() { return m_lastLiquidity; }
+
+ // 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 void lastLiquidity(int v) { m_lastLiquidity = Liquidities.fromInt(v); }
+
+ public Execution() {
+ m_orderId = 0;
+ m_clientId = 0;
+ m_shares = 0;
+ m_price = 0;
+ m_permId = 0;
+ m_liquidation = 0;
+ m_cumQty = 0;
+ m_avgPrice = 0;
+ m_evMultiplier = 0;
+ m_lastLiquidity = Liquidities.None;
+ }
+
+ 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,
+ String p_modelCode) {
+ m_orderId = p_orderId;
+ m_clientId = p_clientId;
+ m_execId = p_execId;
+ m_time = p_time;
+ m_acctNumber = p_acctNumber;
+ m_exchange = p_exchange;
+ m_side = p_side;
+ m_shares = p_shares;
+ m_price = p_price;
+ m_permId = p_permId;
+ m_liquidation = p_liquidation;
+ m_cumQty = p_cumQty;
+ m_avgPrice = p_avgPrice;
+ m_orderRef = p_orderRef;
+ m_evRule = p_evRule;
+ m_evMultiplier = p_evMultiplier;
+ m_modelCode = p_modelCode;
+ }
+
+ @Override
+ public boolean equals(Object p_other) {
+ if (this == p_other) {
+ return true;
+ }
+ if (!(p_other instanceof Execution)) {
+ return false;
+ }
+ 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/api/com/ib/client/ExecutionCondition.java b/api/com/ib/client/ExecutionCondition.java
new file mode 100755
index 0000000..31a1758
--- /dev/null
+++ b/api/com/ib/client/ExecutionCondition.java
@@ -0,0 +1,67 @@
+/* Copyright (C) 2018 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.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/api/com/ib/client/ExecutionFilter.java b/api/com/ib/client/ExecutionFilter.java
new file mode 100755
index 0000000..63dadcd
--- /dev/null
+++ b/api/com/ib/client/ExecutionFilter.java
@@ -0,0 +1,71 @@
+/* Copyright (C) 2018 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 ExecutionFilter{
+ 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() {
+ clientId(0);
+ }
+
+ public ExecutionFilter( int p_clientId, String p_acctCode, String p_time,
+ String p_symbol, String p_secType, String p_exchange, String p_side) {
+ m_clientId = p_clientId;
+ m_acctCode = p_acctCode;
+ m_time = p_time;
+ m_symbol = p_symbol;
+ m_secType = p_secType;
+ m_exchange = p_exchange;
+ m_side = p_side;
+ }
+
+ @Override
+ public boolean equals(Object p_other) {
+ if (this == p_other) {
+ return true;
+ }
+ if (!(p_other instanceof ExecutionFilter)) {
+ return false;
+ }
+ 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/api/com/ib/client/FamilyCode.java b/api/com/ib/client/FamilyCode.java
new file mode 100755
index 0000000..f0bd691
--- /dev/null
+++ b/api/com/ib/client/FamilyCode.java
@@ -0,0 +1,25 @@
+/* Copyright (C) 2018 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/api/com/ib/client/HistogramEntry.java b/api/com/ib/client/HistogramEntry.java
new file mode 100755
index 0000000..c38ecf0
--- /dev/null
+++ b/api/com/ib/client/HistogramEntry.java
@@ -0,0 +1,50 @@
+/* Copyright (C) 2018 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<HistogramEntry> {
+
+ 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/api/com/ib/client/HistoricalTick.java b/api/com/ib/client/HistoricalTick.java
new file mode 100755
index 0000000..9b34f45
--- /dev/null
+++ b/api/com/ib/client/HistoricalTick.java
@@ -0,0 +1,28 @@
+/* Copyright (C) 2018 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 HistoricalTick {
+ private long m_time;
+ private double m_price;
+ private long m_size;
+
+ public HistoricalTick(long time, double price, long size) {
+ m_time = time;
+ m_price = price;
+ m_size = size;
+ }
+
+ public long time() {
+ return m_time;
+ }
+
+ public double price() {
+ return m_price;
+ }
+
+ public long size() {
+ return m_size;
+ }
+} \ No newline at end of file
diff --git a/api/com/ib/client/HistoricalTickBidAsk.java b/api/com/ib/client/HistoricalTickBidAsk.java
new file mode 100755
index 0000000..8747d73
--- /dev/null
+++ b/api/com/ib/client/HistoricalTickBidAsk.java
@@ -0,0 +1,47 @@
+/* Copyright (C) 2018 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 HistoricalTickBidAsk {
+ private long m_time;
+ private int m_mask;
+ private double m_priceBid;
+ private double m_priceAsk;
+ private long m_sizeBid;
+ private long m_sizeAsk;
+
+ public HistoricalTickBidAsk(long time, int mask, double priceBid, double priceAsk, long sizeBid, long sizeAsk) {
+ m_time = time;
+ m_mask = mask;
+ m_priceBid = priceBid;
+ m_priceAsk = priceAsk;
+ m_sizeBid = sizeBid;
+ m_sizeAsk = sizeAsk;
+ }
+
+ public long time() {
+ return m_time;
+ }
+
+ public int mask() {
+ return m_mask;
+ }
+
+ public double priceBid() {
+ return m_priceBid;
+ }
+
+ public double priceAsk() {
+ return m_priceAsk;
+ }
+
+ public long sizeBid() {
+ return m_sizeBid;
+ }
+
+ public long sizeAsk() {
+ return m_sizeAsk;
+ }
+
+} \ No newline at end of file
diff --git a/api/com/ib/client/HistoricalTickLast.java b/api/com/ib/client/HistoricalTickLast.java
new file mode 100755
index 0000000..90a3da3
--- /dev/null
+++ b/api/com/ib/client/HistoricalTickLast.java
@@ -0,0 +1,46 @@
+/* Copyright (C) 2018 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 HistoricalTickLast {
+ private long m_time;
+ private int m_mask;
+ private double m_price;
+ private long m_size;
+ private String m_exchange;
+ private String m_specialConditions;
+
+ public HistoricalTickLast(long time, int mask, double price, long size, String exchange, String specialConditions) {
+ m_time = time;
+ m_mask = mask;
+ m_price = price;
+ m_size = size;
+ m_exchange = exchange;
+ m_specialConditions = specialConditions;
+ }
+
+ public long time() {
+ return m_time;
+ }
+
+ public int mask() {
+ return m_mask;
+ }
+
+ public double price() {
+ return m_price;
+ }
+
+ public long size() {
+ return m_size;
+ }
+
+ public String exchange() {
+ return m_exchange;
+ }
+
+ public String specialConditions() {
+ return m_specialConditions;
+ }
+} \ No newline at end of file
diff --git a/api/com/ib/client/IApiEnum.java b/api/com/ib/client/IApiEnum.java
new file mode 100755
index 0000000..e616d8b
--- /dev/null
+++ b/api/com/ib/client/IApiEnum.java
@@ -0,0 +1,8 @@
+/* Copyright (C) 2018 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 IApiEnum {
+ String getApiString();
+}
diff --git a/api/com/ib/client/MarginCondition.java b/api/com/ib/client/MarginCondition.java
new file mode 100755
index 0000000..2b08958
--- /dev/null
+++ b/api/com/ib/client/MarginCondition.java
@@ -0,0 +1,37 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/MarketDataType.java b/api/com/ib/client/MarketDataType.java
new file mode 100755
index 0000000..b717a0d
--- /dev/null
+++ b/api/com/ib/client/MarketDataType.java
@@ -0,0 +1,49 @@
+/* Copyright (C) 2018 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 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 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 Integer.MAX_VALUE;
+ }
+ }
+
+ public static String[] getFields(){
+ int totalFields = MarketDataType.class.getFields().length;
+ String [] fields = new String[totalFields];
+ for (int i = 0; i < totalFields; i++){
+ fields[i] = MarketDataType.getField(i + 1);
+ }
+ return fields;
+ }
+}
diff --git a/api/com/ib/client/NewsProvider.java b/api/com/ib/client/NewsProvider.java
new file mode 100755
index 0000000..0fe8469
--- /dev/null
+++ b/api/com/ib/client/NewsProvider.java
@@ -0,0 +1,25 @@
+/* Copyright (C) 2018 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/api/com/ib/client/OperatorCondition.java b/api/com/ib/client/OperatorCondition.java
new file mode 100755
index 0000000..c7f9dcc
--- /dev/null
+++ b/api/com/ib/client/OperatorCondition.java
@@ -0,0 +1,47 @@
+/* Copyright (C) 2018 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.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/api/com/ib/client/Order.java b/api/com/ib/client/Order.java
new file mode 100755
index 0000000..8540c8e
--- /dev/null
+++ b/api/com/ib/client/Order.java
@@ -0,0 +1,672 @@
+/* Copyright (C) 2018 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.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;
+ final public static int FIRM = 1;
+ final public static char OPT_UNKNOWN='?';
+ final public static char OPT_BROKER_DEALER='b';
+ final public static char OPT_CUSTOMER ='c';
+ final public static char OPT_FIRM='f';
+ final public static char OPT_ISEMM='m';
+ final public static char OPT_FARMM='n';
+ final public static char OPT_SPECIALIST='y';
+ final public static int AUCTION_MATCH = 1;
+ final public static int AUCTION_IMPROVEMENT = 2;
+ final public static int AUCTION_TRANSPARENT = 3;
+ final public static String EMPTY_STR = "";
+
+ // order id's
+ private int m_clientId;
+ private int m_orderId;
+ private int 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.
+
+ // 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<TagValue> m_algoParams = new ArrayList<>();
+ private String m_algoId;
+
+ // combo orders
+ private List<TagValue> m_smartComboRoutingParams = new ArrayList<>();
+ private List<OrderComboLeg> 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
+ 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
+ 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
+ private int m_auctionStrategy; // 1=AUCTION_MATCH, 2=AUCTION_IMPROVEMENT, 3=AUCTION_TRANSPARENT
+
+ // BOX ORDERS ONLY
+ private double m_startingPrice;
+ private double m_stockRefPrice;
+ private double m_delta = Double.MAX_VALUE;
+
+ // pegged to stock or VOL orders
+ private double m_stockRangeLower;
+ private double m_stockRangeUpper;
+
+ // COMBO ORDERS ONLY
+ private double m_basisPoints; // EFP orders only, download only
+ private int m_basisPointsType; // EFP orders only, download only
+
+ // Not Held
+ private boolean m_notHeld;
+
+ // order misc options
+ private List<TagValue> 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<OrderCondition> 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;
+
+ private String m_mifid2DecisionMaker = EMPTY_STR;
+ private String m_mifid2DecisionAlgo = EMPTY_STR;
+ private String m_mifid2ExecutionTrader = EMPTY_STR;
+ private String m_mifid2ExecutionAlgo = EMPTY_STR;
+
+ // don't use auto price for hedge
+ private boolean m_dontUseAutoPriceForHedge;
+
+ // 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 int 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<OrderComboLeg> 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<TagValue> smartComboRoutingParams() { return m_smartComboRoutingParams; }
+ public List<TagValue> 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<OrderCondition> 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; }
+ public String mifid2DecisionMaker() { return m_mifid2DecisionMaker; }
+ public String mifid2DecisionAlgo() { return m_mifid2DecisionAlgo; }
+ public String mifid2ExecutionTrader() { return m_mifid2ExecutionTrader; }
+ public String mifid2ExecutionAlgo() { return m_mifid2ExecutionAlgo; }
+ public boolean dontUseAutoPriceForHedge() { return m_dontUseAutoPriceForHedge; }
+
+ // 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(int 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<TagValue> 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<OrderComboLeg> 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<TagValue> v) { m_smartComboRoutingParams = v; }
+ public void orderMiscOptions(List<TagValue> 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<OrderCondition> 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 void mifid2DecisionMaker(String v) { m_mifid2DecisionMaker = v; }
+ public void mifid2DecisionAlgo(String v) { m_mifid2DecisionAlgo = v; }
+ public void mifid2ExecutionTrader(String v) { m_mifid2ExecutionTrader = v; }
+ public void mifid2ExecutionAlgo(String v) { m_mifid2ExecutionAlgo = v; }
+ public void dontUseAutoPriceForHedge(boolean v) { m_dontUseAutoPriceForHedge = v; }
+
+
+ public Order() {
+ m_activeStartTime = EMPTY_STR;
+ m_activeStopTime = EMPTY_STR;
+ m_outsideRth = false;
+ m_origin = CUSTOMER;
+ m_designatedLocation = EMPTY_STR;
+ m_optOutSmartRouting = false;
+ m_startingPrice = Double.MAX_VALUE;
+ m_stockRefPrice = Double.MAX_VALUE;
+ m_stockRangeLower = Double.MAX_VALUE;
+ m_stockRangeUpper = Double.MAX_VALUE;
+ m_deltaNeutralConId = 0;
+ m_deltaNeutralSettlingFirm = EMPTY_STR;
+ m_deltaNeutralClearingAccount = EMPTY_STR;
+ m_deltaNeutralClearingIntent = EMPTY_STR;
+ m_deltaNeutralOpenClose = EMPTY_STR;
+ m_deltaNeutralShortSale = false;
+ m_deltaNeutralShortSaleSlot = 0;
+ m_deltaNeutralDesignatedLocation = EMPTY_STR;
+ m_basisPoints = Double.MAX_VALUE;
+ m_basisPointsType = Integer.MAX_VALUE;
+ m_scaleAutoReset = false;
+ 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);
+ m_dontUseAutoPriceForHedge = false;
+ }
+
+ public List<TagValue> algoParams() {
+ if( m_algoParams == null ) {
+ m_algoParams = new ArrayList<>();
+ }
+ return m_algoParams;
+ }
+
+ @Override
+ public boolean equals(Object p_other) {
+ if (this == p_other) {
+ return true;
+ }
+ if (!(p_other instanceof Order)) {
+ return false;
+ }
+ Order l_theOther = (Order)p_other;
+
+ if ( m_permId == l_theOther.m_permId ) {
+ return true;
+ }
+
+ if (m_orderId != l_theOther.m_orderId
+ || m_clientId != l_theOther.m_clientId
+ || m_totalQuantity != l_theOther.m_totalQuantity
+ || m_lmtPrice != l_theOther.m_lmtPrice
+ || m_auxPrice != l_theOther.m_auxPrice
+ || m_ocaType != l_theOther.m_ocaType
+ || m_transmit != l_theOther.m_transmit
+ || m_parentId != l_theOther.m_parentId
+ || m_blockOrder != l_theOther.m_blockOrder
+ || m_sweepToFill != l_theOther.m_sweepToFill
+ || m_displaySize != l_theOther.m_displaySize
+ || m_triggerMethod != l_theOther.m_triggerMethod
+ || m_outsideRth != l_theOther.m_outsideRth
+ || m_hidden != l_theOther.m_hidden
+ || m_overridePercentageConstraints != l_theOther.m_overridePercentageConstraints
+ || m_allOrNone != l_theOther.m_allOrNone
+ || m_minQty != l_theOther.m_minQty
+ || m_percentOffset != l_theOther.m_percentOffset
+ || m_trailStopPrice != l_theOther.m_trailStopPrice
+ || m_trailingPercent != l_theOther.m_trailingPercent
+ || m_origin != l_theOther.m_origin
+ || m_shortSaleSlot != l_theOther.m_shortSaleSlot
+ || m_discretionaryAmt != l_theOther.m_discretionaryAmt
+ || m_eTradeOnly != l_theOther.m_eTradeOnly
+ || m_firmQuoteOnly != l_theOther.m_firmQuoteOnly
+ || m_nbboPriceCap != l_theOther.m_nbboPriceCap
+ || m_optOutSmartRouting != l_theOther.m_optOutSmartRouting
+ || m_auctionStrategy != l_theOther.m_auctionStrategy
+ || m_startingPrice != l_theOther.m_startingPrice
+ || m_stockRefPrice != l_theOther.m_stockRefPrice
+ || m_delta != l_theOther.m_delta
+ || m_stockRangeLower != l_theOther.m_stockRangeLower
+ || m_stockRangeUpper != l_theOther.m_stockRangeUpper
+ || m_volatility != l_theOther.m_volatility
+ || m_volatilityType != l_theOther.m_volatilityType
+ || m_continuousUpdate != l_theOther.m_continuousUpdate
+ || m_referencePriceType != l_theOther.m_referencePriceType
+ || m_deltaNeutralAuxPrice != l_theOther.m_deltaNeutralAuxPrice
+ || m_deltaNeutralConId != l_theOther.m_deltaNeutralConId
+ || m_deltaNeutralShortSale != l_theOther.m_deltaNeutralShortSale
+ || m_deltaNeutralShortSaleSlot != l_theOther.m_deltaNeutralShortSaleSlot
+ || m_basisPoints != l_theOther.m_basisPoints
+ || m_basisPointsType != l_theOther.m_basisPointsType
+ || m_scaleInitLevelSize != l_theOther.m_scaleInitLevelSize
+ || m_scaleSubsLevelSize != l_theOther.m_scaleSubsLevelSize
+ || m_scalePriceIncrement != l_theOther.m_scalePriceIncrement
+ || m_scalePriceAdjustValue != l_theOther.m_scalePriceAdjustValue
+ || m_scalePriceAdjustInterval != l_theOther.m_scalePriceAdjustInterval
+ || m_scaleProfitOffset != l_theOther.m_scaleProfitOffset
+ || m_scaleAutoReset != l_theOther.m_scaleAutoReset
+ || m_scaleInitPosition != l_theOther.m_scaleInitPosition
+ || m_scaleInitFillQty != l_theOther.m_scaleInitFillQty
+ || 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_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
+ || m_dontUseAutoPriceForHedge != l_theOther.m_dontUseAutoPriceForHedge) {
+ return false;
+ }
+
+ if (Util.StringCompare(m_action, l_theOther.m_action) != 0
+ || Util.StringCompare(m_orderType, l_theOther.m_orderType) != 0
+ || Util.StringCompare(m_tif, l_theOther.m_tif) != 0
+ || Util.StringCompare(m_activeStartTime, l_theOther.m_activeStartTime) != 0
+ || Util.StringCompare(m_activeStopTime, l_theOther.m_activeStopTime) != 0
+ || Util.StringCompare(m_ocaGroup, l_theOther.m_ocaGroup) != 0
+ || Util.StringCompare(m_orderRef,l_theOther.m_orderRef) != 0
+ || Util.StringCompare(m_goodAfterTime, l_theOther.m_goodAfterTime) != 0
+ || Util.StringCompare(m_goodTillDate, l_theOther.m_goodTillDate) != 0
+ || Util.StringCompare(m_rule80A, l_theOther.m_rule80A) != 0
+ || Util.StringCompare(m_faGroup, l_theOther.m_faGroup) != 0
+ || Util.StringCompare(m_faProfile, l_theOther.m_faProfile) != 0
+ || Util.StringCompare(m_faMethod, l_theOther.m_faMethod) != 0
+ || Util.StringCompare(m_faPercentage, l_theOther.m_faPercentage) != 0
+ || Util.StringCompare(m_openClose, l_theOther.m_openClose) != 0
+ || Util.StringCompare(m_designatedLocation, l_theOther.m_designatedLocation) != 0
+ || Util.StringCompare(m_deltaNeutralOrderType, l_theOther.m_deltaNeutralOrderType) != 0
+ || Util.StringCompare(m_deltaNeutralSettlingFirm, l_theOther.m_deltaNeutralSettlingFirm) != 0
+ || Util.StringCompare(m_deltaNeutralClearingAccount, l_theOther.m_deltaNeutralClearingAccount) != 0
+ || Util.StringCompare(m_deltaNeutralClearingIntent, l_theOther.m_deltaNeutralClearingIntent) != 0
+ || Util.StringCompare(m_deltaNeutralOpenClose, l_theOther.m_deltaNeutralOpenClose) != 0
+ || Util.StringCompare(m_deltaNeutralDesignatedLocation, l_theOther.m_deltaNeutralDesignatedLocation) != 0
+ || Util.StringCompare(m_hedgeType, l_theOther.m_hedgeType) != 0
+ || Util.StringCompare(m_hedgeParam, l_theOther.m_hedgeParam) != 0
+ || Util.StringCompare(m_account, l_theOther.m_account) != 0
+ || Util.StringCompare(m_settlingFirm, l_theOther.m_settlingFirm) != 0
+ || 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_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
+ || Util.StringCompare(m_mifid2DecisionMaker, l_theOther.m_mifid2DecisionMaker) != 0
+ || Util.StringCompare(m_mifid2DecisionAlgo, l_theOther.m_mifid2DecisionAlgo) != 0
+ || Util.StringCompare(m_mifid2ExecutionTrader, l_theOther.m_mifid2ExecutionTrader) != 0
+ || Util.StringCompare(m_mifid2ExecutionAlgo, l_theOther.m_mifid2ExecutionAlgo) != 0) {
+ return false;
+ }
+
+ if (!Util.listsEqualUnordered(m_algoParams, l_theOther.m_algoParams)) {
+ return false;
+ }
+
+ if (!Util.listsEqualUnordered(m_smartComboRoutingParams, l_theOther.m_smartComboRoutingParams)) {
+ return false;
+ }
+
+ // compare order combo legs
+ 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/api/com/ib/client/OrderComboLeg.java b/api/com/ib/client/OrderComboLeg.java
new file mode 100755
index 0000000..243b401
--- /dev/null
+++ b/api/com/ib/client/OrderComboLeg.java
@@ -0,0 +1,40 @@
+/* Copyright (C) 2018 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 OrderComboLeg {
+ private 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;
+ }
+
+ public OrderComboLeg(double p_price) {
+ m_price = p_price;
+ }
+
+ @Override
+ public boolean equals(Object p_other) {
+ if (this == p_other) {
+ return true;
+ }
+ if (!(p_other instanceof OrderComboLeg)) {
+ return false;
+ }
+
+ OrderComboLeg l_theOther = (OrderComboLeg)p_other;
+
+ return m_price == l_theOther.m_price;
+ }
+
+ @Override
+ public int hashCode() {
+ long temp = Double.doubleToLongBits(m_price);
+ return (int) (temp ^ (temp >>> 32));
+ }
+}
diff --git a/api/com/ib/client/OrderCondition.java b/api/com/ib/client/OrderCondition.java
new file mode 100755
index 0000000..25adca1
--- /dev/null
+++ b/api/com/ib/client/OrderCondition.java
@@ -0,0 +1,75 @@
+/* Copyright (C) 2018 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.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() ? "<AND>" : "<OR>";
+ }
+
+ 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/api/com/ib/client/OrderConditionType.java b/api/com/ib/client/OrderConditionType.java
new file mode 100755
index 0000000..ddefba4
--- /dev/null
+++ b/api/com/ib/client/OrderConditionType.java
@@ -0,0 +1,31 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/OrderState.java b/api/com/ib/client/OrderState.java
new file mode 100755
index 0000000..c9b4e46
--- /dev/null
+++ b/api/com/ib/client/OrderState.java
@@ -0,0 +1,132 @@
+/* Copyright (C) 2018 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 OrderState {
+ private String m_status;
+ private String m_initMarginBefore;
+ private String m_maintMarginBefore;
+ private String m_equityWithLoanBefore;
+ private String m_initMarginChange;
+ private String m_maintMarginChange;
+ private String m_equityWithLoanChange;
+ private String m_initMarginAfter;
+ private String m_maintMarginAfter;
+ private String m_equityWithLoanAfter;
+ 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 initMarginBefore() { return m_initMarginBefore; }
+ public String maintMarginBefore() { return m_maintMarginBefore; }
+ public String equityWithLoanBefore() { return m_equityWithLoanBefore; }
+ public String initMarginChange() { return m_initMarginChange; }
+ public String maintMarginChange() { return m_maintMarginChange; }
+ public String equityWithLoanChange() { return m_equityWithLoanChange; }
+ public String initMarginAfter() { return m_initMarginAfter; }
+ public String maintMarginAfter() { return m_maintMarginAfter; }
+ public String equityWithLoanAfter() { return m_equityWithLoanAfter; }
+ 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 initMarginBefore(String v) { m_initMarginBefore = v; }
+ public void maintMarginBefore(String v) { m_maintMarginBefore = v; }
+ public void equityWithLoanBefore(String v) { m_equityWithLoanBefore = v; }
+ public void initMarginChange(String v) { m_initMarginChange = v; }
+ public void maintMarginChange(String v) { m_maintMarginChange = v; }
+ public void equityWithLoanChange(String v) { m_equityWithLoanChange = v; }
+ public void initMarginAfter(String v) { m_initMarginAfter = v; }
+ public void maintMarginAfter(String v) { m_maintMarginAfter = v; }
+ public void equityWithLoanAfter(String v) { m_equityWithLoanAfter = 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, null, null, null, null, null, null, 0.0, 0.0, 0.0, null, null);
+ }
+
+ OrderState(String status,
+ String initMarginBefore, String maintMarginBefore, String equityWithLoanBefore,
+ String initMarginChange, String maintMarginChange, String equityWithLoanChange,
+ String initMarginAfter, String maintMarginAfter, String equityWithLoanAfter,
+ double commission, double minCommission,
+ double maxCommission, String commissionCurrency, String warningText) {
+ m_status = status;
+ m_initMarginBefore = initMarginBefore;
+ m_maintMarginBefore = maintMarginBefore;
+ m_equityWithLoanBefore = equityWithLoanBefore;
+ m_initMarginChange = initMarginChange;
+ m_maintMarginChange = maintMarginChange;
+ m_equityWithLoanChange = equityWithLoanChange;
+ m_initMarginAfter = initMarginAfter;
+ m_maintMarginAfter = maintMarginAfter;
+ m_equityWithLoanAfter = equityWithLoanAfter;
+ m_commission = commission;
+ m_minCommission = minCommission;
+ m_maxCommission = maxCommission;
+ m_commissionCurrency = commissionCurrency;
+ m_warningText = warningText;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof OrderState)) {
+ return false;
+ }
+ OrderState state = (OrderState)other;
+
+ if (m_commission != state.m_commission ||
+ m_minCommission != state.m_minCommission ||
+ m_maxCommission != state.m_maxCommission) {
+ return false;
+ }
+
+ if (Util.StringCompare(m_status, state.m_status) != 0 ||
+ Util.StringCompare(m_initMarginBefore, state.m_initMarginBefore) != 0 ||
+ Util.StringCompare(m_maintMarginBefore, state.m_maintMarginBefore) != 0 ||
+ Util.StringCompare(m_equityWithLoanBefore, state.m_equityWithLoanBefore) != 0 ||
+ Util.StringCompare(m_initMarginChange, state.m_initMarginChange) != 0 ||
+ Util.StringCompare(m_maintMarginChange, state.m_maintMarginChange) != 0 ||
+ Util.StringCompare(m_equityWithLoanChange, state.m_equityWithLoanChange) != 0 ||
+ Util.StringCompare(m_initMarginAfter, state.m_initMarginAfter) != 0 ||
+ Util.StringCompare(m_maintMarginAfter, state.m_maintMarginAfter) != 0 ||
+ Util.StringCompare(m_equityWithLoanAfter, state.m_equityWithLoanAfter) != 0 ||
+ 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/api/com/ib/client/OrderStatus.java b/api/com/ib/client/OrderStatus.java
new file mode 100755
index 0000000..9fa0a54
--- /dev/null
+++ b/api/com/ib/client/OrderStatus.java
@@ -0,0 +1,31 @@
+/* Copyright (C) 2018 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 enum OrderStatus {
+ ApiPending,
+ ApiCancelled,
+ PreSubmitted,
+ PendingCancel,
+ Cancelled,
+ Submitted,
+ Filled,
+ Inactive,
+ 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/api/com/ib/client/OrderType.java b/api/com/ib/client/OrderType.java
new file mode 100755
index 0000000..e5c4fd4
--- /dev/null
+++ b/api/com/ib/client/OrderType.java
@@ -0,0 +1,74 @@
+/* Copyright (C) 2018 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 enum OrderType implements IApiEnum {
+ None( ""),
+ MKT( "MKT"),
+ LMT( "LMT"),
+ STP( "STP"),
+ STP_LMT( "STP LMT"),
+ REL( "REL"),
+ TRAIL( "TRAIL"),
+ BOX_TOP( "BOX TOP"),
+ FIX_PEGGED( "FIX PEGGED"),
+ LIT( "LIT"),
+ LMT_PLUS_MKT( "LMT + MKT"),
+ LOC( "LOC"),
+ MIT( "MIT"),
+ MKT_PRT( "MKT PRT"),
+ MOC( "MOC"),
+ MTL( "MTL"),
+ PASSV_REL( "PASSV REL"),
+ PEG_BENCH( "PEG BENCH"),
+ PEG_MID( "PEG MID"),
+ PEG_MKT( "PEG MKT"),
+ PEG_PRIM( "PEG PRIM"),
+ 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"),
+ TRAIL_LMT_PLUS_MKT( "TRAIL LMT + MKT"),
+ TRAIL_MIT( "TRAIL MIT"),
+ TRAIL_REL_PLUS_MKT( "TRAIL REL + MKT"),
+ VOL( "VOL"),
+ VWAP( "VWAP"),
+ QUOTE("QUOTE"),
+ PEG_PRIM_VOL("PPV"),
+ PEG_MID_VOL("PDV"),
+ PEG_MKT_VOL("PMV"),
+ PEG_SRF_VOL("PSV");
+
+ private String m_apiString;
+
+ OrderType( String apiString) {
+ m_apiString = apiString;
+ }
+
+ public static OrderType get(String apiString) {
+ if (apiString != null && apiString.length() > 0 && !apiString.equals( "None") ) {
+ for (OrderType type : values() ) {
+ if (type.m_apiString.equals( apiString) ) {
+ return type;
+ }
+ }
+ }
+ return None;
+ }
+
+ @Override public String toString() {
+ return this == None ? super.toString() : m_apiString;
+ }
+
+ @Override public String getApiString() {
+ return m_apiString;
+ }
+
+}
diff --git a/api/com/ib/client/PercentChangeCondition.java b/api/com/ib/client/PercentChangeCondition.java
new file mode 100755
index 0000000..0a070b0
--- /dev/null
+++ b/api/com/ib/client/PercentChangeCondition.java
@@ -0,0 +1,42 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/PriceCondition.java b/api/com/ib/client/PriceCondition.java
new file mode 100755
index 0000000..1011bb2
--- /dev/null
+++ b/api/com/ib/client/PriceCondition.java
@@ -0,0 +1,73 @@
+/* Copyright (C) 2018 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.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/api/com/ib/client/PriceIncrement.java b/api/com/ib/client/PriceIncrement.java
new file mode 100755
index 0000000..706a9fb
--- /dev/null
+++ b/api/com/ib/client/PriceIncrement.java
@@ -0,0 +1,25 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/ScannerSubscription.java b/api/com/ib/client/ScannerSubscription.java
new file mode 100755
index 0000000..cdfba7f
--- /dev/null
+++ b/api/com/ib/client/ScannerSubscription.java
@@ -0,0 +1,76 @@
+/* Copyright (C) 2018 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 ScannerSubscription {
+ public final static int NO_ROW_NUMBER_SPECIFIED = -1;
+
+ private int m_numberOfRows = NO_ROW_NUMBER_SPECIFIED;
+ private String m_instrument;
+ private String m_locationCode;
+ private String m_scanCode;
+ private double m_abovePrice = Double.MAX_VALUE;
+ private double m_belowPrice = Double.MAX_VALUE;
+ private int m_aboveVolume = Integer.MAX_VALUE;
+ private int m_averageOptionVolumeAbove = Integer.MAX_VALUE;
+ private double m_marketCapAbove = Double.MAX_VALUE;
+ private double m_marketCapBelow = Double.MAX_VALUE;
+ private String m_moodyRatingAbove;
+ private String m_moodyRatingBelow;
+ private String m_spRatingAbove;
+ private String m_spRatingBelow;
+ private String m_maturityDateAbove;
+ private String m_maturityDateBelow;
+ private double m_couponRateAbove = Double.MAX_VALUE;
+ private double m_couponRateBelow = Double.MAX_VALUE;
+ private String m_excludeConvertible;
+ private String m_scannerSettingPairs;
+ private String m_stockTypeFilter;
+
+ // Get
+ public int numberOfRows() { return m_numberOfRows; }
+ public String instrument() { return m_instrument; }
+ public String locationCode() { return m_locationCode; }
+ public String scanCode() { return m_scanCode; }
+ public double abovePrice() { return m_abovePrice; }
+ public double belowPrice() { return m_belowPrice; }
+ public int aboveVolume() { return m_aboveVolume; }
+ public int averageOptionVolumeAbove() { return m_averageOptionVolumeAbove; }
+ public double marketCapAbove() { return m_marketCapAbove; }
+ public double marketCapBelow() { return m_marketCapBelow; }
+ public String moodyRatingAbove() { return m_moodyRatingAbove; }
+ public String moodyRatingBelow() { return m_moodyRatingBelow; }
+ public String spRatingAbove() { return m_spRatingAbove; }
+ public String spRatingBelow() { return m_spRatingBelow; }
+ public String maturityDateAbove() { return m_maturityDateAbove; }
+ public String maturityDateBelow() { return m_maturityDateBelow; }
+ public double couponRateAbove() { return m_couponRateAbove; }
+ public double couponRateBelow() { return m_couponRateBelow; }
+ public String excludeConvertible() { return m_excludeConvertible; }
+ public String scannerSettingPairs() { return m_scannerSettingPairs; }
+ public String stockTypeFilter() { return m_stockTypeFilter; }
+
+ // Set
+ public void numberOfRows(int num) { m_numberOfRows = num; }
+ public void instrument(String txt) { m_instrument = txt; }
+ public void locationCode(String txt) { m_locationCode = txt; }
+ public void scanCode(String txt) { m_scanCode = txt; }
+ public void abovePrice(double price) { m_abovePrice = price; }
+ public void belowPrice(double price) { m_belowPrice = price; }
+ public void aboveVolume(int volume) { m_aboveVolume = volume; }
+ public void averageOptionVolumeAbove(int volume) { m_averageOptionVolumeAbove = volume; }
+ public void marketCapAbove(double cap) { m_marketCapAbove = cap; }
+ public void marketCapBelow(double cap) { m_marketCapBelow = cap; }
+ public void moodyRatingAbove(String r) { m_moodyRatingAbove = r; }
+ public void moodyRatingBelow(String r) { m_moodyRatingBelow = r; }
+ public void spRatingAbove(String r) { m_spRatingAbove = r; }
+ public void spRatingBelow(String r) { m_spRatingBelow = r; }
+ public void maturityDateAbove(String d) { m_maturityDateAbove = d; }
+ public void maturityDateBelow(String d) { m_maturityDateBelow = d; }
+ public void couponRateAbove(double r) { m_couponRateAbove = r; }
+ public void couponRateBelow(double r) { m_couponRateBelow = r; }
+ public void excludeConvertible(String c) { m_excludeConvertible = c; }
+ public void scannerSettingPairs(String val) { m_scannerSettingPairs = val; }
+ public void stockTypeFilter(String val) { m_stockTypeFilter = val; }
+}
diff --git a/api/com/ib/client/SoftDollarTier.java b/api/com/ib/client/SoftDollarTier.java
new file mode 100755
index 0000000..81778eb
--- /dev/null
+++ b/api/com/ib/client/SoftDollarTier.java
@@ -0,0 +1,81 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/TagValue.java b/api/com/ib/client/TagValue.java
new file mode 100755
index 0000000..e98020d
--- /dev/null
+++ b/api/com/ib/client/TagValue.java
@@ -0,0 +1,38 @@
+/* Copyright (C) 2018 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 final class TagValue {
+ public String m_tag;
+ public String m_value;
+
+ public TagValue() {
+ }
+
+ public TagValue(String p_tag, String p_value) {
+ m_tag = p_tag;
+ m_value = p_value;
+ }
+
+ @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;
+
+ return Util.StringCompare(m_tag, l_theOther.m_tag) == 0
+ && Util.StringCompare(m_value, l_theOther.m_value) == 0;
+ }
+
+ @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/api/com/ib/client/TickAttr.java b/api/com/ib/client/TickAttr.java
new file mode 100755
index 0000000..409006e
--- /dev/null
+++ b/api/com/ib/client/TickAttr.java
@@ -0,0 +1,50 @@
+/* Copyright (C) 2018 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;
+ private boolean m_preOpen = false;
+ private boolean m_unreported = false;
+ private boolean m_bidPastLow = false;
+ private boolean m_askPastHigh = false;
+
+ public boolean canAutoExecute() {
+ return m_canAutoExecute;
+ }
+ public boolean pastLimit() {
+ return m_pastLimit;
+ }
+ public boolean preOpen() {
+ return m_preOpen;
+ }
+ public boolean unreported() {
+ return m_unreported;
+ }
+ public boolean bidPastLow() {
+ return m_bidPastLow;
+ }
+ public boolean askPastHigh() {
+ return m_askPastHigh;
+ }
+ public void canAutoExecute(boolean canAutoExecute) {
+ this.m_canAutoExecute = canAutoExecute;
+ }
+ public void pastLimit(boolean pastLimit) {
+ this.m_pastLimit = pastLimit;
+ }
+ public void preOpen(boolean preOpen) {
+ this.m_preOpen = preOpen;
+ }
+ public void unreported(boolean unreported) {
+ this.m_unreported = unreported;
+ }
+ public void bidPastLow(boolean bidPastLow) {
+ this.m_bidPastLow = bidPastLow;
+ }
+ public void askPastHigh(boolean askPastHigh) {
+ this.m_askPastHigh = askPastHigh;
+ }
+}
diff --git a/api/com/ib/client/TickByTick.java b/api/com/ib/client/TickByTick.java
new file mode 100755
index 0000000..a85bd69
--- /dev/null
+++ b/api/com/ib/client/TickByTick.java
@@ -0,0 +1,102 @@
+/* Copyright (C) 2018 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 TickByTick {
+ private int m_tickType; // 0 - None, 1 - Last, 2 - AllLast, 3 -BidAsk, 4 - MidPoint
+ private long m_time; // in seconds
+ private double m_price;
+ private long m_size;
+ private TickAttr m_attribs;
+ private String m_exchange;
+ private String m_specialConditions;
+ private double m_bidPrice;
+ private long m_bidSize;
+ private double m_askPrice;
+ private long m_askSize;
+ private double m_midPoint;
+
+ public TickByTick(int tickType, long time, double price, long size, TickAttr attribs, String exchange, String specialConditions) {
+ m_tickType = tickType;
+ m_time = time;
+ m_price = price;
+ m_size = size;
+ m_attribs = attribs;
+ m_exchange = exchange;
+ m_specialConditions = specialConditions;
+ }
+
+ public TickByTick(long time, double bidPrice, long bidSize, double askPrice, long askSize, TickAttr attribs) {
+ m_tickType = 3;
+ m_time = time;
+ m_bidPrice = bidPrice;
+ m_bidSize = bidSize;
+ m_askPrice = askPrice;
+ m_askSize = askSize;
+ m_attribs = attribs;
+ }
+
+ public TickByTick(long time, double midPoint) {
+ m_tickType = 4;
+ m_time = time;
+ m_midPoint = midPoint;
+ }
+
+ public int tickType() {
+ return m_tickType;
+ }
+
+ public long time() {
+ return m_time;
+ }
+
+ public double price() {
+ return m_price;
+ }
+
+ public long size() {
+ return m_size;
+ }
+
+ public TickAttr attribs() {
+ return m_attribs;
+ }
+
+ public String attribsStr() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(m_attribs.pastLimit() ? "PastLimit " : "");
+ sb.append(m_attribs.unreported() ? "Unreported " : "");
+ sb.append(m_attribs.bidPastLow() ? "BidPastLow " : "");
+ sb.append(m_attribs.askPastHigh() ? "AskPastHigh " : "");
+ return sb.toString();
+ }
+
+ public String exchange() {
+ return m_exchange;
+ }
+
+ public String specialConditions() {
+ return m_specialConditions;
+ }
+
+ public double bidPrice() {
+ return m_bidPrice;
+ }
+
+ public long bidSize() {
+ return m_bidSize;
+ }
+
+ public double askPrice() {
+ return m_askPrice;
+ }
+
+ public long askSize() {
+ return m_askSize;
+ }
+
+ public double midPoint() {
+ return m_midPoint;
+ }
+} \ No newline at end of file
diff --git a/api/com/ib/client/TickType.java b/api/com/ib/client/TickType.java
new file mode 100755
index 0000000..c53e527
--- /dev/null
+++ b/api/com/ib/client/TickType.java
@@ -0,0 +1,124 @@
+/* Copyright (C) 2018 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 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"),
+ AVG_OPT_VOLUME(87, "avgOptVolume"),
+ DELAYED_LAST_TIMESTAMP(88, "delayedLastTimestamp"),
+
+ 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/api/com/ib/client/TimeCondition.java b/api/com/ib/client/TimeCondition.java
new file mode 100755
index 0000000..d708c34
--- /dev/null
+++ b/api/com/ib/client/TimeCondition.java
@@ -0,0 +1,37 @@
+/* Copyright (C) 2018 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 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/api/com/ib/client/Types.java b/api/com/ib/client/Types.java
new file mode 100755
index 0000000..8c79045
--- /dev/null
+++ b/api/com/ib/client/Types.java
@@ -0,0 +1,372 @@
+/* Copyright (C) 2018 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;
+
+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 enum TickByTickType {
+ None, Last, AllLast, BidAsk, MidPoint,
+ }
+
+ public enum ComboParam {
+ NonGuaranteed, PriceCondConid, CondPriceMax, CondPriceMin, ChangeToMktTime1, ChangeToMktTime2, DiscretionaryPct, DontLeginNext, LeginPrio, MaxSegSize,
+ }
+
+ public enum AlgoParam {
+ startTime, endTime, allowPastEndTime, maxPctVol, pctVol, strategyType, noTakeLiq, riskAversion, forceCompletion, displaySize, getDone, noTradeAhead, useOddLots,
+ componentSize, timeBetweenOrders, randomizeTime20, randomizeSize55, giveUp, catchUp, waitForFill
+ }
+
+ public enum AlgoStrategy implements IApiEnum {
+ None(),
+ Vwap( startTime, endTime, maxPctVol, noTakeLiq, getDone, noTradeAhead, useOddLots),
+ Twap( startTime, endTime, allowPastEndTime, strategyType),
+ ArrivalPx( startTime, endTime, allowPastEndTime, maxPctVol, riskAversion, forceCompletion),
+ DarkIce( startTime, endTime, allowPastEndTime, displaySize),
+ PctVol( startTime, endTime, pctVol, noTakeLiq),
+ AD( startTime, endTime, componentSize, timeBetweenOrders, randomizeTime20, randomizeSize55, giveUp, catchUp, waitForFill);
+
+ private AlgoParam[] m_params;
+
+ public AlgoParam[] params() {
+ return Arrays.copyOf(m_params, m_params.length);
+ }
+
+ AlgoStrategy( AlgoParam... params) {
+ m_params = Arrays.copyOf(params, params.length);
+ }
+
+ public static AlgoStrategy get(String apiString) {
+ return getValueOf(apiString, values(), None);
+ }
+
+ @Override public String getApiString() {
+ return this == None ? "" : super.toString();
+ }
+ }
+
+ public enum HedgeType implements IApiEnum {
+ None, Delta, Beta, Fx, Pair;
+
+ public static HedgeType get(String apiString) {
+ return getValueOf(apiString, values(), None);
+ }
+
+ @Override public String getApiString() {
+ return this == None ? "" : String.valueOf( super.toString().charAt( 0) );
+ }
+ }
+
+ public enum Right implements IApiEnum {
+ None, Put, Call;
+
+ public static Right get( String apiString) {
+ if (apiString != null && apiString.length() > 0) {
+ switch( apiString.charAt( 0) ) {
+ case 'P' : return Put;
+ case 'C' : return Call;
+ }
+ }
+ return None;
+ }
+
+ @Override public String getApiString() {
+ return this == None ? "" : String.valueOf( toString().charAt( 0) );
+ }
+ }
+
+ public enum VolatilityType implements IApiEnum {
+ None, Daily, Annual;
+
+ public static VolatilityType get( int ordinal) {
+ return ordinal == Integer.MAX_VALUE ? None : getEnum( ordinal, values() );
+ }
+
+ @Override public String getApiString() {
+ return String.valueOf(ordinal());
+ }
+ }
+
+ public enum ReferencePriceType implements IApiEnum {
+ None, Midpoint, BidOrAsk;
+
+ public static ReferencePriceType get( int ordinal) {
+ return getEnum( ordinal, values() );
+ }
+
+ @Override public String getApiString() {
+ return String.valueOf(ordinal());
+ }
+ }
+
+ 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; }
+
+ TriggerMethod( int val) {
+ m_val = val;
+ }
+
+ public static TriggerMethod get( int val) {
+ for (TriggerMethod m : values() ) {
+ if (m.m_val == val) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ @Override public String getApiString() {
+ return String.valueOf(m_val);
+ }
+ }
+
+ public enum Action implements IApiEnum {
+ BUY, SELL, SSHORT;
+
+ public static Action get(String apiString) {
+ return getValueOf(apiString, values(), null);
+ }
+
+ @Override public String getApiString() {
+ return toString();
+ }
+ }
+
+ public enum Rule80A implements IApiEnum {
+ None(""), Individual("I"), Agency("A"), AgentOtherMember("W"), IndividualPTIA("J"), AgencyPTIA("U"), AgentOtherMemberPTIA("M"), IndividualPT("K"), AgencyPT("Y"), AgentOtherMemberPT("N");
+
+ private String m_apiString;
+
+ Rule80A( String apiString) {
+ m_apiString = apiString;
+ }
+
+ public static Rule80A get( String apiString) {
+ return getValueOf(apiString, values(), None);
+ }
+
+ @Override
+ public String getApiString() {
+ return m_apiString;
+ }
+ }
+
+ public enum OcaType implements IApiEnum {
+ None, CancelWithBlocking, ReduceWithBlocking, ReduceWithoutBlocking;
+
+ public static OcaType get( int ordinal) {
+ return getEnum( ordinal, values() );
+ }
+
+ @Override public String getApiString() {
+ return String.valueOf(ordinal());
+ }
+ }
+
+ 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 enum ExerciseType {
+ None, Exercise, Lapse,
+ }
+
+ 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() {
+ return description;
+ }
+ }
+
+ 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, ADJUSTED_LAST
+ }
+
+ 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 enum DurationUnit {
+ SECOND, DAY, WEEK, MONTH, YEAR,
+ }
+
+ public enum DeepType {
+ INSERT, UPDATE, DELETE;
+
+ public static DeepType get( int ordinal) {
+ return getEnum( ordinal, values() );
+ }
+ }
+
+ public enum DeepSide {
+ SELL, BUY;
+
+ public static DeepSide get( int ordinal) {
+ return getEnum( ordinal, values() );
+ }
+ }
+
+ public enum NewsType {
+ UNKNOWN, BBS, LIVE_EXCH, DEAD_EXCH, HTML, POPUP_TEXT, POPUP_HTML;
+
+ public static NewsType get( int ordinal) {
+ return getEnum( ordinal, values() );
+ }
+ }
+
+ public enum FADataType {
+ UNUSED, GROUPS, PROFILES, ALIASES;
+
+ public static FADataType get( int ordinal) {
+ return getEnum( ordinal, values() );
+ }
+ }
+
+ public enum SecIdType implements IApiEnum {
+ None, CUSIP, SEDOL, ISIN, RIC;
+
+ public static SecIdType get(String str) {
+ return getValueOf(str, values(), None);
+ }
+
+ @Override public String getApiString() {
+ return this == None ? "" : super.toString();
+ }
+ }
+
+ public enum SecType implements IApiEnum {
+ 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();
+ }
+ }
+
+ public enum MktDataType {
+ Unknown, Realtime, Frozen, Delayed, DelayedFrozen;
+
+ public static MktDataType get( int ordinal) {
+ return getEnum( ordinal, values() );
+ }
+ }
+
+ public enum Method implements IApiEnum {
+ None, EqualQuantity, AvailableEquity, NetLiq, PctChange;
+
+ public static Method get( String str) {
+ return getValueOf(str, values(), None);
+ }
+
+ @Override public String getApiString() {
+ return this == None ? "" : super.toString();
+ }
+ }
+
+ public static <T extends Enum<?> & 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 extends Enum<T>> T getEnum(int ordinal, T[] values) {
+ if (ordinal == Integer.MAX_VALUE) {
+ return null;
+ }
+
+ for (T val : values) {
+ if (val.ordinal() == ordinal) {
+ return val;
+ }
+ }
+ String str = String.format( "Error: %s is not a valid value for enum %s", ordinal, values[0].getClass().getName() );
+ throw new IllegalArgumentException( str);
+ }
+}
diff --git a/api/com/ib/client/Util.java b/api/com/ib/client/Util.java
new file mode 100755
index 0000000..d63a56f
--- /dev/null
+++ b/api/com/ib/client/Util.java
@@ -0,0 +1,118 @@
+/* Copyright (C) 2018 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.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+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;
+ }
+
+ public static String NormalizeString(String str) {
+ return str != null ? str : "";
+ }
+
+ public static int StringCompare(String lhs, String rhs) {
+ return NormalizeString(lhs).compareTo(NormalizeString(rhs));
+ }
+
+ public static int StringCompareIgnCase(String lhs, String rhs) {
+ return NormalizeString(lhs).compareToIgnoreCase(NormalizeString(rhs));
+ }
+
+ public static boolean listsEqualUnordered(List<?> lhs, List<?> rhs) {
+ if (lhs == rhs)
+ return true;
+
+ int lhsCount = lhs == null ? 0 : lhs.size();
+ int rhsCount = rhs == null ? 0 : rhs.size();
+
+ if (lhsCount != rhsCount)
+ return false;
+
+ if (lhsCount == 0)
+ return true;
+
+ boolean[] matchedRhsElems = new boolean[rhsCount];
+
+ for (int lhsIdx = 0; lhsIdx < lhsCount; ++lhsIdx) {
+ Object lhsElem = lhs.get(lhsIdx);
+ int rhsIdx = 0;
+ for (; rhsIdx < rhsCount; ++rhsIdx) {
+ if (matchedRhsElems[rhsIdx]) {
+ continue;
+ }
+ if (lhsElem.equals(rhs.get(rhsIdx))) {
+ matchedRhsElems[rhsIdx] = true;
+ break;
+ }
+ }
+ if (rhsIdx >= rhsCount) {
+ // no matching elem found
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static String IntMaxString(int value) {
+ return (value == Integer.MAX_VALUE) ? "" : String.valueOf(value);
+ }
+
+ public static String DoubleMaxString(double 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 String UnixSecondsToString(long seconds, String dateFormat){
+ return UnixMillisecondsToString(seconds * 1000, dateFormat);
+ }
+
+ public static List<ContractDetails> lookupContract(ApiController controller, Contract contract) {
+ if (controller == null) {
+ return new ArrayList<>();
+ }
+ final CompletableFuture<List<ContractDetails>> future = new CompletableFuture<>();
+
+ controller.reqContractDetails(contract, new IContractDetailsHandler() {
+
+ private final List<ContractDetails> contractDetails = new ArrayList<>();
+
+ @Override
+ public void contractDetails(List<ContractDetails> 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<>();
+ }
+ }
+
+ public static String maxDoubleToString(Double value){
+ return value != Double.MAX_VALUE ? Double.toString(value) : "N/A";
+ }
+}
diff --git a/api/com/ib/client/VolumeCondition.java b/api/com/ib/client/VolumeCondition.java
new file mode 100755
index 0000000..755e69c
--- /dev/null
+++ b/api/com/ib/client/VolumeCondition.java
@@ -0,0 +1,42 @@
+/* Copyright (C) 2018 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 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/api/com/ib/contracts/ComboContract.java b/api/com/ib/contracts/ComboContract.java
new file mode 100755
index 0000000..66e8367
--- /dev/null
+++ b/api/com/ib/contracts/ComboContract.java
@@ -0,0 +1,24 @@
+/* Copyright (C) 2018 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.contracts;
+
+import com.ib.client.Contract;
+import com.ib.client.Types.SecType;
+
+public class ComboContract extends Contract {
+ 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/api/com/ib/contracts/FutContract.java b/api/com/ib/contracts/FutContract.java
new file mode 100755
index 0000000..cd07912
--- /dev/null
+++ b/api/com/ib/contracts/FutContract.java
@@ -0,0 +1,24 @@
+/* Copyright (C) 2018 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.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 lastTradeDateOrContractMonth, String currency) {
+ symbol(symbol);
+ secType(SecType.FUT.name());
+ currency(currency);
+ lastTradeDateOrContractMonth(lastTradeDateOrContractMonth);
+ }
+}
diff --git a/api/com/ib/contracts/OptContract.java b/api/com/ib/contracts/OptContract.java
new file mode 100755
index 0000000..c59cdc4
--- /dev/null
+++ b/api/com/ib/contracts/OptContract.java
@@ -0,0 +1,23 @@
+/* Copyright (C) 2018 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.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 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/api/com/ib/contracts/StkContract.java b/api/com/ib/contracts/StkContract.java
new file mode 100755
index 0000000..b869164
--- /dev/null
+++ b/api/com/ib/contracts/StkContract.java
@@ -0,0 +1,16 @@
+/* Copyright (C) 2018 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.contracts;
+
+import com.ib.client.Contract;
+import com.ib.client.Types.SecType;
+
+public class StkContract extends Contract {
+ public StkContract(String symbol) {
+ symbol(symbol);
+ secType(SecType.STK.name());
+ exchange("SMART");
+ currency("USD");
+ }
+}
diff --git a/api/com/ib/controller/AccountSummaryTag.java b/api/com/ib/controller/AccountSummaryTag.java
new file mode 100755
index 0000000..7cc564f
--- /dev/null
+++ b/api/com/ib/controller/AccountSummaryTag.java
@@ -0,0 +1,46 @@
+/* Copyright (C) 2018 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 AccountSummaryTag {
+ AccountType,
+
+ // balances
+ NetLiquidation,
+ TotalCashValue, // Total cash including futures pnl
+ SettledCash, // For cash accounts, this is the same as TotalCashValue
+ AccruedCash, // Net accrued interest
+ BuyingPower, // The maximum amount of marginable US stocks the account can buy
+ EquityWithLoanValue, // Cash + stocks + bonds + mutual funds
+ PreviousEquityWithLoanValue,
+ GrossPositionValue, // The sum of the absolute value of all stock and equity option positions
+ RegTEquity,
+ RegTMargin,
+ SMA, // Special Memorandum Account
+
+ // current margin
+ InitMarginReq,
+ MaintMarginReq,
+ AvailableFunds,
+ ExcessLiquidity,
+ Cushion, // Excess liquidity as a percentage of net liquidation value
+
+ // overnight margin
+ FullInitMarginReq,
+ FullMaintMarginReq,
+ FullAvailableFunds,
+ FullExcessLiquidity,
+
+ // look-ahead margin
+ LookAheadNextChange, // Time when look-ahead values take effect
+ LookAheadInitMarginReq,
+ LookAheadMaintMarginReq,
+ LookAheadAvailableFunds,
+ LookAheadExcessLiquidity,
+
+ // misc
+ HighestSeverity, // A measure of how close the account is to liquidation
+ DayTradesRemaining, // The Number of Open/Close trades one could do before Pattern Day Trading is detected; a value of "-1" means user can do unlimited day trades.
+ Leverage, // GrossPositionValue / NetLiquidation
+}
diff --git a/api/com/ib/controller/AdvisorUtil.java b/api/com/ib/controller/AdvisorUtil.java
new file mode 100755
index 0000000..bf80292
--- /dev/null
+++ b/api/com/ib/controller/AdvisorUtil.java
@@ -0,0 +1,335 @@
+/* Copyright (C) 2018 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.BufferedReader;
+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;
+
+
+
+public class AdvisorUtil {
+ static List<Group> getGroups( String xml) {
+ try {
+ return getGroups_( xml);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ static List<Group> getGroups_( String xml) throws IOException {
+ List<Group> list = new ArrayList<>();
+
+ Group group = null;
+
+ BufferedReader reader = new BufferedReader( new StringReader( xml) );
+ String line;
+ int state = 0; // 0=none; 1=list of groups; 2=reading group 3=listOfAccts
+ while ( (line=reader.readLine()) != null) {
+ line = line.trim();
+
+ switch( state) {
+ // top of file
+ case 0:
+ if (line.equals( "<ListOfGroups>")) {
+ state = 1;
+ }
+ break;
+
+ // reading groups
+ case 1:
+ if (line.equals( "<Group>")) {
+ group = new Group();
+ state = 2;
+ }
+ else if (line.equals( "</ListOfGroups>")) {
+ state = 0;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // reading group
+ case 2:
+ if (line.startsWith( "<name>") ) {
+ group.name( getVal( line) );
+ }
+ else if (line.startsWith( "<defaultMethod>")) {
+ group.defaultMethod( Method.valueOf( getVal( line) ) );
+ }
+ else if (line.startsWith( "<ListOfAccts")) {
+ state = 3;
+ }
+ else if (line.equals( "</Group>")) {
+ list.add( group);
+ state = 1;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // reading list of accts
+ case 3:
+ if (line.equals( "</ListOfAccts>")) {
+ state = 2;
+ }
+ else {
+ group.addAccount( getVal( line) );
+ }
+ break;
+
+ // should not happen
+ default:
+ break;
+ }
+ }
+
+ return list;
+ }
+
+ static List<Profile> getProfiles( String xml) {
+ try {
+ return getProfiles_( xml);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ static List<Profile> getProfiles_( String xml) throws IOException {
+ List<Profile> list = new ArrayList<>();
+
+ Profile profile = null;
+ Allocation alloc = null;
+
+ BufferedReader reader = new BufferedReader( new StringReader( xml) );
+ String line;
+ int state = 0; // 0=none; 1=list of groups; 2=reading group 3=listOfAllocations 4=allocation
+ while ( (line=reader.readLine() ) != null) {
+ line = line.trim();
+
+ switch( state) {
+ // top of file
+ case 0:
+ if (line.equals( "<ListOfAllocationProfiles>")) {
+ state = 1;
+ }
+ break;
+
+ // reading profiles
+ case 1:
+ if (line.equals( "<AllocationProfile>")) {
+ profile = new Profile();
+ state = 2;
+ }
+ else if (line.equals( "</ListOfAllocationProfiles>")) {
+ state = 0;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // reading Profile
+ case 2:
+ if (line.startsWith( "<name>") ) {
+ profile.name( getVal( line) );
+ }
+ else if (line.startsWith( "<type>")) {
+ int i = Integer.parseInt( getVal( line) );
+ profile.type( Type.get( i) );
+ }
+ else if (line.startsWith( "<ListOfAllocations")) {
+ state = 3;
+ }
+ else if (line.equals( "</AllocationProfile>")) {
+ list.add( profile);
+ state = 1;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // reading list of allocations
+ case 3:
+ if (line.equals( "<Allocation>")) {
+ alloc = new Allocation();
+ state = 4;
+ }
+ else if (line.equals( "</ListOfAllocations>")) {
+ state = 2;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // reading Allocation
+ case 4:
+ if (line.startsWith( "<acct>") ) {
+ alloc.account( getVal( line) );
+ }
+ else if (line.startsWith( "<amount>") ) {
+ alloc.amount( getVal( line) );
+ }
+ else if (line.startsWith( "<posEff>") ) {
+ // skip this
+ }
+ else if (line.equals( "</Allocation>") ) {
+ profile.add( alloc);
+ state = 3;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // should not happen
+ default:
+ break;
+ }
+ }
+
+ return list;
+ }
+
+ static List<Alias> getAliases( String xml) {
+ try {
+ return getAliases_( xml);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ static List<Alias> getAliases_( String xml) throws IOException {
+ List<Alias> list = new ArrayList<>();
+
+ Alias alias = null;
+
+ BufferedReader reader = new BufferedReader( new StringReader( xml) );
+ String line;
+ int state = 0; // 0=none; 1=list of aliases; 2=reading alias
+ while ( (line=reader.readLine() ) != null) {
+ line = line.trim();
+
+ switch( state) {
+ // top of file
+ case 0:
+ if (line.equals( "<ListOfAccountAliases>")) {
+ state = 1;
+ }
+ break;
+
+ // reading aliases
+ case 1:
+ if (line.equals( "<AccountAlias>")) {
+ alias = new Alias();
+ state = 2;
+ }
+ else if (line.equals( "</ListOfAccountAliases>")) {
+ state = 0;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // reading Alias
+ case 2:
+ if (line.startsWith( "<account>") ) {
+ alias.account( getVal( line) );
+ }
+ else if (line.startsWith( "<alias>")) {
+ alias.alias( getVal( line) );
+ }
+ else if (line.equals( "</AccountAlias>")) {
+ list.add( alias);
+ state = 1;
+ }
+ else {
+ err( line);
+ }
+ break;
+
+ // should not happen
+ default:
+ break;
+ }
+ }
+
+ return list;
+ }
+
+ private static String getVal(String line) {
+ int i1 = line.indexOf( '>');
+ int i2 = line.indexOf( '<', 1);
+ return line.substring( i1 + 1, i2);
+ }
+
+ private static void err(String line) {
+ System.out.println( "error " + line);
+ }
+
+
+ public static void main(String[] args) {
+ String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListOfAccountAliases>\n <AccountAlias>\n <account>DF109948</account>\n <alias>DF109948</alias>\n </AccountAlias>\n <AccountAlias>\n <account>DU109949</account>\n <alias>DU109949</alias>\n </AccountAlias>\n <AccountAlias>\n <account>DU109950</account>\n <alias>DU109950</alias>\n </AccountAlias>\n <AccountAlias>\n <account>DU110156</account>\n <alias>DU110156</alias>\n </AccountAlias>\n <AccountAlias>\n <account>DU110157</account>\n <alias>DU110157</alias>\n </AccountAlias>\n <AccountAlias>\n <account>DU110158</account>\n <alias>DU110158</alias>\n </AccountAlias>\n</ListOfAccountAliases>\n\n";
+ List<Alias> aliases = getAliases(str);
+
+ if (aliases != null) {
+ AdvisorUtil.err(aliases.toString());
+ }
+ }
+
+ public static String getGroupsXml(List<Group> groups) {
+ StringBuilder buf = new StringBuilder();
+ buf.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ buf.append( "<ListOfGroups>\n");
+ for( Group group : groups) {
+ buf.append( "<Group>\n");
+ buf.append( String.format( "<name>%s</name>%n", group.name() ) );
+ buf.append( String.format( "<defaultMethod>%s</defaultMethod>%n", group.defaultMethod() ) );
+ buf.append( "<ListOfAccts varName=\"list\"\n>");
+ for( String acct : group.accounts() ) {
+ buf.append( String.format( "<String>%s</String>%n", acct) );
+ }
+ buf.append( "</ListOfAccts>\n");
+ buf.append( "</Group>\n");
+ }
+ buf.append( "</ListOfGroups>\n");
+ return buf.toString();
+ }
+
+ public static String getProfilesXml(List<Profile> profiles) {
+ StringBuilder buf = new StringBuilder();
+ buf.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ buf.append( "<ListOfProfiles>\n");
+ for( Profile profile : profiles) {
+ buf.append( "<Profile>\n");
+ buf.append( String.format( "<name>%s</name>%n", profile.name() ) );
+ buf.append( String.format( "<type>%s</type>%n", profile.type().ordinal() ) );
+ buf.append( "<ListOfAllocations varName=\"listOfAllocations\">\n");
+ for( Allocation alloc : profile.allocations() ) {
+ buf.append( "<Allocation>\n");
+ buf.append( String.format( "<acct>%s</acct>%n", alloc.account() ) );
+ buf.append( String.format( "<amount>%s</amount>%n", alloc.amount() ) );
+ buf.append( "</Allocation>\n");
+ }
+ buf.append( "</ListOfAllocations>\n");
+ buf.append( "</Profile>\n");
+ }
+ buf.append( "</ListOfProfiles>\n");
+ return buf.toString();
+ }
+}
diff --git a/api/com/ib/controller/Alias.java b/api/com/ib/controller/Alias.java
new file mode 100755
index 0000000..2715e2f
--- /dev/null
+++ b/api/com/ib/controller/Alias.java
@@ -0,0 +1,19 @@
+/* Copyright (C) 2018 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 Alias {
+ private String m_account;
+ private String m_alias;
+
+ public String alias() { return m_alias; }
+ public String account() { return m_account; }
+
+ public void alias( String v) { m_alias = v; }
+ public void account( String v) { m_account = v; }
+
+ @Override public String toString() {
+ return m_account + " / " + m_alias;
+ }
+}
diff --git a/api/com/ib/controller/ApiConnection.java b/api/com/ib/controller/ApiConnection.java
new file mode 100755
index 0000000..171d501
--- /dev/null
+++ b/api/com/ib/controller/ApiConnection.java
@@ -0,0 +1,81 @@
+/* Copyright (C) 2018 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.nio.charset.StandardCharsets;
+
+import com.ib.client.Contract;
+import com.ib.client.EClientErrors;
+import com.ib.client.EClientSocket;
+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.
+
+public class ApiConnection extends EClientSocket {
+ public interface ILogger {
+ void log(String valueOf);
+ }
+
+ public static final char EOL = 0;
+ public static final char LOG_EOL = '_';
+
+ private final ILogger m_inLogger;
+ private final ILogger m_outLogger;
+ private static final EJavaSignal m_signal = new EJavaSignal();
+
+ public ApiConnection(EWrapper wrapper, ILogger inLogger, ILogger outLogger) {
+ super( wrapper, m_signal);
+ m_inLogger = inLogger;
+ m_outLogger = outLogger;
+ }
+
+ @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));
+ }
+
+ @Override
+ public int readInt() throws IOException {
+ int c = super.readInt();
+
+ m_inLogger.log( String.valueOf( (char)c) );
+
+ return c;
+ }
+
+ @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(Contract contract, Order order) {
+ // not connected?
+ if( !isConnected() ) {
+ notConnected();
+ return;
+ }
+
+ // ApiController requires TWS 932 or higher; this limitation could be removed if needed
+ if (serverVersion() < 66) {
+ error( EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, "ApiController requires TWS build 932 or higher to place orders.");
+ return;
+ }
+
+ placeOrder(order.orderId(), contract, order);
+ }
+}
diff --git a/api/com/ib/controller/ApiController.java b/api/com/ib/controller/ApiController.java
new file mode 100755
index 0000000..d2bdc5c
--- /dev/null
+++ b/api/com/ib/controller/ApiController.java
@@ -0,0 +1,1898 @@
+/* Copyright (C) 2018 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.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.*;
+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;
+
+public class ApiController implements EWrapper {
+ private ApiConnection m_client;
+ private final ILogger m_outLogger;
+ private final ILogger m_inLogger;
+ private int m_reqId; // used for all requests except orders; designed not to conflict with m_orderId
+ private int m_orderId;
+
+ private final IConnectionHandler m_connectionHandler;
+ private ITradeReportHandler m_tradeReportHandler;
+ private IAdvisorHandler m_advisorHandler;
+ private IScannerHandler m_scannerHandler;
+ private ITimeHandler m_timeHandler;
+ private IBulletinHandler m_bulletinHandler;
+ private final Map<Integer,IInternalHandler> m_contractDetailsMap = new HashMap<>();
+ private final Map<Integer,IOptHandler> m_optionCompMap = new HashMap<>();
+ private final Map<Integer,IEfpHandler> m_efpMap = new HashMap<>();
+ private final Map<Integer,ITopMktDataHandler> m_topMktDataMap = new HashMap<>();
+ private final Map<Integer,IDeepMktDataHandler> m_deepMktDataMap = new HashMap<>();
+ private final Map<Integer, IScannerHandler> m_scannerMap = new HashMap<>();
+ private final Map<Integer, IRealTimeBarHandler> m_realTimeBarMap = new HashMap<>();
+ private final Map<Integer, IHistoricalDataHandler> m_historicalDataMap = new HashMap<>();
+ private final Map<Integer, IHeadTimestampHandler> m_headTimestampMap = new HashMap<>();
+ private final Map<Integer, IHistogramDataHandler> m_histogramDataMap = new HashMap<>();
+ private final Map<Integer, IFundamentalsHandler> m_fundMap = new HashMap<>();
+ private final Map<Integer, IOrderHandler> m_orderHandlers = new HashMap<>();
+ private final Map<Integer,IAccountSummaryHandler> m_acctSummaryHandlers = new HashMap<>();
+ private final Map<Integer,IMarketValueSummaryHandler> m_mktValSummaryHandlers = new HashMap<>();
+ private final Set<IPositionHandler> m_positionHandlers = new ConcurrentHashSet<>();
+ private final Set<IAccountHandler> m_accountHandlers = new ConcurrentHashSet<>();
+ private final Set<ILiveOrderHandler> m_liveOrderHandlers = new ConcurrentHashSet<>();
+ private final Map<Integer, IPositionMultiHandler> m_positionMultiMap = new HashMap<>();
+ private final Map<Integer, IAccountUpdateMultiHandler> m_accountUpdateMultiMap = new HashMap<>();
+ private final Map<Integer, ISecDefOptParamsReqHandler> m_secDefOptParamsReqMap = new HashMap<>();
+ private final Map<Integer, ISoftDollarTiersReqHandler> m_softDollarTiersReqMap = new HashMap<>();
+ private final Set<IFamilyCodesHandler> m_familyCodesHandlers = new ConcurrentHashSet<>();
+ private final Map<Integer, ISymbolSamplesHandler> m_symbolSamplesHandlerMap = new HashMap<>();
+ private final Set<IMktDepthExchangesHandler> m_mktDepthExchangesHandlers = new ConcurrentHashSet<>();
+ private final Map<Integer, ITickNewsHandler> m_tickNewsHandlerMap = new HashMap<>();
+ private final Map<Integer, ISmartComponentsHandler> m_smartComponentsHandler = new HashMap<>();
+ private final Set<INewsProvidersHandler> m_newsProvidersHandlers = new ConcurrentHashSet<>();
+ private final Map<Integer, INewsArticleHandler> m_newsArticleHandlerMap = new HashMap<>();
+ private final Map<Integer, IHistoricalNewsHandler> m_historicalNewsHandlerMap = new HashMap<>();
+ private final Set<IMarketRuleHandler> m_marketRuleHandlers = new ConcurrentHashSet<>();
+ private final Map<Integer, IPnLHandler> m_pnlMap = new HashMap<>();
+ private final Map<Integer, IPnLSingleHandler> m_pnlSingleMap = new HashMap<>();
+ private final Map<Integer, IHistoricalTickHandler> m_historicalTicksMap = new HashMap<>();
+ private final Map<Integer, ITickByTickDataHandler> m_tickByTickDataMap = 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(List<String> list);
+ void error(Exception e);
+ void message(int id, int errorCode, String errorMsg);
+ void show(String string);
+ }
+
+ public ApiController( IConnectionHandler handler, ILogger inLogger, ILogger outLogger) {
+ m_connectionHandler = handler;
+ m_client = new ApiConnection( this, inLogger, outLogger);
+ m_inLogger = inLogger;
+ m_outLogger = outLogger;
+ }
+
+ 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) {
+ List<String> list = new ArrayList<>();
+ for( StringTokenizer st = new StringTokenizer( accounts, ","); st.hasMoreTokens(); ) {
+ list.add( st.nextToken() );
+ }
+ m_connectionHandler.accountList( list);
+ recEOM();
+ }
+
+ @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();
+ }
+ recEOM();
+ }
+
+ @Override public void error(Exception e) {
+ m_connectionHandler.error( e);
+ }
+
+ @Override public void error(int id, int errorCode, String errorMsg) {
+ IOrderHandler handler = m_orderHandlers.get( id);
+ if (handler != null) {
+ handler.handle( errorCode, errorMsg);
+ }
+
+ for (ILiveOrderHandler liveHandler : m_liveOrderHandlers) {
+ liveHandler.handle( id, errorCode, errorMsg);
+ }
+
+ // "no sec def found" response?
+ if (errorCode == 200) {
+ IInternalHandler hand = m_contractDetailsMap.remove( id);
+ if (hand != null) {
+ hand.contractDetailsEnd();
+ }
+ }
+
+ m_connectionHandler.message( id, errorCode, errorMsg);
+ recEOM();
+ }
+
+ @Override public void connectionClosed() {
+ m_connectionHandler.disconnected();
+ m_connected = false;
+ }
+
+
+ // ---------------------------------------- Account and portfolio updates ----------------------------------------
+ public interface IAccountHandler {
+ 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) {
+ 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 ("Currency".equals(tag)) { // ignore this, it is useless
+ return;
+ }
+
+ for( IAccountHandler handler : m_accountHandlers) {
+ handler.accountValue( account, tag, value, currency);
+ }
+ recEOM();
+ }
+
+ @Override public void updateAccountTime(String timeStamp) {
+ for( IAccountHandler handler : m_accountHandlers) {
+ handler.accountTime( timeStamp);
+ }
+ recEOM();
+ }
+
+ @Override public void accountDownloadEnd(String account) {
+ for( IAccountHandler handler : m_accountHandlers) {
+ handler.accountDownloadEnd( account);
+ }
+ recEOM();
+ }
+
+ @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) {
+ handler.updatePortfolio( position);
+ }
+ recEOM();
+ }
+
+ // ---------------------------------------- Account Summary handling ----------------------------------------
+ public interface IAccountSummaryHandler {
+ void accountSummary( String account, AccountSummaryTag tag, String value, String currency);
+ void accountSummaryEnd();
+ }
+
+ public interface IMarketValueSummaryHandler {
+ void marketValueSummary( String account, MarketValueTag tag, String value, String currency);
+ void marketValueSummaryEnd();
+ }
+
+ /** @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) {
+ sb.append( ',');
+ }
+ sb.append( tag);
+ }
+
+ int reqId = m_reqId++;
+ m_acctSummaryHandlers.put( reqId, handler);
+ m_client.reqAccountSummary( reqId, group, sb.toString() );
+ 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);
+ sendEOM();
+ }
+ }
+
+ 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");
+ sendEOM();
+ }
+
+ public void cancelMarketValueSummary(IMarketValueSummaryHandler handler) {
+ if (!checkConnection())
+ return;
+
+ Integer reqId = getAndRemoveKey( m_mktValSummaryHandlers, handler);
+ if (reqId != null) {
+ m_client.cancelAccountSummary( reqId);
+ sendEOM();
+ }
+ }
+
+ @Override public void accountSummary( int reqId, String account, String tag, String value, String currency) {
+ if ("Currency".equals(tag)) { // ignore this, it is useless
+ return;
+ }
+
+ IAccountSummaryHandler handler = m_acctSummaryHandlers.get( reqId);
+ if (handler != null) {
+ handler.accountSummary(account, AccountSummaryTag.valueOf( tag), value, currency);
+ }
+
+ IMarketValueSummaryHandler handler2 = m_mktValSummaryHandlers.get( reqId);
+ if (handler2 != null) {
+ handler2.marketValueSummary(account, MarketValueTag.valueOf( tag), value, currency);
+ }
+
+ recEOM();
+ }
+
+ @Override public void accountSummaryEnd( int reqId) {
+ IAccountSummaryHandler handler = m_acctSummaryHandlers.get( reqId);
+ if (handler != null) {
+ handler.accountSummaryEnd();
+ }
+
+ IMarketValueSummaryHandler handler2 = m_mktValSummaryHandlers.get( reqId);
+ if (handler2 != null) {
+ handler2.marketValueSummaryEnd();
+ }
+
+ recEOM();
+ }
+
+ // ---------------------------------------- Position handling ----------------------------------------
+ public interface IPositionHandler {
+ 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) {
+ if (!checkConnection())
+ return;
+
+ m_positionHandlers.remove( handler);
+ m_client.cancelPositions();
+ sendEOM();
+ }
+
+ @Override public void position(String account, Contract contract, double pos, double avgCost) {
+ for (IPositionHandler handler : m_positionHandlers) {
+ handler.position( account, contract, pos, avgCost);
+ }
+ recEOM();
+ }
+
+ @Override public void positionEnd() {
+ for (IPositionHandler handler : m_positionHandlers) {
+ handler.positionEnd();
+ }
+ recEOM();
+ }
+
+ // ---------------------------------------- Contract Details ----------------------------------------
+ public interface IContractDetailsHandler {
+ void contractDetails(List<ContractDetails> list);
+ }
+
+ public void reqContractDetails( Contract contract, final IContractDetailsHandler processor) {
+ if (!checkConnection())
+ return;
+
+ final List<ContractDetails> list = new ArrayList<>();
+ internalReqContractDetails( contract, new IInternalHandler() {
+ @Override public void contractDetails(ContractDetails data) {
+ list.add( data);
+ }
+ @Override public void contractDetailsEnd() {
+ processor.contractDetails( list);
+ }
+ });
+ sendEOM();
+ }
+
+ private interface IInternalHandler {
+ void contractDetails(ContractDetails data);
+ void contractDetailsEnd();
+ }
+
+ private void internalReqContractDetails( Contract contract, final IInternalHandler processor) {
+ int reqId = m_reqId++;
+ m_contractDetailsMap.put( reqId, processor);
+ 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, int permId,
+ int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) {
+ // 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(contractDetails);
+ }
+ else {
+ show( "Error: no contract details handler for reqId " + reqId);
+ }
+ recEOM();
+ }
+
+ @Override public void bondContractDetails(int reqId, ContractDetails contractDetails) {
+ IInternalHandler handler = m_contractDetailsMap.get( reqId);
+ if (handler != null) {
+ handler.contractDetails(contractDetails);
+ }
+ else {
+ show( "Error: no bond contract details handler for reqId " + reqId);
+ }
+ recEOM();
+ }
+
+ @Override public void contractDetailsEnd(int reqId) {
+ IInternalHandler handler = m_contractDetailsMap.remove( reqId);
+ if (handler != null) {
+ handler.contractDetailsEnd();
+ }
+ else {
+ show( "Error: no contract details handler for reqId " + reqId);
+ }
+ recEOM();
+ }
+
+ // ---------------------------------------- Top Market Data handling ----------------------------------------
+ public interface ITopMktDataHandler {
+ void tickPrice(TickType tickType, double price, TickAttr attribs);
+ void tickSize(TickType tickType, int size);
+ void tickString(TickType tickType, String value);
+ void tickSnapshotEnd();
+ 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 futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate);
+ }
+
+ public interface IOptHandler extends ITopMktDataHandler {
+ 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(TickType tickType, double price, TickAttr attribs) {
+ }
+ @Override public void tickSize(TickType tickType, int size) {
+ }
+ @Override public void tickString(TickType tickType, String value) {
+ }
+ @Override public void tickSnapshotEnd() {
+ }
+ @Override public void marketDataType(int marketDataType) {
+ }
+ @Override public void tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions) {
+ }
+ }
+
+ 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, genericTickList, snapshot, regulatorySnapshot, Collections.emptyList() );
+ sendEOM();
+ }
+
+ 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, genericTickList, snapshot, regulatorySnapshot, Collections.emptyList() );
+ sendEOM();
+ }
+
+ 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, genericTickList, snapshot, regulatorySnapshot, Collections.emptyList() );
+ sendEOM();
+ }
+
+ public void cancelTopMktData( ITopMktDataHandler handler) {
+ if (!checkConnection())
+ return;
+
+ Integer reqId = getAndRemoveKey( m_topMktDataMap, handler);
+ if (reqId != null) {
+ m_client.cancelMktData( reqId);
+ }
+ else {
+ show( "Error: could not cancel top market data");
+ }
+ sendEOM();
+ }
+
+ public void cancelOptionMktData( IOptHandler handler) {
+ cancelTopMktData( handler);
+ getAndRemoveKey( m_optionCompMap, handler);
+ }
+
+ public void cancelEfpMktData( IEfpHandler handler) {
+ cancelTopMktData( handler);
+ getAndRemoveKey( m_efpMap, handler);
+ }
+
+ 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, TickAttr attribs) {
+ ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.tickPrice( TickType.get( tickType), price, attribs);
+ }
+ recEOM();
+ }
+
+ @Override public void tickGeneric(int reqId, int tickType, double value) {
+ ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.tickPrice( TickType.get( tickType), value, new TickAttr());
+ }
+ recEOM();
+ }
+
+ @Override public void tickSize(int reqId, int tickType, int size) {
+ ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.tickSize( TickType.get( tickType), size);
+ }
+ recEOM();
+ }
+
+ @Override public void tickString(int reqId, int tickType, String value) {
+ ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.tickString( TickType.get( tickType), value);
+ }
+ recEOM();
+ }
+
+ @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, futureLastTradeDate, dividendImpact, dividendsToLastTradeDate);
+ }
+ recEOM();
+ }
+
+ @Override public void tickSnapshotEnd(int reqId) {
+ ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.tickSnapshotEnd();
+ }
+ recEOM();
+ }
+
+ @Override public void marketDataType(int reqId, int marketDataType) {
+ ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.marketDataType( marketDataType );
+ }
+ recEOM();
+ }
+
+
+ // ---------------------------------------- Deep Market Data handling ----------------------------------------
+ public interface IDeepMktDataHandler {
+ void updateMktDepth(int position, String marketMaker, DeepType operation, DeepSide side, double price, int size);
+ }
+
+ public void reqDeepMktData( Contract contract, int numRows, IDeepMktDataHandler handler) {
+ if (!checkConnection())
+ return;
+
+ int reqId = m_reqId++;
+ m_deepMktDataMap.put( reqId, handler);
+ List<TagValue> 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);
+ sendEOM();
+ }
+ }
+
+ @Override public void updateMktDepth(int reqId, int position, int operation, int side, double price, int size) {
+ IDeepMktDataHandler handler = m_deepMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.updateMktDepth( position, null, DeepType.get( operation), DeepSide.get( side), price, size);
+ }
+ recEOM();
+ }
+
+ @Override public void updateMktDepthL2(int reqId, int position, String marketMaker, int operation, int side, double price, int size) {
+ IDeepMktDataHandler handler = m_deepMktDataMap.get( reqId);
+ if (handler != null) {
+ handler.updateMktDepth( position, marketMaker, DeepType.get( operation), DeepSide.get( side), price, size);
+ }
+ recEOM();
+ }
+
+ // ---------------------------------------- Option computations ----------------------------------------
+ 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, optPrice, underPrice, null);
+ sendEOM();
+ }
+
+ 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, vol, underPrice, null);
+ sendEOM();
+ }
+
+ void cancelOptionComp( IOptHandler handler) {
+ if (!checkConnection())
+ return;
+
+ Integer reqId = getAndRemoveKey( m_optionCompMap, handler);
+ if (reqId != null) {
+ m_client.cancelCalculateOptionPrice( reqId);
+ sendEOM();
+ }
+ }
+
+ @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( 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) );
+ }
+ recEOM();
+ }
+
+
+ // ---------------------------------------- Trade reports ----------------------------------------
+ public interface ITradeReportHandler {
+ 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();
+ }
+
+ @Override public void execDetails(int reqId, Contract contract, Execution execution) {
+ if (m_tradeReportHandler != null) {
+ int i = execution.execId().lastIndexOf( '.');
+ String tradeKey = execution.execId().substring( 0, i);
+ m_tradeReportHandler.tradeReport( tradeKey, contract, execution);
+ }
+ recEOM();
+ }
+
+ @Override public void execDetailsEnd(int reqId) {
+ if (m_tradeReportHandler != null) {
+ m_tradeReportHandler.tradeReportEnd();
+ }
+ recEOM();
+ }
+
+ @Override public void commissionReport(CommissionReport commissionReport) {
+ if (m_tradeReportHandler != null) {
+ int i = commissionReport.m_execId.lastIndexOf( '.');
+ String tradeKey = commissionReport.m_execId.substring( 0, i);
+ m_tradeReportHandler.commissionReport( tradeKey, commissionReport);
+ }
+ recEOM();
+ }
+
+ // ---------------------------------------- Advisor info ----------------------------------------
+ public interface IAdvisorHandler {
+ void groups(List<Group> groups);
+ void profiles(List<Profile> profiles);
+ void aliases(List<Alias> aliases);
+ }
+
+ public void reqAdvisorData( FADataType type, IAdvisorHandler handler) {
+ if (!checkConnection())
+ return;
+
+ m_advisorHandler = handler;
+ m_client.requestFA( type.ordinal() );
+ sendEOM();
+ }
+
+ public void updateGroups( List<Group> groups) {
+ if (!checkConnection())
+ return;
+
+ m_client.replaceFA( FADataType.GROUPS.ordinal(), AdvisorUtil.getGroupsXml( groups) );
+ sendEOM();
+ }
+
+ public void updateProfiles(List<Profile> profiles) {
+ if (!checkConnection())
+ return;
+
+ m_client.replaceFA( FADataType.PROFILES.ordinal(), AdvisorUtil.getProfilesXml( profiles) );
+ sendEOM();
+ }
+
+ @Override public final void receiveFA(int faDataType, String xml) {
+ if (m_advisorHandler == null) {
+ return;
+ }
+
+ FADataType type = FADataType.get( faDataType);
+
+ switch( type) {
+ case GROUPS:
+ List<Group> groups = AdvisorUtil.getGroups( xml);
+ m_advisorHandler.groups(groups);
+ break;
+
+ case PROFILES:
+ List<Profile> profiles = AdvisorUtil.getProfiles( xml);
+ m_advisorHandler.profiles(profiles);
+ break;
+
+ case ALIASES:
+ List<Alias> 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(OrderState orderState);
+ void orderStatus(OrderStatus status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice);
+ void handle(int errorCode, String errorMsg);
+ }
+
+ 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++);
+ if (handler != null) {
+ m_orderHandlers.put( order.orderId(), handler);
+ }
+ }
+
+ m_client.placeOrder( contract, order);
+ sendEOM();
+ }
+
+ 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, 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();
+ }
+
+ public void removeOrderHandler( IOrderHandler handler) {
+ getAndRemoveKey(m_orderHandlers, handler);
+ }
+
+
+ // ---------------------------------------- Live order handling ----------------------------------------
+ /** This interface is for downloading and receiving events for all live orders.
+ * Compare to IOrderHandler. */
+ public interface ILiveOrderHandler {
+ void openOrder(Contract contract, Order order, OrderState orderState);
+ void openOrderEnd();
+ void orderStatus(int orderId, OrderStatus status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice);
+ 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();
+ }
+
+ public void removeLiveOrderHandler(ILiveOrderHandler handler) {
+ m_liveOrderHandlers.remove( handler);
+ }
+
+ @Override public void openOrder(int orderId, Contract contract, Order order, OrderState orderState) {
+ IOrderHandler handler = m_orderHandlers.get( orderId);
+ if (handler != null) {
+ handler.orderState(orderState);
+ }
+
+ if (!order.whatIf() ) {
+ for (ILiveOrderHandler liveHandler : m_liveOrderHandlers) {
+ liveHandler.openOrder( contract, order, orderState );
+ }
+ }
+ recEOM();
+ }
+
+ @Override public void openOrderEnd() {
+ for (ILiveOrderHandler handler : m_liveOrderHandlers) {
+ handler.openOrderEnd();
+ }
+ recEOM();
+ }
+
+ @Override public void orderStatus(int orderId, String status, double filled, double remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld, double mktCapPrice) {
+ IOrderHandler handler = m_orderHandlers.get( orderId);
+ if (handler != null) {
+ handler.orderStatus( OrderStatus.valueOf( status), filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice);
+ }
+
+ for (ILiveOrderHandler liveOrderHandler : m_liveOrderHandlers) {
+ liveOrderHandler.orderStatus(orderId, OrderStatus.valueOf( status), filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice);
+ }
+ recEOM();
+ }
+
+
+ // ---------------------------------------- Market Scanners ----------------------------------------
+ public interface IScannerHandler {
+ void scannerParameters(String xml);
+ 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);
+ List<TagValue> 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);
+ sendEOM();
+ }
+ }
+
+ @Override public void scannerParameters(String xml) {
+ m_scannerHandler.scannerParameters( xml);
+ recEOM();
+ }
+
+ @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, contractDetails, legsStr);
+ }
+ recEOM();
+ }
+
+ @Override public void scannerDataEnd(int reqId) {
+ IScannerHandler handler = m_scannerMap.get( reqId);
+ if (handler != null) {
+ handler.scannerDataEnd();
+ }
+ recEOM();
+ }
+
+
+ // ----------------------------------------- Historical data handling ----------------------------------------
+ public interface IHistoricalDataHandler {
+ void historicalData(Bar bar);
+ void historicalDataEnd();
+ }
+
+ /** @param endDateTime format is YYYYMMDD HH:MM:SS [TMZ]
+ * @param duration is number of durationUnits */
+ 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, endDateTime, durationStr, barSize.toString(), whatToShow.toString(), rthOnly ? 1 : 0, 2, keepUpToDate, Collections.emptyList());
+ sendEOM();
+ }
+
+ public void cancelHistoricalData( IHistoricalDataHandler handler) {
+ if (!checkConnection())
+ return;
+
+ Integer reqId = getAndRemoveKey( m_historicalDataMap, handler);
+ if (reqId != null) {
+ m_client.cancelHistoricalData( reqId);
+ sendEOM();
+ }
+ }
+
+ @Override public void historicalData(int reqId, com.ib.client.Bar bar) {
+ IHistoricalDataHandler handler = m_historicalDataMap.get( reqId);
+ if (handler != null) {
+ if (bar.time().startsWith( "finished")) {
+ handler.historicalDataEnd();
+ }
+ else {
+ long longDate;
+ 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( bar.time());
+ }
+ Bar bar2 = new Bar( longDate, bar.high(), bar.low(), bar.open(), bar.close(), bar.wap(), bar.volume(), bar.count());
+ handler.historicalData(bar2);
+ }
+ }
+ recEOM();
+ }
+
+
+ //----------------------------------------- Real-time bars --------------------------------------
+ public interface IRealTimeBarHandler {
+ void realtimeBar(Bar bar); // time is in seconds since epoch
+ }
+
+ public void reqRealTimeBars(Contract contract, WhatToShow whatToShow, boolean rthOnly, IRealTimeBarHandler handler) {
+ if (!checkConnection())
+ return;
+
+ int reqId = m_reqId++;
+ m_realTimeBarMap.put( reqId, handler);
+ List<TagValue> 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);
+ sendEOM();
+ }
+ }
+
+ @Override public void realtimeBar(int reqId, long time, double open, double high, double low, double close, long volume, double wap, int count) {
+ IRealTimeBarHandler handler = m_realTimeBarMap.get( reqId);
+ if (handler != null) {
+ Bar bar = new Bar( time, high, low, open, close, wap, volume, count);
+ handler.realtimeBar( bar);
+ }
+ recEOM();
+ }
+
+ // ----------------------------------------- Fundamentals handling ----------------------------------------
+ public interface IFundamentalsHandler {
+ void fundamentals( String str);
+ }
+
+ 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, reportType.getApiString(), null);
+ sendEOM();
+ }
+
+ @Override public void fundamentalData(int reqId, String data) {
+ IFundamentalsHandler handler = m_fundMap.get( reqId);
+ if (handler != null) {
+ handler.fundamentals( data);
+ }
+ 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();
+ }
+
+ @Override public void updateNewsBulletin(int msgId, int msgType, String message, String origExchange) {
+ m_bulletinHandler.bulletin( msgId, NewsType.get( msgType), message, origExchange);
+ 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, DeltaNeutralContract deltaNeutralContract) {
+ show( "RECEIVED DN VALIDATION");
+ recEOM();
+ }
+
+ protected void sendEOM() {
+ m_outLogger.log( "\n");
+ }
+
+ private void recEOM() {
+ m_inLogger.log( "\n");
+ }
+
+ public void show(String string) {
+ m_connectionHandler.show( string);
+ }
+
+ private static <K,V> K getAndRemoveKey( Map<K,V> map, V value) {
+ for (Entry<K,V> entry : map.entrySet() ) {
+ if (entry.getValue() == value) {
+ map.remove( entry.getKey() );
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+ /** Obsolete, never called. */
+ @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<String> expirations, Set<Double> strikes);
+ void securityDefinitionOptionalParameterEnd(int reqId);
+ }
+
+ @Override
+ public void securityDefinitionOptionalParameter(int reqId, String exchange, int underlyingConId, String tradingClass,
+ String multiplier, Set<String> expirations, Set<Double> 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<Integer, Entry<String, Character>> theMap);
+
+ }
+
+ @Override
+ public void smartComponents(int reqId, Map<Integer, Map.Entry<String, Character>> 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<HistogramEntry> 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<HistogramEntry> 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, double realizedPnL);
+
+ }
+
+ 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, double realizedPnL) {
+ IPnLHandler handler = m_pnlMap.get(reqId);
+
+ if (handler != null) {
+ handler.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL);
+ }
+
+ recEOM();
+ }
+
+ public interface IPnLSingleHandler {
+
+ void pnlSingle(int reqId, int pos, double dailyPnL, double unrealizedPnL, double realizedPnL, 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 realizedPnL, double value) {
+ IPnLSingleHandler handler = m_pnlSingleMap.get(reqId);
+
+ if (handler != null) {
+ handler.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value);
+ }
+
+ recEOM();
+ }
+
+ public interface IHistoricalTickHandler {
+
+ void historicalTick(int reqId, List<HistoricalTick> ticks);
+ void historicalTickBidAsk(int reqId, List<HistoricalTickBidAsk> ticks);
+ void historicalTickLast(int reqId, List<HistoricalTickLast> ticks);
+
+ }
+
+ public void reqHistoricalTicks(Contract contract, String startDateTime,
+ String endDateTime, int numberOfTicks, String whatToShow, int useRth, boolean ignoreSize, IHistoricalTickHandler handler) {
+ if (!checkConnection())
+ return;
+
+ int reqId = m_reqId++;
+
+ m_historicalTicksMap.put(reqId, handler);
+
+ m_client.reqHistoricalTicks(reqId, contract, startDateTime, endDateTime, numberOfTicks, whatToShow, useRth, ignoreSize, Collections.emptyList());
+ }
+
+ @Override
+ public void historicalTicks(int reqId, List<HistoricalTick> ticks, boolean last) {
+ IHistoricalTickHandler handler = m_historicalTicksMap.get(reqId);
+
+ if (handler != null) {
+ handler.historicalTick(reqId, ticks);
+ }
+
+ ITickByTickDataHandler handlerTickByTick = m_tickByTickDataMap.get(reqId);
+
+ if (handlerTickByTick != null) {
+ handlerTickByTick.tickByTickHistoricalTick(reqId, ticks);
+ }
+
+
+ recEOM();
+ }
+
+ @Override
+ public void historicalTicksBidAsk(int reqId, List<HistoricalTickBidAsk> ticks, boolean done) {
+ IHistoricalTickHandler handler = m_historicalTicksMap.get(reqId);
+
+ if (handler != null) {
+ handler.historicalTickBidAsk(reqId, ticks);
+ }
+
+ ITickByTickDataHandler handlerTickByTick = m_tickByTickDataMap.get(reqId);
+
+ if (handlerTickByTick != null) {
+ handlerTickByTick.tickByTickHistoricalTickBidAsk(reqId, ticks);
+ }
+
+ recEOM();
+ }
+
+ @Override
+ public void historicalTicksLast(int reqId, List<HistoricalTickLast> ticks, boolean done) {
+ IHistoricalTickHandler handler = m_historicalTicksMap.get(reqId);
+
+ if (handler != null) {
+ handler.historicalTickLast(reqId, ticks);
+ }
+
+ ITickByTickDataHandler handlerTickByTick = m_tickByTickDataMap.get(reqId);
+
+ if (handlerTickByTick != null) {
+ handlerTickByTick.tickByTickHistoricalTickAllLast(reqId, ticks);
+ }
+
+ recEOM();
+ }
+
+ public interface ITickByTickDataHandler {
+ void tickByTickAllLast(int reqId, int tickType, long time, double price, int size, TickAttr attribs, String exchange, String specialConditions);
+ void tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, int bidSize, int askSize, TickAttr attribs);
+ void tickByTickMidPoint(int reqId, long time, double midPoint);
+ void tickByTickHistoricalTickAllLast(int reqId, List<HistoricalTickLast> ticks);
+ void tickByTickHistoricalTickBidAsk(int reqId, List<HistoricalTickBidAsk> ticks);
+ void tickByTickHistoricalTick(int reqId, List<HistoricalTick> ticks);
+ }
+
+ public void reqTickByTickData(Contract contract, String tickType, int numberOfTicks, boolean ignoreSize,
+ ITickByTickDataHandler handler) {
+ if (!checkConnection())
+ return;
+
+ int reqId = m_reqId++;
+ m_tickByTickDataMap.put( reqId, handler);
+ m_client.reqTickByTickData( reqId, contract, tickType, numberOfTicks, ignoreSize);
+ sendEOM();
+ }
+
+ public void cancelTickByTickData( ITickByTickDataHandler handler) {
+ if (!checkConnection())
+ return;
+
+ Integer reqId = getAndRemoveKey( m_tickByTickDataMap, handler);
+ if (reqId != null) {
+ m_client.cancelTickByTickData( reqId);
+ sendEOM();
+ }
+ }
+
+ @Override
+ public void tickByTickAllLast(int reqId, int tickType, long time, double price, int size, TickAttr attribs,
+ String exchange, String specialConditions) {
+ ITickByTickDataHandler handler = m_tickByTickDataMap.get(reqId);
+
+ if (handler != null) {
+ handler.tickByTickAllLast(reqId, tickType, time, price, size, attribs, exchange, specialConditions);
+ }
+
+ recEOM();
+ }
+
+ @Override
+ public void tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, int bidSize, int askSize,
+ TickAttr attribs) {
+ ITickByTickDataHandler handler = m_tickByTickDataMap.get(reqId);
+
+ if (handler != null) {
+ handler.tickByTickBidAsk(reqId, time, bidPrice, askPrice, bidSize, askSize, attribs);
+ }
+
+ recEOM();
+ }
+
+ @Override
+ public void tickByTickMidPoint(int reqId, long time, double midPoint) {
+ ITickByTickDataHandler handler = m_tickByTickDataMap.get(reqId);
+
+ if (handler != null) {
+ handler.tickByTickMidPoint(reqId, time, midPoint);
+ }
+
+ recEOM();
+ }
+
+}
diff --git a/api/com/ib/controller/Bar.java b/api/com/ib/controller/Bar.java
new file mode 100755
index 0000000..86d4492
--- /dev/null
+++ b/api/com/ib/controller/Bar.java
@@ -0,0 +1,53 @@
+/* Copyright (C) 2018 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.text.SimpleDateFormat;
+import java.util.Date;
+
+public class Bar {
+ private static final ThreadLocal<SimpleDateFormat> FORMAT_CACHE = ThreadLocal.withInitial(() -> new SimpleDateFormat( "yyyyMMdd HH:mm:ss"));
+
+ private final long m_time;
+ private final double m_high;
+ private final double m_low;
+ private final double m_open;
+ private final double m_close;
+ private final double m_wap;
+ private final long m_volume;
+ private final int m_count;
+
+ public long time() { return m_time; }
+ public double high() { return m_high; }
+ public double low() { return m_low; }
+ public double open() { return m_open; }
+ public double close() { return m_close; }
+ public double wap() { return m_wap; }
+ public long volume() { return m_volume; }
+ public int count() { return m_count; }
+
+ public Bar( long time, double high, double low, double open, double close, double wap, long volume, int count) {
+ m_time = time;
+ m_high = high;
+ m_low = low;
+ m_open = open;
+ m_close = close;
+ m_wap = wap;
+ m_volume = volume;
+ m_count = count;
+ }
+
+ public String formattedTime() {
+ return Formats.fmtDate( m_time * 1000);
+ }
+
+ /** Format for query. */
+ public static String format( long ms) {
+ return FORMAT_CACHE.get().format( new Date( ms) );
+ }
+
+ @Override public String toString() {
+ return String.format( "%s %s %s %s %s", formattedTime(), m_open, m_high, m_low, m_close);
+ }
+}
diff --git a/api/com/ib/controller/ConcurrentHashSet.java b/api/com/ib/controller/ConcurrentHashSet.java
new file mode 100755
index 0000000..b9434f6
--- /dev/null
+++ b/api/com/ib/controller/ConcurrentHashSet.java
@@ -0,0 +1,52 @@
+/* Copyright (C) 2018 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<Key> extends AbstractSet<Key> {
+ private static final Object OBJECT = new Object();
+
+ private Map<Key, Object> 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<Key> 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/api/com/ib/controller/Formats.java b/api/com/ib/controller/Formats.java
new file mode 100755
index 0000000..dc6e434
--- /dev/null
+++ b/api/com/ib/controller/Formats.java
@@ -0,0 +1,58 @@
+/* Copyright (C) 2018 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.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 ThreadLocal<DateFormat> 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<DateFormat> DATE_TIME_FORMAT_CACHE = ThreadLocal.withInitial(() -> new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"));
+ private static final ThreadLocal<DateFormat> TIME_FORMAT_CACHE = ThreadLocal.withInitial(() -> new SimpleDateFormat( "HH:mm:ss"));
+
+ /** Format with two decimals. */
+ public static String fmt( double v) {
+ return v == Double.MAX_VALUE ? null : FMT2.format( v);
+ }
+
+ /** Format with two decimals; return null for zero. */
+ public static String fmtNz( double v) {
+ return v == Double.MAX_VALUE || v == 0 ? null : FMT2.format( v);
+ }
+
+ /** Format with no decimals. */
+ public static String fmt0( double v) {
+ return v == Double.MAX_VALUE ? null : FMT0.format( v);
+ }
+
+ /** Format as percent with one decimal. */
+ public static String fmtPct( double v) {
+ return v == Double.MAX_VALUE ? null : PCT.format( v);
+ }
+
+ /** Format date/time for display. */
+ public static String fmtDate( long 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_CACHE.get().format( new Date( ms) );
+ }
+}
diff --git a/api/com/ib/controller/Group.java b/api/com/ib/controller/Group.java
new file mode 100755
index 0000000..53ca74f
--- /dev/null
+++ b/api/com/ib/controller/Group.java
@@ -0,0 +1,34 @@
+/* Copyright (C) 2018 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 java.util.StringTokenizer;
+
+import com.ib.client.Types.Method;
+
+public class Group {
+ private String m_name;
+ private Method m_defaultMethod;
+ private List<String> m_accounts = new ArrayList<>();
+
+ public String name() { return m_name; }
+ public Method defaultMethod() { return m_defaultMethod; }
+ public List<String> accounts() { return m_accounts; }
+
+ public void name( String v) { m_name = v; }
+ public void defaultMethod( Method v) { m_defaultMethod = v; }
+ public void addAccount( String acct) { m_accounts.add( acct); }
+
+ /** @param val is a comma or space delimited string of accounts */
+ public void setAllAccounts(String val) {
+ m_accounts.clear();
+
+ StringTokenizer st = new StringTokenizer( val, " ,");
+ while( st.hasMoreTokens() ) {
+ m_accounts.add( st.nextToken() );
+ }
+ }
+}
diff --git a/api/com/ib/controller/Instrument.java b/api/com/ib/controller/Instrument.java
new file mode 100755
index 0000000..8c695e3
--- /dev/null
+++ b/api/com/ib/controller/Instrument.java
@@ -0,0 +1,35 @@
+/* Copyright (C) 2018 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 Instrument {
+ 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");
+
+ private final String code;
+
+ Instrument(final String code) {
+ this.code = code;
+ }
+
+ @Override
+ public String toString() {
+ return code;
+ }
+}
diff --git a/api/com/ib/controller/LocationCode.java b/api/com/ib/controller/LocationCode.java
new file mode 100755
index 0000000..732ab38
--- /dev/null
+++ b/api/com/ib/controller/LocationCode.java
@@ -0,0 +1,102 @@
+/* Copyright (C) 2018 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 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/api/com/ib/controller/MarketValueTag.java b/api/com/ib/controller/MarketValueTag.java
new file mode 100755
index 0000000..5c22a0f
--- /dev/null
+++ b/api/com/ib/controller/MarketValueTag.java
@@ -0,0 +1,47 @@
+/* Copyright (C) 2018 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 {
+ 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());
+ }
+
+ @Override
+ public String toString() {
+ return description;
+ }
+}
diff --git a/api/com/ib/controller/Position.java b/api/com/ib/controller/Position.java
new file mode 100755
index 0000000..5c8f976
--- /dev/null
+++ b/api/com/ib/controller/Position.java
@@ -0,0 +1,39 @@
+/* Copyright (C) 2018 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.Contract;
+
+
+public class Position {
+ private Contract m_contract;
+ private String m_account;
+ 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 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 double position() { return m_position;}
+ public String account() { return m_account;}
+
+ 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;
+ m_marketPrice = marketPrice;
+ m_marketValue =marketValue;
+ m_averageCost = averageCost;
+ m_unrealPnl = unrealPnl;
+ m_realPnl = realPnl;
+ }
+}
diff --git a/api/com/ib/controller/Profile.java b/api/com/ib/controller/Profile.java
new file mode 100755
index 0000000..d190b51
--- /dev/null
+++ b/api/com/ib/controller/Profile.java
@@ -0,0 +1,65 @@
+/* Copyright (C) 2018 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 java.util.StringTokenizer;
+
+import com.ib.client.Types;
+
+public class Profile {
+ static final String SEP = "/";
+
+ private String m_name;
+ private Type m_type;
+ private List<Allocation> m_allocations = new ArrayList<>();
+
+ public String name() { return m_name; }
+ public Type type() { return m_type; }
+ public List<Allocation> allocations() { return m_allocations; }
+
+ public void name( String v) { m_name = v; }
+ public void type( Type v) { m_type = v; }
+ public void add( Allocation v) { m_allocations.add( v); }
+
+ public void setAllocations(String val) {
+ m_allocations.clear();
+
+ StringTokenizer st = new StringTokenizer( val, ", ");
+ while( st.hasMoreTokens() ) {
+ String tok = st.nextToken();
+ StringTokenizer st2 = new StringTokenizer( tok, SEP);
+
+ Allocation alloc = new Allocation();
+ alloc.account( st2.nextToken() );
+ alloc.amount( st2.nextToken() );
+
+ m_allocations.add( alloc);
+ }
+ }
+
+ 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;
+ private String m_amount;
+
+ public String account() { return m_account; }
+ public String amount() { return m_amount; }
+
+ public void account( String v) { m_account = v; }
+ public void amount( String v) { m_amount = v; }
+
+ @Override public String toString() {
+ return m_account + SEP + m_amount;
+ }
+ }
+}
diff --git a/api/com/ib/controller/ScanCode.java b/api/com/ib/controller/ScanCode.java
new file mode 100755
index 0000000..8964253
--- /dev/null
+++ b/api/com/ib/controller/ScanCode.java
@@ -0,0 +1,111 @@
+/* Copyright (C) 2018 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 ScanCode {
+ TOP_PERC_GAIN,
+ TOP_PERC_LOSE,
+ MOST_ACTIVE,
+ ALL_SYMBOLS_ASC,
+ ALL_SYMBOLS_DESC,
+ BOND_CUSIP_AZ,
+ BOND_CUSIP_ZA,
+ FAR_MATURITY_DATE,
+ HALTED,
+ HIGH_BOND_ASK_CURRENT_YIELD_ALL,
+ HIGH_BOND_ASK_YIELD_ALL,
+ HIGH_BOND_DEBT_2_BOOK_RATIO,
+ HIGH_BOND_DEBT_2_EQUITY_RATIO,
+ HIGH_BOND_DEBT_2_TAN_BOOK_RATIO,
+ HIGH_BOND_EQUITY_2_BOOK_RATIO,
+ HIGH_BOND_EQUITY_2_TAN_BOOK_RATIO,
+ HIGH_BOND_NET_ASK_CURRENT_YIELD_ALL,
+ HIGH_BOND_NET_ASK_YIELD_ALL,
+ HIGH_BOND_NET_SPREAD_ALL,
+ HIGH_BOND_SPREAD_ALL,
+ HIGH_COUPON_RATE,
+ HIGH_DIVIDEND_YIELD,
+ HIGH_DIVIDEND_YIELD_IB,
+ HIGHEST_SLB_BID,
+ HIGH_GROWTH_RATE,
+ HIGH_MOODY_RATING_ALL,
+ HIGH_OPEN_GAP,
+ HIGH_OPT_IMP_VOLAT,
+ HIGH_OPT_IMP_VOLAT_OVER_HIST,
+ HIGH_OPT_OPEN_INTEREST_PUT_CALL_RATIO,
+ HIGH_OPT_VOLUME_PUT_CALL_RATIO,
+ HIGH_PE_RATIO,
+ HIGH_PRICE_2_BOOK_RATIO,
+ HIGH_PRICE_2_TAN_BOOK_RATIO,
+ HIGH_QUICK_RATIO,
+ HIGH_RETURN_ON_EQUITY,
+ HIGH_SYNTH_BID_REV_NAT_YIELD,
+ HIGH_VS_13W_HL,
+ HIGH_VS_26W_HL,
+ HIGH_VS_52W_HL,
+ HOT_BY_OPT_VOLUME,
+ HOT_BY_PRICE,
+ HOT_BY_PRICE_RANGE,
+ HOT_BY_VOLUME,
+ LIMIT_UP_DOWN,
+ LOW_BOND_BID_CURRENT_YIELD_ALL,
+ LOW_BOND_BID_YIELD_ALL,
+ LOW_BOND_DEBT_2_BOOK_RATIO,
+ LOW_BOND_DEBT_2_EQUITY_RATIO,
+ LOW_BOND_DEBT_2_TAN_BOOK_RATIO,
+ LOW_BOND_EQUITY_2_BOOK_RATIO,
+ LOW_BOND_EQUITY_2_TAN_BOOK_RATIO,
+ LOW_BOND_NET_BID_CURRENT_YIELD_ALL,
+ LOW_BOND_NET_BID_YIELD_ALL,
+ LOW_BOND_NET_SPREAD_ALL,
+ LOW_BOND_SPREAD_ALL,
+ LOW_COUPON_RATE,
+ LOWEST_SLB_ASK,
+ LOW_GROWTH_RATE,
+ LOW_MOODY_RATING_ALL,
+ LOW_OPEN_GAP,
+ LOW_OPT_IMP_VOLAT,
+ LOW_OPT_IMP_VOLAT_OVER_HIST,
+ LOW_OPT_OPEN_INTEREST_PUT_CALL_RATIO,
+ LOW_OPT_VOLUME_PUT_CALL_RATIO,
+ LOW_PE_RATIO,
+ LOW_PRICE_2_BOOK_RATIO,
+ LOW_PRICE_2_TAN_BOOK_RATIO,
+ LOW_QUICK_RATIO,
+ LOW_RETURN_ON_EQUITY,
+ LOW_SYNTH_ASK_REV_NAT_YIELD,
+ LOW_VS_13W_HL,
+ LOW_VS_26W_HL,
+ LOW_VS_52W_HL,
+ LOW_WAR_REL_IMP_VOLAT,
+ MARKET_CAP_USD_ASC,
+ MARKET_CAP_USD_DESC,
+ MOST_ACTIVE_AVG_USD,
+ MOST_ACTIVE_USD,
+ NEAR_MATURITY_DATE,
+ NOT_OPEN,
+ OPT_OPEN_INTEREST_MOST_ACTIVE,
+ OPT_VOLUME_MOST_ACTIVE,
+ PMONITOR_AVAIL_CONTRACTS,
+ PMONITOR_CTT,
+ PMONITOR_IBOND,
+ PMONITOR_RFQ,
+ TOP_OPEN_PERC_GAIN,
+ TOP_OPEN_PERC_LOSE,
+ TOP_OPT_IMP_VOLAT_GAIN,
+ TOP_OPT_IMP_VOLAT_LOSE,
+ TOP_PRICE_RANGE,
+ TOP_STOCK_BUY_IMBALANCE_ADV_RATIO,
+ TOP_STOCK_SELL_IMBALANCE_ADV_RATIO,
+ TOP_TRADE_COUNT,
+ TOP_TRADE_RATE,
+ TOP_VOLUME_RATE,
+ WSH_NEXT_ANALYST_MEETING,
+ WSH_NEXT_EARNINGS,
+ WSH_NEXT_EVENT,
+ WSH_NEXT_MAJOR_EVENT,
+ WSH_PREV_ANALYST_MEETING,
+ WSH_PREV_EARNINGS,
+ WSH_PREV_EVENT,
+}
diff --git a/api/com/ib/controller/TradeId.java b/api/com/ib/controller/TradeId.java
new file mode 100755
index 0000000..a2b667b
--- /dev/null
+++ b/api/com/ib/controller/TradeId.java
@@ -0,0 +1,18 @@
+/* Copyright (C) 2018 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 TradeId {
+ private String m_key;
+ private String m_full;
+
+ public String key() { return m_key; }
+ public String full() { return m_full; }
+
+ public TradeId( String id) {
+ m_full = id;
+ int i = id.lastIndexOf( '.');
+ m_key = id.substring( i + 1);
+ }
+}
diff --git a/api/pom.xml b/api/pom.xml
new file mode 100755
index 0000000..3ef0399
--- /dev/null
+++ b/api/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.interactivebrokers</groupId>
+ <artifactId>tws-api</artifactId>
+ <version>9.73.01-SNAPSHOT</version>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <java.source.version>1.8</java.source.version>
+ <java.target.version>1.8</java.target.version>
+ <maven.plugin.compiler.version>3.7.0</maven.plugin.compiler.version>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>${java.source.version}</source>
+ <target>${java.target.version}</target>
+ <compilerArgument>-Xlint:deprecation</compilerArgument>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>