📄 eclientsocket.java
字号:
/* * EClientSocket.java * */package com.ib.client;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;public class EClientSocket { // Client version history // // 6 = Added parentId to orderStatus // 7 = The new execDetails event returned for an order filled status and reqExecDetails // Also market depth is available. // 8 = Added lastFillPrice to orderStatus() event and permId to execution details // 9 = Added 'averageCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event // 10 = Added 'serverId' to the 'open order' & 'order status' events. // We send back all the API open orders upon connection. // Added new methods reqAllOpenOrders, reqAutoOpenOrders() // Added FA support - reqExecution has filter. // - reqAccountUpdates takes acct code. // 11 = Added permId to openOrder event. // 12 = requsting open order attributes ignoreRth, hidden, and discretionary // 13 = added goodAfterTime // 14 = always send size on bid/ask/last tick // 15 = send allocation description string on openOrder // 16 = can receive account name in account and portfolio updates, and fa params in openOrder // 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data // 18 = can receive good till date field in open order messages, and request intraday backfill // 19 = can receive rthOnly flag in ORDER_STATUS // 20 = expects TWS time string on connection after server version >= 20. // 21 = can receive bond contract details. // 22 = can receive price magnifier in version 2 contract details message // 23 = support for scanner // 24 = can receive volatility order parameters in open order messages // 25 = can receive HMDS query start and end times // 26 = can receive option vols in option market data messages // 27 = can receive delta neutral order type and delta neutral aux price in place order version 20: API 8.85 // 28 = can receive option model computation ticks: API 8.9 // 29 = can receive trail stop limit price in open order and can place them: API 8.91 // 30 = can receive extended bond contract def, new ticks, and trade count in bars // 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders // ; can receive RT bars // 32 = can receive TickType.LAST_TIMESTAMP // ; can receive "whyHeld" in order status messages // 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages // 34 = can receive whatIf orders / order state // 35 = can receive contId field for Contract objects // 36 = can receive outsideRth field for Order objects // 37 = can receive clearingAccount and clearingIntent for Order objects private static final int CLIENT_VERSION = 37; private static final int SERVER_VERSION = 38; private static final byte[] EOL = {0}; private static final String BAG_SEC_TYPE = "BAG"; // FA msg data types public static final int GROUPS = 1; public static final int PROFILES = 2; public static final int ALIASES = 3; public static String faMsgTypeName(int faDataType) { switch (faDataType) { case GROUPS: return "GROUPS"; case PROFILES: return "PROFILES"; case ALIASES: return "ALIASES"; } return null; } // outgoing msg id's private static final int REQ_MKT_DATA = 1; private static final int CANCEL_MKT_DATA = 2; private 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 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 AnyWrapper m_anyWrapper; // msg handler private Socket m_socket; // the socket private DataOutputStream m_dos; // the socket output stream private boolean m_connected;// true if we are connected private EReader m_reader; // thread which reads msgs from socket private int m_serverVersion =1; private String m_TwsTime; public int serverVersion() { return m_serverVersion; } public String TwsConnectionTime() { return m_TwsTime; } public AnyWrapper wrapper() { return m_anyWrapper; } public EReader reader() { return m_reader; } public EClientSocket( AnyWrapper anyWrapper) { m_anyWrapper = anyWrapper; } public boolean isConnected() { return m_connected; } public synchronized void eConnect( String host, int port, int clientId) { // already connected? host = checkConnected(host); if(host == null){ return; } try{ Socket socket = new Socket( host, port); eConnect(socket, clientId); } catch( Exception e) { connectionError(); } } protected void connectionError() { m_anyWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.CONNECT_FAIL.code(), EClientErrors.CONNECT_FAIL.msg()); m_reader = null; } protected String checkConnected(String host) { if( m_connected) { m_anyWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.ALREADY_CONNECTED.code(), EClientErrors.ALREADY_CONNECTED.msg()); return null; } if( isNull( host) ) { host = "127.0.0.1"; } return host; } public EReader createReader(EClientSocket socket, DataInputStream dis) { return new EReader(socket, dis); } public synchronized void eConnect(Socket socket, int clientId) throws IOException { m_socket = socket; // create io streams DataInputStream dis = new DataInputStream( m_socket.getInputStream() ); m_dos = new DataOutputStream( m_socket.getOutputStream() ); // set client version send( CLIENT_VERSION); // start reader thread m_reader = createReader(this, dis); // check server version m_serverVersion = m_reader.readInt(); System.out.println("Server Version:" + m_serverVersion); if ( m_serverVersion >= 20 ){ m_TwsTime = m_reader.readStr(); System.out.println("TWS Time at connection:" + m_TwsTime); } if( m_serverVersion < SERVER_VERSION) { m_anyWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), EClientErrors.UPDATE_TWS.msg()); return; } // Send the client id if ( m_serverVersion >= 3 ){ send( clientId); } m_reader.start(); // set connected flag m_connected = true; } public synchronized void eDisconnect() { // not connected? if( !m_connected) { return; } try { // stop reader thread if( m_reader != null) { m_reader.interrupt(); } // close socket if( m_socket != null) { m_socket.close(); } } catch( Exception e) { } m_connected = false; } public synchronized void cancelScannerSubscription( int tickerId) { // not connected? if( !m_connected) { error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); return; } if (m_serverVersion < 24) { error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, " It does not support API scanner subscription."); return; } final int VERSION = 1; // send cancel mkt data msg try { send( CANCEL_SCANNER_SUBSCRIPTION); send( VERSION); send( tickerId); } catch( Exception e) { error( tickerId, EClientErrors.FAIL_SEND_CANSCANNER, "" + e); close(); } } public synchronized void reqScannerParameters() { // not connected? if (!m_connected) { error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); return; } if (m_serverVersion < 24) { error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, " It does not support API scanner subscription."); return; } final int VERSION = 1; try { send(REQ_SCANNER_PARAMETERS); send(VERSION); } catch( Exception e) { error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQSCANNERPARAMETERS, "" + e); close(); } } public synchronized void reqScannerSubscription( int tickerId, ScannerSubscription subscription) { // not connected? if (!m_connected) { error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); return; } if (m_serverVersion < 24) { error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, " It does not support API scanner subscription."); return; } final int VERSION = 3; try { send(REQ_SCANNER_SUBSCRIPTION); send(VERSION); send(tickerId); sendMax(subscription.numberOfRows()); send(subscription.instrument()); send(subscription.locationCode()); send(subscription.scanCode()); sendMax(subscription.abovePrice()); sendMax(subscription.belowPrice()); sendMax(subscription.aboveVolume()); sendMax(subscription.marketCapAbove()); sendMax(subscription.marketCapBelow()); send(subscription.moodyRatingAbove()); send(subscription.moodyRatingBelow()); send(subscription.spRatingAbove()); send(subscription.spRatingBelow()); send(subscription.maturityDateAbove()); send(subscription.maturityDateBelow()); sendMax(subscription.couponRateAbove()); sendMax(subscription.couponRateBelow()); send(subscription.excludeConvertible()); if (m_serverVersion >= 25) { send(subscription.averageOptionVolumeAbove()); send(subscription.scannerSettingPairs()); } if (m_serverVersion >= 27) { send(subscription.stockTypeFilter()); } } catch( Exception e) { error( tickerId, EClientErrors.FAIL_SEND_REQSCANNER, "" + e); close(); } } public synchronized void reqMktData(int tickerId, Contract contract, String genericTickList, boolean snapshot) { if (!m_connected) { error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); return; } if (m_serverVersion < MIN_SERVER_VER_SNAPSHOT_MKT_DATA && snapshot) { error(tickerId, EClientErrors.UPDATE_TWS, " It does not support snapshot market data requests."); return; } final int VERSION = 7; try { // send req mkt data msg send(REQ_MKT_DATA); send(VERSION); send(tickerId); // send contract fields send(contract.m_symbol); send(contract.m_secType); send(contract.m_expiry); send(contract.m_strike); send(contract.m_right); if (m_serverVersion >= 15) { send(contract.m_multiplier); } send(contract.m_exchange); if (m_serverVersion >= 14) { send(contract.m_primaryExch); } send(contract.m_currency); if(m_serverVersion >= 2) { send( contract.m_localSymbol); } if(m_serverVersion >= 8 && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { if ( contract.m_comboLegs == null ) { send( 0); } else { send( contract.m_comboLegs.size()); ComboLeg comboLeg; for (int i=0; i < contract.m_comboLegs.size(); i ++) { comboLeg = (ComboLeg)contract.m_comboLegs.get(i); send( comboLeg.m_conId); send( comboLeg.m_ratio); send( comboLeg.m_action); send( comboLeg.m_exchange); } } } if (m_serverVersion >= 31) { /* * Note: Even though SHORTABLE tick type supported only * starting server version 33 it would be relatively * expensive to expose this restriction here. * * Therefore we are relying on TWS doing validation. */ send( genericTickList); } if (m_serverVersion >= MIN_SERVER_VER_SNAPSHOT_MKT_DATA) { send (snapshot); } } catch( Exception e) { error( tickerId, EClientErrors.FAIL_SEND_REQMKT, "" + e); close(); } } public synchronized void cancelHistoricalData( int tickerId ) { // not connected? if( !m_connected) { error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); return; } if (m_serverVersion < 24) { error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, " It does not support historical data query cancellation."); return; } final int VERSION = 1; // send cancel mkt data msg try { send( CANCEL_HISTORICAL_DATA); send( VERSION); send( tickerId); } catch( Exception e) { error( tickerId, EClientErrors.FAIL_SEND_CANHISTDATA, "" + e); close(); } } public void cancelRealTimeBars(int tickerId) { // not connected? if( !m_connected) { error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); return; } if (m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, " It does not support realtime bar data query cancellation."); return; } final int VERSION = 1; // send cancel mkt data msg try { send( CANCEL_REAL_TIME_BARS); send( VERSION); send( tickerId); } catch( Exception e) { error( tickerId, EClientErrors.FAIL_SEND_CANRTBARS, "" + e); close(); } } public synchronized void reqHistoricalData( int tickerId, Contract contract, String endDateTime, String durationStr, String barSizeSetting, String whatToShow,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -