├── README.md ├── makefile ├── shared ├── CommonDefs.h ├── Contract.h ├── EClient.h ├── EClientSocketBase.cpp ├── EClientSocketBase.h ├── EPosixClientSocket.cpp ├── EPosixClientSocket.h ├── EPosixClientSocketPlatform.h ├── EWrapper.h ├── Execution.h ├── IBString.h ├── Order.h ├── OrderState.h ├── ScannerSubscription.h ├── StdAfx.h ├── TwsSocketClientErrors.h └── shared_ptr.h ├── src ├── BreakoutTrader.cpp ├── BreakoutTrader.h └── main.cpp └── tests ├── UnitTest.cpp └── UnitTest.h /README.md: -------------------------------------------------------------------------------- 1 | algo-trader-tool-suite 2 | ====================== 3 | 4 | Proprietary trading solution for high-frequency trading (HFT) and statistical arbitrage algorithms 5 | forked from http://code.google.com/p/algo-trader-tool-suite/ 6 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | CXXFLAGS=-DIB_USE_STD_STRING -Wall -Wno-switch 3 | BASE_SRC_DIR=src 4 | RELEASE_DIR=bin 5 | SHARED_DIR=shared 6 | TEST_DIR=tests 7 | BOOST_DIR=../boost_1_49_0 8 | INCLUDES=-I${SHARED_DIR} -I${BASE_SRC_DIR} -I${BOOST_DIR} 9 | TARGET=BreakoutTrader 10 | 11 | 12 | $(TARGET): 13 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(RELEASE_DIR)/EClientSocketBase.o -c $(SHARED_DIR)/EClientSocketBase.cpp 14 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(RELEASE_DIR)/EPosixClientSocket.o -c $(SHARED_DIR)/EPosixClientSocket.cpp 15 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(RELEASE_DIR)/BreakoutTrader.o -c $(BASE_SRC_DIR)/BreakoutTrader.cpp 16 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(RELEASE_DIR)/main.o -c $(BASE_SRC_DIR)/main.cpp 17 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(RELEASE_DIR)/$(TARGET) $(RELEASE_DIR)/EClientSocketBase.o $(RELEASE_DIR)/EPosixClientSocket.o $(RELEASE_DIR)/BreakoutTrader.o $(RELEASE_DIR)/main.o 18 | 19 | clean: 20 | rm -f $(RELEASE_DIR)/$(TARGET) $(RELEASE_DIR)/*.o 21 | 22 | unittest: 23 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(TEST_DIR)/EClientSocketBase.o -c $(SHARED_DIR)/EClientSocketBase.cpp 24 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(TEST_DIR)/EPosixClientSocket.o -c $(SHARED_DIR)/EPosixClientSocket.cpp 25 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(TEST_DIR)/UnitTest.o -c $(TEST_DIR)/UnitTest.cpp 26 | $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(TEST_DIR)/UnitTest $(TEST_DIR)/EClientSocketBase.o $(TEST_DIR)/EPosixClientSocket.o $(TEST_DIR)/UnitTest.o -------------------------------------------------------------------------------- /shared/CommonDefs.h: -------------------------------------------------------------------------------- 1 | #ifndef common_defs_h_INCLUDED 2 | #define common_defs_h_INCLUDED 3 | 4 | typedef long TickerId; 5 | typedef long OrderId; 6 | 7 | enum faDataType { GROUPS=1, PROFILES, ALIASES } ; 8 | 9 | inline const char* faDataTypeStr ( faDataType pFaDataType ) 10 | { 11 | switch (pFaDataType) { 12 | case GROUPS: 13 | return "GROUPS" ; 14 | break ; 15 | case PROFILES: 16 | return "PROFILES" ; 17 | break ; 18 | case ALIASES: 19 | return "ALIASES" ; 20 | break ; 21 | } 22 | return 0 ; 23 | } 24 | 25 | enum MarketDataType { 26 | REALTIME = 1, 27 | FROZEN = 2 28 | }; 29 | 30 | #endif /* common_defs_h_INCLUDED */ 31 | -------------------------------------------------------------------------------- /shared/Contract.h: -------------------------------------------------------------------------------- 1 | #ifndef contract_def 2 | #define contract_def 3 | 4 | #include 5 | #include "IBString.h" 6 | 7 | /* 8 | SAME_POS = open/close leg value is same as combo 9 | OPEN_POS = open 10 | CLOSE_POS = close 11 | UNKNOWN_POS = unknown 12 | 13 | */ 14 | enum LegOpenClose { SAME_POS, OPEN_POS, CLOSE_POS, UNKNOWN_POS }; 15 | 16 | struct ComboLeg 17 | { 18 | 19 | ComboLeg() 20 | : 21 | conId(0), 22 | ratio(0), 23 | openClose(0), 24 | shortSaleSlot(0), 25 | exemptCode(-1) 26 | { 27 | } 28 | 29 | long conId; 30 | long ratio; 31 | IBString action; //BUY/SELL/SSHORT 32 | 33 | IBString exchange; 34 | long openClose; // LegOpenClose enum values 35 | 36 | // for stock legs when doing short sale 37 | long shortSaleSlot; // 1 = clearing broker, 2 = third party 38 | IBString designatedLocation; 39 | int exemptCode; 40 | 41 | bool operator==( const ComboLeg &other) const 42 | { 43 | return (conId == other.conId && 44 | ratio == other.ratio && 45 | openClose == other.openClose && 46 | shortSaleSlot == other.shortSaleSlot && 47 | (Compare(action, other.action) == 0) && 48 | (Compare(exchange, other.exchange) == 0) && 49 | (Compare(designatedLocation, other.designatedLocation) == 0) && 50 | exemptCode == other.exemptCode); 51 | } 52 | }; 53 | 54 | struct UnderComp 55 | { 56 | UnderComp() 57 | : conId(0) 58 | , delta(0) 59 | , price(0) 60 | {} 61 | 62 | long conId; 63 | double delta; 64 | double price; 65 | }; 66 | 67 | struct Contract 68 | { 69 | Contract() 70 | : conId(0) 71 | , strike(0) 72 | , includeExpired(false) 73 | , comboLegs(NULL) 74 | , underComp(NULL) 75 | { 76 | } 77 | 78 | long conId; 79 | IBString symbol; 80 | IBString secType; 81 | IBString expiry; 82 | double strike; 83 | IBString right; 84 | IBString multiplier; 85 | IBString exchange; 86 | IBString primaryExchange; // pick an actual (ie non-aggregate) exchange that the contract trades on. DO NOT SET TO SMART. 87 | IBString currency; 88 | IBString localSymbol; 89 | bool includeExpired; 90 | IBString secIdType; // CUSIP;SEDOL;ISIN;RIC 91 | IBString secId; 92 | 93 | // COMBOS 94 | IBString comboLegsDescrip; // received in open order 14 and up for all combos 95 | 96 | typedef std::vector ComboLegList; 97 | ComboLegList* comboLegs; 98 | 99 | // delta neutral 100 | UnderComp* underComp; 101 | 102 | public: 103 | 104 | // Helpers 105 | static void CloneComboLegs(ComboLegList& dst, const ComboLegList& src); 106 | static void CleanupComboLegs(ComboLegList&); 107 | }; 108 | 109 | struct ContractDetails 110 | { 111 | ContractDetails() 112 | : minTick(0) 113 | , priceMagnifier(0) 114 | , underConId(0) 115 | , callable(false) 116 | , putable(false) 117 | , coupon(0) 118 | , convertible(false) 119 | , nextOptionPartial(false) 120 | 121 | { 122 | } 123 | 124 | Contract summary; 125 | IBString marketName; 126 | IBString tradingClass; 127 | double minTick; 128 | IBString orderTypes; 129 | IBString validExchanges; 130 | long priceMagnifier; 131 | int underConId; 132 | IBString longName; 133 | IBString contractMonth; 134 | IBString industry; 135 | IBString category; 136 | IBString subcategory; 137 | IBString timeZoneId; 138 | IBString tradingHours; 139 | IBString liquidHours; 140 | 141 | // BOND values 142 | IBString cusip; 143 | IBString ratings; 144 | IBString descAppend; 145 | IBString bondType; 146 | IBString couponType; 147 | bool callable; 148 | bool putable; 149 | double coupon; 150 | bool convertible; 151 | IBString maturity; 152 | IBString issueDate; 153 | IBString nextOptionDate; 154 | IBString nextOptionType; 155 | bool nextOptionPartial; 156 | IBString notes; 157 | }; 158 | 159 | inline void 160 | Contract::CloneComboLegs(ComboLegList& dst, const ComboLegList& src) 161 | { 162 | CleanupComboLegs(dst); 163 | 164 | if (src.empty()) 165 | return; 166 | 167 | dst.reserve(src.size()); 168 | 169 | ComboLegList::const_iterator iter = src.begin(); 170 | const ComboLegList::const_iterator iterEnd = src.end(); 171 | 172 | for (; iter != iterEnd; ++iter) { 173 | const ComboLeg* leg = *iter; 174 | if (!leg) 175 | continue; 176 | dst.push_back(new ComboLeg(*leg)); 177 | } 178 | } 179 | 180 | inline void 181 | Contract::CleanupComboLegs(ComboLegList& legs) 182 | { 183 | if (legs.empty()) 184 | return; 185 | 186 | ComboLegList::iterator iter = legs.begin(); 187 | const ComboLegList::iterator iterEnd = legs.end(); 188 | 189 | for (; iter != iterEnd; ++iter) { 190 | delete *iter; 191 | } 192 | 193 | legs.clear(); 194 | } 195 | 196 | #endif 197 | -------------------------------------------------------------------------------- /shared/EClient.h: -------------------------------------------------------------------------------- 1 | #ifndef eclient_def 2 | #define eclient_def 3 | 4 | #include "CommonDefs.h" 5 | #include "IBString.h" 6 | 7 | struct Contract; 8 | struct Order; 9 | struct ExecutionFilter; 10 | struct ScannerSubscription; 11 | 12 | class EClient 13 | { 14 | public: 15 | virtual ~EClient() {} 16 | virtual bool eConnect( const char *host, unsigned int port, int clientId=0) = 0; 17 | virtual void eDisconnect() = 0; 18 | virtual int serverVersion() = 0; 19 | virtual IBString TwsConnectionTime() = 0; 20 | virtual void reqMktData( TickerId id, const Contract &contract, 21 | const IBString& genericTicks, bool snapshot) = 0; 22 | virtual void cancelMktData( TickerId id) = 0; 23 | virtual void placeOrder( OrderId id, const Contract &contract, const Order &order) = 0; 24 | virtual void cancelOrder( OrderId id) = 0; 25 | virtual void reqOpenOrders() = 0; 26 | virtual void reqAccountUpdates(bool subscribe, const IBString& acctCode) = 0; 27 | virtual void reqExecutions(int reqId, const ExecutionFilter& filter) = 0; 28 | virtual void reqIds( int numIds) = 0; 29 | virtual bool checkMessages() = 0; 30 | virtual void reqContractDetails( int reqId, const Contract &contract) = 0; 31 | virtual void reqMktDepth( TickerId id, const Contract &contract, int numRows) = 0; 32 | virtual void cancelMktDepth( TickerId id) = 0; 33 | virtual void reqNewsBulletins( bool allMsgs) = 0; 34 | virtual void cancelNewsBulletins() = 0; 35 | virtual void setServerLogLevel(int level) = 0; 36 | virtual void reqAutoOpenOrders(bool bAutoBind) = 0; 37 | virtual void reqAllOpenOrders() = 0; 38 | virtual void reqManagedAccts() = 0; 39 | virtual void requestFA(faDataType pFaDataType) = 0; 40 | virtual void replaceFA(faDataType pFaDataType, const IBString& cxml) = 0; 41 | virtual void reqHistoricalData( TickerId id, const Contract &contract, 42 | const IBString &endDateTime, const IBString &durationStr, const IBString &barSizeSetting, 43 | const IBString &whatToShow, int useRTH, int formatDate) = 0; 44 | virtual void exerciseOptions( TickerId id, const Contract &contract, 45 | int exerciseAction, int exerciseQuantity, const IBString &account, int override) = 0; 46 | virtual void cancelHistoricalData( TickerId tickerId ) = 0; 47 | virtual void reqRealTimeBars( TickerId id, const Contract &contract, int barSize, 48 | const IBString &whatToShow, bool useRTH) = 0; 49 | virtual void cancelRealTimeBars( TickerId tickerId) = 0; 50 | virtual void cancelScannerSubscription( int tickerId) = 0; 51 | virtual void reqScannerParameters() = 0; 52 | virtual void reqScannerSubscription( int tickerId, const ScannerSubscription &subscription) = 0; 53 | virtual void reqCurrentTime() = 0; 54 | virtual void reqFundamentalData( TickerId reqId, const Contract&, const IBString& reportType) = 0; 55 | virtual void cancelFundamentalData( TickerId reqId) = 0; 56 | virtual void calculateImpliedVolatility( TickerId reqId, const Contract &contract, double optionPrice, double underPrice) = 0; 57 | virtual void calculateOptionPrice( TickerId reqId, const Contract &contract, double volatility, double underPrice) = 0; 58 | virtual void cancelCalculateImpliedVolatility( TickerId reqId) = 0; 59 | virtual void cancelCalculateOptionPrice( TickerId reqId) = 0; 60 | virtual void reqGlobalCancel() = 0; 61 | virtual void reqMarketDataType( int marketDataType) = 0; 62 | private: 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /shared/EClientSocketBase.cpp: -------------------------------------------------------------------------------- 1 | #ifndef eclientsocketbaseimpl_h__INCLUDED 2 | #define eclientsocketbaseimpl_h__INCLUDED 3 | 4 | #include "StdAfx.h" 5 | #include "EClientSocketBase.h" 6 | 7 | #include "EWrapper.h" 8 | #include "TwsSocketClientErrors.h" 9 | #include "Contract.h" 10 | #include "Order.h" 11 | #include "OrderState.h" 12 | #include "Execution.h" 13 | #include "ScannerSubscription.h" 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | ///////////////////////////////////////////////////////////////////////////////// 25 | // SOCKET CLIENT VERSION CHANGE LOG : Incremented when the format of incomming 26 | // server responses change 27 | ///////////////////////////////////////////////////////////////////////////////// 28 | // constants 29 | // 6 = Added parentId to orderStatus 30 | // 7 = The new execDetails event returned for an order filled status and reqExecDetails 31 | // Also added market depth support. 32 | // 8 = Added 'lastFillPrice' to orderStatus and 'permId' to execDetails 33 | // 9 = Added 'avgCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event 34 | // 10 = Added 'serverId' to the 'open order' & 'order status' events. 35 | // We send back all the API open orders upon connection. 36 | // Added new methods reqAllOpenOrders, reqAutoOpenOrders() 37 | // Added FA support - reqExecution has filter. 38 | // - reqAccountUpdates takes acct code. 39 | // 11 = Added permId to openOrder event. 40 | // 12 = Added IgnoreRth, hidden, and discretionaryAmt 41 | // 13 = Added GoodAfterTime 42 | // 14 = always send size on bid/ask/last tick 43 | // 15 = send allocation string with open order 44 | // 16 = can receive account name in account and portfolio updates, and fa params in openOrder 45 | // 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data 46 | // 18 = can receive good till date field in open order messages, and send backfill requests 47 | // 19 = can receive new extended order attributes in OPEN_ORDER 48 | // 20 = expects TWS time string on connection after server version >= 20, and parentId in open order 49 | // 21 = can receive bond contract details. 50 | // 22 = can receive price magnifier in contract details 51 | // 23 = support for scanner 52 | // 24 = can receive volatility order parameters in open order messages 53 | // 25 = can receive HMDS query start and end times 54 | // 26 = can receive option vols in option market data messages 55 | // 27 = can receive delta neutral order type and delta neutral aux price 56 | // 28 = can receive option model computation ticks 57 | // 29 = can receive trail stop limit price in open order and can place them: API 8.91 58 | // 30 = can receive extended bond contract def, new ticks, and trade count in bars 59 | // 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders 60 | // ; can receive RT bars 61 | // 32 = can receive TickType.LAST_TIMESTAMP 62 | // 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages 63 | // 34 = can receive whatIf orders / order state 64 | // 35 = can receive contId field for Contract objects 65 | // 36 = can receive outsideRth field for Order objects 66 | // 37 = can receive clearingAccount and clearingIntent for Order objects 67 | // 38 = can receive multipier and primaryExchange in portfolio updates 68 | // ; can receive cumQty and avgPrice in execution 69 | // ; can receive fundamental data 70 | // ; can receive underComp for Contract objects 71 | // ; can receive reqId and end marker in contractDetails/bondContractDetails 72 | // ; can receive ScaleInitComponentSize and ScaleSubsComponentSize for Order objects 73 | // 39 = can receive underConId in contractDetails 74 | // 40 = can receive algoStrategy/algoParams in openOrder 75 | // 41 = can receive end marker for openOrder 76 | // ; can receive end marker for account download 77 | // ; can receive end marker for executions download 78 | // 42 = can receive deltaNeutralValidation 79 | // 43 = can receive longName(companyName) 80 | // ; can receive listingExchange 81 | // ; can receive RTVolume tick 82 | // 44 = can receive end market for ticker snapshot 83 | // 45 = can receive notHeld field in openOrder 84 | // 46 = can receive contractMonth, industry, category, subcategory fields in contractDetails 85 | // ; can receive timeZoneId, tradingHours, liquidHours fields in contractDetails 86 | // 47 = can receive gamma, vega, theta, undPrice fields in TICK_OPTION_COMPUTATION 87 | // 48 = can receive exemptCode in openOrder 88 | // 49 = can receive hedgeType and hedgeParam in openOrder 89 | // 50 = can receive optOutSmartRouting field in openOrder 90 | // 51 = can receive smartComboRoutingParams in openOrder 91 | // 52 = can receive deltaNeutralConId, deltaNeutralSettlingFirm, deltaNeutralClearingAccount and deltaNeutralClearingIntent in openOrder 92 | // 53 = can receive orderRef in execution 93 | const int CLIENT_VERSION = 53; 94 | const int SERVER_VERSION = 38; 95 | 96 | // outgoing msg id's 97 | const int REQ_MKT_DATA = 1; 98 | const int CANCEL_MKT_DATA = 2; 99 | const int PLACE_ORDER = 3; 100 | const int CANCEL_ORDER = 4; 101 | const int REQ_OPEN_ORDERS = 5; 102 | const int REQ_ACCT_DATA = 6; 103 | const int REQ_EXECUTIONS = 7; 104 | const int REQ_IDS = 8; 105 | const int REQ_CONTRACT_DATA = 9; 106 | const int REQ_MKT_DEPTH = 10; 107 | const int CANCEL_MKT_DEPTH = 11; 108 | const int REQ_NEWS_BULLETINS = 12; 109 | const int CANCEL_NEWS_BULLETINS = 13; 110 | const int SET_SERVER_LOGLEVEL = 14; 111 | const int REQ_AUTO_OPEN_ORDERS = 15; 112 | const int REQ_ALL_OPEN_ORDERS = 16; 113 | const int REQ_MANAGED_ACCTS = 17; 114 | const int REQ_FA = 18; 115 | const int REPLACE_FA = 19; 116 | const int REQ_HISTORICAL_DATA = 20; 117 | const int EXERCISE_OPTIONS = 21; 118 | const int REQ_SCANNER_SUBSCRIPTION = 22; 119 | const int CANCEL_SCANNER_SUBSCRIPTION = 23; 120 | const int REQ_SCANNER_PARAMETERS = 24; 121 | const int CANCEL_HISTORICAL_DATA = 25; 122 | const int REQ_CURRENT_TIME = 49; 123 | const int REQ_REAL_TIME_BARS = 50; 124 | const int CANCEL_REAL_TIME_BARS = 51; 125 | const int REQ_FUNDAMENTAL_DATA = 52; 126 | const int CANCEL_FUNDAMENTAL_DATA = 53; 127 | const int REQ_CALC_IMPLIED_VOLAT = 54; 128 | const int REQ_CALC_OPTION_PRICE = 55; 129 | const int CANCEL_CALC_IMPLIED_VOLAT = 56; 130 | const int CANCEL_CALC_OPTION_PRICE = 57; 131 | const int REQ_GLOBAL_CANCEL = 58; 132 | const int REQ_MARKET_DATA_TYPE = 59; 133 | 134 | //const int MIN_SERVER_VER_REAL_TIME_BARS = 34; 135 | //const int MIN_SERVER_VER_SCALE_ORDERS = 35; 136 | //const int MIN_SERVER_VER_SNAPSHOT_MKT_DATA = 35; 137 | //const int MIN_SERVER_VER_SSHORT_COMBO_LEGS = 35; 138 | //const int MIN_SERVER_VER_WHAT_IF_ORDERS = 36; 139 | //const int MIN_SERVER_VER_CONTRACT_CONID = 37; 140 | const int MIN_SERVER_VER_PTA_ORDERS = 39; 141 | const int MIN_SERVER_VER_FUNDAMENTAL_DATA = 40; 142 | const int MIN_SERVER_VER_UNDER_COMP = 40; 143 | const int MIN_SERVER_VER_CONTRACT_DATA_CHAIN = 40; 144 | const int MIN_SERVER_VER_SCALE_ORDERS2 = 40; 145 | const int MIN_SERVER_VER_ALGO_ORDERS = 41; 146 | const int MIN_SERVER_VER_EXECUTION_DATA_CHAIN = 42; 147 | const int MIN_SERVER_VER_NOT_HELD = 44; 148 | const int MIN_SERVER_VER_SEC_ID_TYPE = 45; 149 | const int MIN_SERVER_VER_PLACE_ORDER_CONID = 46; 150 | const int MIN_SERVER_VER_REQ_MKT_DATA_CONID = 47; 151 | const int MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT = 49; 152 | const int MIN_SERVER_VER_REQ_CALC_OPTION_PRICE = 50; 153 | const int MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT = 50; 154 | const int MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE = 50; 155 | const int MIN_SERVER_VER_SSHORTX_OLD = 51; 156 | const int MIN_SERVER_VER_SSHORTX = 52; 157 | const int MIN_SERVER_VER_REQ_GLOBAL_CANCEL = 53; 158 | const int MIN_SERVER_VER_HEDGE_ORDERS = 54; 159 | const int MIN_SERVER_VER_REQ_MARKET_DATA_TYPE = 55; 160 | const int MIN_SERVER_VER_OPT_OUT_SMART_ROUTING = 56; 161 | const int MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS = 57; 162 | const int MIN_SERVER_VER_DELTA_NEUTRAL_CONID = 58; 163 | 164 | // incoming msg id's 165 | const int TICK_PRICE = 1; 166 | const int TICK_SIZE = 2; 167 | const int ORDER_STATUS = 3; 168 | const int ERR_MSG = 4; 169 | const int OPEN_ORDER = 5; 170 | const int ACCT_VALUE = 6; 171 | const int PORTFOLIO_VALUE = 7; 172 | const int ACCT_UPDATE_TIME = 8; 173 | const int NEXT_VALID_ID = 9; 174 | const int CONTRACT_DATA = 10; 175 | const int EXECUTION_DATA = 11; 176 | const int MARKET_DEPTH = 12; 177 | const int MARKET_DEPTH_L2 = 13; 178 | const int NEWS_BULLETINS = 14; 179 | const int MANAGED_ACCTS = 15; 180 | const int RECEIVE_FA = 16; 181 | const int HISTORICAL_DATA = 17; 182 | const int BOND_CONTRACT_DATA = 18; 183 | const int SCANNER_PARAMETERS = 19; 184 | const int SCANNER_DATA = 20; 185 | const int TICK_OPTION_COMPUTATION = 21; 186 | const int TICK_GENERIC = 45; 187 | const int TICK_STRING = 46; 188 | const int TICK_EFP = 47; 189 | const int CURRENT_TIME = 49; 190 | const int REAL_TIME_BARS = 50; 191 | const int FUNDAMENTAL_DATA = 51; 192 | const int CONTRACT_DATA_END = 52; 193 | const int OPEN_ORDER_END = 53; 194 | const int ACCT_DOWNLOAD_END = 54; 195 | const int EXECUTION_DATA_END = 55; 196 | const int DELTA_NEUTRAL_VALIDATION = 56; 197 | const int TICK_SNAPSHOT_END = 57; 198 | const int MARKET_DATA_TYPE = 58; 199 | 200 | // TWS New Bulletins constants 201 | const int NEWS_MSG = 1; // standard IB news bulleting message 202 | const int EXCHANGE_AVAIL_MSG = 2; // control message specifing that an exchange is available for trading 203 | const int EXCHANGE_UNAVAIL_MSG = 3; // control message specifing that an exchange is unavailable for trading 204 | 205 | /////////////////////////////////////////////////////////// 206 | // helper macroses 207 | #define DECODE_FIELD(x) if (!DecodeField(x, ptr, endPtr)) return 0; 208 | #define DECODE_FIELD_MAX(x) if (!DecodeFieldMax(x, ptr, endPtr)) return 0; 209 | 210 | #define ENCODE_FIELD(x) EncodeField(msg, x); 211 | #define ENCODE_FIELD_MAX(x) EncodeFieldMax(msg, x); 212 | 213 | /////////////////////////////////////////////////////////// 214 | // helper structures 215 | namespace { 216 | 217 | struct BarData { 218 | IBString date; 219 | double open; 220 | double high; 221 | double low; 222 | double close; 223 | int volume; 224 | double average; 225 | IBString hasGaps; 226 | int barCount; 227 | }; 228 | 229 | struct ScanData { 230 | ContractDetails contract; 231 | int rank; 232 | IBString distance; 233 | IBString benchmark; 234 | IBString projection; 235 | IBString legsStr; 236 | }; 237 | 238 | } // end of anonymous namespace 239 | 240 | /////////////////////////////////////////////////////////// 241 | // encoders 242 | template 243 | void EClientSocketBase::EncodeField(std::ostream& os, T value) 244 | { 245 | os << value << '\0'; 246 | } 247 | 248 | template<> 249 | void EClientSocketBase::EncodeField(std::ostream& os, bool boolValue) 250 | { 251 | EncodeField(os, boolValue ? 1 : 0); 252 | } 253 | 254 | template<> 255 | void EClientSocketBase::EncodeField(std::ostream& os, double doubleValue) 256 | { 257 | char str[128]; 258 | 259 | snprintf(str, sizeof(str), "%.10g", doubleValue); 260 | 261 | EncodeField(os, str); 262 | } 263 | 264 | /////////////////////////////////////////////////////////// 265 | // "max" encoders 266 | void EClientSocketBase::EncodeFieldMax(std::ostream& os, int intValue) 267 | { 268 | if( intValue == INT_MAX) { 269 | EncodeField(os, ""); 270 | return; 271 | } 272 | EncodeField(os, intValue); 273 | } 274 | 275 | void EClientSocketBase::EncodeFieldMax(std::ostream& os, double doubleValue) 276 | { 277 | if( doubleValue == DBL_MAX) { 278 | EncodeField(os, ""); 279 | return; 280 | } 281 | EncodeField(os, doubleValue); 282 | } 283 | 284 | /////////////////////////////////////////////////////////// 285 | // decoders 286 | bool EClientSocketBase::CheckOffset(const char* ptr, const char* endPtr) 287 | { 288 | assert (ptr && ptr <= endPtr); 289 | return (ptr && ptr < endPtr); 290 | } 291 | 292 | const char* EClientSocketBase::FindFieldEnd(const char* ptr, const char* endPtr) 293 | { 294 | return (const char*)memchr(ptr, 0, endPtr - ptr); 295 | } 296 | 297 | bool EClientSocketBase::DecodeField(bool& boolValue, const char*& ptr, const char* endPtr) 298 | { 299 | int intValue; 300 | if( !DecodeField(intValue, ptr, endPtr)) 301 | return false; 302 | boolValue = (intValue > 0); 303 | return true; 304 | } 305 | 306 | bool EClientSocketBase::DecodeField(int& intValue, const char*& ptr, const char* endPtr) 307 | { 308 | if( !CheckOffset(ptr, endPtr)) 309 | return false; 310 | const char* fieldBeg = ptr; 311 | const char* fieldEnd = FindFieldEnd(fieldBeg, endPtr); 312 | if( !fieldEnd) 313 | return false; 314 | intValue = atoi(fieldBeg); 315 | ptr = ++fieldEnd; 316 | return true; 317 | } 318 | 319 | bool EClientSocketBase::DecodeField(long& longValue, const char*& ptr, const char* endPtr) 320 | { 321 | int intValue; 322 | if( !DecodeField(intValue, ptr, endPtr)) 323 | return false; 324 | longValue = intValue; 325 | return true; 326 | } 327 | 328 | bool EClientSocketBase::DecodeField(double& doubleValue, const char*& ptr, const char* endPtr) 329 | { 330 | if( !CheckOffset(ptr, endPtr)) 331 | return false; 332 | const char* fieldBeg = ptr; 333 | const char* fieldEnd = FindFieldEnd(fieldBeg, endPtr); 334 | if( !fieldEnd) 335 | return false; 336 | doubleValue = atof(fieldBeg); 337 | ptr = ++fieldEnd; 338 | return true; 339 | } 340 | 341 | bool EClientSocketBase::DecodeField(IBString& stringValue, 342 | const char*& ptr, const char* endPtr) 343 | { 344 | if( !CheckOffset(ptr, endPtr)) 345 | return false; 346 | const char* fieldBeg = ptr; 347 | const char* fieldEnd = FindFieldEnd(ptr, endPtr); 348 | if( !fieldEnd) 349 | return false; 350 | stringValue = fieldBeg; // better way? 351 | ptr = ++fieldEnd; 352 | return true; 353 | } 354 | 355 | bool EClientSocketBase::DecodeFieldMax(int& intValue, const char*& ptr, const char* endPtr) 356 | { 357 | IBString stringValue; 358 | if( !DecodeField(stringValue, ptr, endPtr)) 359 | return false; 360 | intValue = (IsEmpty(stringValue) ? UNSET_INTEGER : Atoi(stringValue)); 361 | return true; 362 | } 363 | 364 | bool EClientSocketBase::DecodeFieldMax(long& longValue, const char*& ptr, const char* endPtr) 365 | { 366 | int intValue; 367 | if( !DecodeFieldMax(intValue, ptr, endPtr)) 368 | return false; 369 | longValue = intValue; 370 | return true; 371 | } 372 | 373 | bool EClientSocketBase::DecodeFieldMax(double& doubleValue, const char*& ptr, const char* endPtr) 374 | { 375 | IBString stringValue; 376 | if( !DecodeField(stringValue, ptr, endPtr)) 377 | return false; 378 | doubleValue = (IsEmpty(stringValue) ? UNSET_DOUBLE : Atof(stringValue)); 379 | return true; 380 | } 381 | 382 | /////////////////////////////////////////////////////////// 383 | // static helpers 384 | 385 | static const size_t BufferSizeHighMark = 1 * 1024 * 1024; // 1Mb 386 | 387 | void EClientSocketBase::CleanupBuffer(BytesVec& buffer, int processed) 388 | { 389 | assert( buffer.empty() || processed <= (int)buffer.size()); 390 | 391 | if( buffer.empty()) 392 | return; 393 | 394 | if( processed <= 0) 395 | return; 396 | 397 | if( (size_t)processed == buffer.size()) { 398 | if( buffer.capacity() >= BufferSizeHighMark) { 399 | BytesVec().swap(buffer); 400 | } 401 | else { 402 | buffer.clear(); 403 | } 404 | } 405 | else { 406 | buffer.erase( buffer.begin(), buffer.begin() + processed); 407 | } 408 | }; 409 | 410 | /////////////////////////////////////////////////////////// 411 | // utility funcs 412 | static IBString errMsg(std::exception e) { 413 | // return the error associated with this exception 414 | return IBString(e.what()); 415 | } 416 | 417 | 418 | #ifdef _MSC_VER 419 | static IBString errMsg(CException *e) { 420 | // return the error associated with this exception 421 | char buf[1024]; 422 | e->GetErrorMessage( buf, sizeof buf); 423 | return IBString( buf); 424 | } 425 | #endif 426 | 427 | /////////////////////////////////////////////////////////// 428 | // member funcs 429 | EClientSocketBase::EClientSocketBase( EWrapper *ptr) 430 | : m_pEWrapper(ptr) 431 | , m_clientId(-1) 432 | , m_connected(false) 433 | , m_serverVersion(0) 434 | { 435 | } 436 | 437 | EClientSocketBase::~EClientSocketBase() 438 | { 439 | } 440 | 441 | void EClientSocketBase::eConnectBase() 442 | { 443 | } 444 | 445 | void EClientSocketBase::eDisconnectBase() 446 | { 447 | Empty(m_TwsTime); 448 | m_serverVersion = 0; 449 | m_connected = false; 450 | m_clientId = -1; 451 | m_outBuffer.clear(); 452 | m_inBuffer.clear(); 453 | } 454 | 455 | int EClientSocketBase::serverVersion() 456 | { 457 | return m_serverVersion; 458 | } 459 | 460 | IBString EClientSocketBase::TwsConnectionTime() 461 | { 462 | return m_TwsTime; 463 | } 464 | 465 | void EClientSocketBase::reqMktData(TickerId tickerId, const Contract& contract, 466 | const IBString& genericTicks, bool snapshot) 467 | { 468 | // not connected? 469 | if( !m_connected) { 470 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 471 | return; 472 | } 473 | 474 | // not needed anymore validation 475 | //if( m_serverVersion < MIN_SERVER_VER_SNAPSHOT_MKT_DATA && snapshot) { 476 | // m_pEWrapper->error( tickerId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 477 | // " It does not support snapshot market data requests."); 478 | // return; 479 | //} 480 | 481 | if( m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { 482 | if( contract.underComp) { 483 | m_pEWrapper->error( tickerId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 484 | " It does not support delta-neutral orders."); 485 | return; 486 | } 487 | } 488 | 489 | if (m_serverVersion < MIN_SERVER_VER_REQ_MKT_DATA_CONID) { 490 | if( contract.conId > 0) { 491 | m_pEWrapper->error( tickerId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 492 | " It does not support conId parameter."); 493 | return; 494 | } 495 | } 496 | 497 | std::ostringstream msg; 498 | 499 | const int VERSION = 9; 500 | 501 | // send req mkt data msg 502 | ENCODE_FIELD( REQ_MKT_DATA); 503 | ENCODE_FIELD( VERSION); 504 | ENCODE_FIELD( tickerId); 505 | 506 | // send contract fields 507 | if( m_serverVersion >= MIN_SERVER_VER_REQ_MKT_DATA_CONID) { 508 | ENCODE_FIELD( contract.conId); 509 | } 510 | ENCODE_FIELD( contract.symbol); 511 | ENCODE_FIELD( contract.secType); 512 | ENCODE_FIELD( contract.expiry); 513 | ENCODE_FIELD( contract.strike); 514 | ENCODE_FIELD( contract.right); 515 | ENCODE_FIELD( contract.multiplier); // srv v15 and above 516 | 517 | ENCODE_FIELD( contract.exchange); 518 | ENCODE_FIELD( contract.primaryExchange); // srv v14 and above 519 | ENCODE_FIELD( contract.currency); 520 | 521 | ENCODE_FIELD( contract.localSymbol); // srv v2 and above 522 | 523 | // Send combo legs for BAG requests (srv v8 and above) 524 | if( Compare(contract.secType, "BAG") == 0) 525 | { 526 | if( !contract.comboLegs || contract.comboLegs->empty()) { 527 | ENCODE_FIELD( 0); 528 | } 529 | else { 530 | typedef Contract::ComboLegList ComboLegList; 531 | const ComboLegList& comboLegs = *contract.comboLegs; 532 | ENCODE_FIELD( (int)comboLegs.size() ); 533 | ComboLegList::const_iterator iter = comboLegs.begin(); 534 | const ComboLegList::const_iterator iterEnd = comboLegs.end(); 535 | for( ; iter != iterEnd; ++iter) { 536 | const ComboLeg* comboLeg = *iter; 537 | assert( comboLeg); 538 | ENCODE_FIELD( comboLeg->conId); 539 | ENCODE_FIELD( comboLeg->ratio); 540 | ENCODE_FIELD( comboLeg->action); 541 | ENCODE_FIELD( comboLeg->exchange); 542 | } 543 | } 544 | } 545 | 546 | if( m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { 547 | if( contract.underComp) { 548 | const UnderComp& underComp = *contract.underComp; 549 | ENCODE_FIELD( true); 550 | ENCODE_FIELD( underComp.conId); 551 | ENCODE_FIELD( underComp.delta); 552 | ENCODE_FIELD( underComp.price); 553 | } 554 | else { 555 | ENCODE_FIELD( false); 556 | } 557 | } 558 | 559 | ENCODE_FIELD( genericTicks); // srv v31 and above 560 | ENCODE_FIELD( snapshot); // srv v35 and above 561 | 562 | bufferedSend( msg.str()); 563 | } 564 | 565 | void EClientSocketBase::cancelMktData(TickerId tickerId) 566 | { 567 | // not connected? 568 | if( !m_connected) { 569 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 570 | return; 571 | } 572 | 573 | std::ostringstream msg; 574 | 575 | const int VERSION = 2; 576 | 577 | // send cancel mkt data msg 578 | ENCODE_FIELD( CANCEL_MKT_DATA); 579 | ENCODE_FIELD( VERSION); 580 | ENCODE_FIELD( tickerId); 581 | 582 | bufferedSend( msg.str()); 583 | } 584 | 585 | void EClientSocketBase::reqMktDepth( TickerId tickerId, const Contract &contract, int numRows) 586 | { 587 | // not connected? 588 | if( !m_connected) { 589 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 590 | return; 591 | } 592 | 593 | // Not needed anymore validation 594 | // This feature is only available for versions of TWS >=6 595 | //if( m_serverVersion < 6) { 596 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 597 | // return; 598 | //} 599 | 600 | std::ostringstream msg; 601 | 602 | const int VERSION = 3; 603 | 604 | // send req mkt data msg 605 | ENCODE_FIELD( REQ_MKT_DEPTH); 606 | ENCODE_FIELD( VERSION); 607 | ENCODE_FIELD( tickerId); 608 | 609 | // send contract fields 610 | ENCODE_FIELD( contract.symbol); 611 | ENCODE_FIELD( contract.secType); 612 | ENCODE_FIELD( contract.expiry); 613 | ENCODE_FIELD( contract.strike); 614 | ENCODE_FIELD( contract.right); 615 | ENCODE_FIELD( contract.multiplier); // srv v15 and above 616 | ENCODE_FIELD( contract.exchange); 617 | ENCODE_FIELD( contract.currency); 618 | ENCODE_FIELD( contract.localSymbol); 619 | ENCODE_FIELD( numRows); // srv v19 and above 620 | 621 | bufferedSend( msg.str()); 622 | } 623 | 624 | 625 | void EClientSocketBase::cancelMktDepth( TickerId tickerId) 626 | { 627 | // not connected? 628 | if( !m_connected) { 629 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 630 | return; 631 | } 632 | 633 | // Not needed anymore validation 634 | // This feature is only available for versions of TWS >=6 635 | //if( m_serverVersion < 6) { 636 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 637 | // return; 638 | //} 639 | 640 | std::ostringstream msg; 641 | 642 | const int VERSION = 1; 643 | 644 | // send cancel mkt data msg 645 | ENCODE_FIELD( CANCEL_MKT_DEPTH); 646 | ENCODE_FIELD( VERSION); 647 | ENCODE_FIELD( tickerId); 648 | 649 | bufferedSend( msg.str()); 650 | } 651 | 652 | void EClientSocketBase::reqHistoricalData( TickerId tickerId, const Contract &contract, 653 | const IBString &endDateTime, const IBString &durationStr, 654 | const IBString & barSizeSetting, const IBString &whatToShow, 655 | int useRTH, int formatDate) 656 | { 657 | // not connected? 658 | if( !m_connected) { 659 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 660 | return; 661 | } 662 | 663 | // Not needed anymore validation 664 | //if( m_serverVersion < 16) { 665 | // m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 666 | // return; 667 | //} 668 | 669 | std::ostringstream msg; 670 | 671 | const int VERSION = 4; 672 | 673 | ENCODE_FIELD( REQ_HISTORICAL_DATA); 674 | ENCODE_FIELD( VERSION); 675 | ENCODE_FIELD( tickerId); 676 | 677 | // send contract fields 678 | ENCODE_FIELD( contract.symbol); 679 | ENCODE_FIELD( contract.secType); 680 | ENCODE_FIELD( contract.expiry); 681 | ENCODE_FIELD( contract.strike); 682 | ENCODE_FIELD( contract.right); 683 | ENCODE_FIELD( contract.multiplier); 684 | ENCODE_FIELD( contract.exchange); 685 | ENCODE_FIELD( contract.primaryExchange); 686 | ENCODE_FIELD( contract.currency); 687 | ENCODE_FIELD( contract.localSymbol); 688 | ENCODE_FIELD( contract.includeExpired); // srv v31 and above 689 | 690 | ENCODE_FIELD( endDateTime); // srv v20 and above 691 | ENCODE_FIELD( barSizeSetting); // srv v20 and above 692 | 693 | ENCODE_FIELD( durationStr); 694 | ENCODE_FIELD( useRTH); 695 | ENCODE_FIELD( whatToShow); 696 | ENCODE_FIELD( formatDate); // srv v16 and above 697 | 698 | // Send combo legs for BAG requests 699 | if( Compare(contract.secType, "BAG") == 0) 700 | { 701 | if( !contract.comboLegs || contract.comboLegs->empty()) { 702 | ENCODE_FIELD( 0); 703 | } 704 | else { 705 | typedef Contract::ComboLegList ComboLegList; 706 | const ComboLegList& comboLegs = *contract.comboLegs; 707 | ENCODE_FIELD( (int)comboLegs.size()); 708 | ComboLegList::const_iterator iter = comboLegs.begin(); 709 | const ComboLegList::const_iterator iterEnd = comboLegs.end(); 710 | for( ; iter != iterEnd; ++iter) { 711 | const ComboLeg* comboLeg = *iter; 712 | assert( comboLeg); 713 | ENCODE_FIELD( comboLeg->conId); 714 | ENCODE_FIELD( comboLeg->ratio); 715 | ENCODE_FIELD( comboLeg->action); 716 | ENCODE_FIELD( comboLeg->exchange); 717 | } 718 | } 719 | } 720 | 721 | bufferedSend( msg.str()); 722 | } 723 | 724 | void EClientSocketBase::cancelHistoricalData(TickerId tickerId) 725 | { 726 | // not connected? 727 | if( !m_connected) { 728 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 729 | return; 730 | } 731 | 732 | // Not needed anymore validation 733 | //if( m_serverVersion < 24) { 734 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 735 | // " It does not support historical data query cancellation."); 736 | // return; 737 | //} 738 | 739 | std::ostringstream msg; 740 | 741 | const int VERSION = 1; 742 | 743 | ENCODE_FIELD( CANCEL_HISTORICAL_DATA); 744 | ENCODE_FIELD( VERSION); 745 | ENCODE_FIELD( tickerId); 746 | 747 | bufferedSend( msg.str()); 748 | } 749 | 750 | void EClientSocketBase::reqRealTimeBars(TickerId tickerId, const Contract &contract, 751 | int barSize, const IBString &whatToShow, bool useRTH) 752 | { 753 | // not connected? 754 | if( !m_connected) { 755 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 756 | return; 757 | } 758 | 759 | // Not needed anymore validation 760 | //if( m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { 761 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 762 | // " It does not support real time bars."); 763 | // return; 764 | //} 765 | 766 | std::ostringstream msg; 767 | 768 | const int VERSION = 1; 769 | 770 | ENCODE_FIELD( REQ_REAL_TIME_BARS); 771 | ENCODE_FIELD( VERSION); 772 | ENCODE_FIELD( tickerId); 773 | 774 | // send contract fields 775 | ENCODE_FIELD( contract.symbol); 776 | ENCODE_FIELD( contract.secType); 777 | ENCODE_FIELD( contract.expiry); 778 | ENCODE_FIELD( contract.strike); 779 | ENCODE_FIELD( contract.right); 780 | ENCODE_FIELD( contract.multiplier); 781 | ENCODE_FIELD( contract.exchange); 782 | ENCODE_FIELD( contract.primaryExchange); 783 | ENCODE_FIELD( contract.currency); 784 | ENCODE_FIELD( contract.localSymbol); 785 | ENCODE_FIELD( barSize); 786 | ENCODE_FIELD( whatToShow); 787 | ENCODE_FIELD( useRTH); 788 | 789 | bufferedSend( msg.str()); 790 | } 791 | 792 | 793 | void EClientSocketBase::cancelRealTimeBars(TickerId tickerId) 794 | { 795 | // not connected? 796 | if( !m_connected) { 797 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 798 | return; 799 | } 800 | 801 | // Not needed anymore validation 802 | //if( m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { 803 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 804 | // " It does not support realtime bar data query cancellation."); 805 | // return; 806 | //} 807 | 808 | std::ostringstream msg; 809 | 810 | const int VERSION = 1; 811 | 812 | ENCODE_FIELD( CANCEL_REAL_TIME_BARS); 813 | ENCODE_FIELD( VERSION); 814 | ENCODE_FIELD( tickerId); 815 | 816 | bufferedSend( msg.str()); 817 | } 818 | 819 | 820 | void EClientSocketBase::reqScannerParameters() 821 | { 822 | // not connected? 823 | if( !m_connected) { 824 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 825 | return; 826 | } 827 | 828 | // Not needed anymore validation 829 | //if( m_serverVersion < 24) { 830 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 831 | // " It does not support API scanner subscription."); 832 | // return; 833 | //} 834 | 835 | std::ostringstream msg; 836 | 837 | const int VERSION = 1; 838 | 839 | ENCODE_FIELD( REQ_SCANNER_PARAMETERS); 840 | ENCODE_FIELD( VERSION); 841 | 842 | bufferedSend( msg.str()); 843 | } 844 | 845 | 846 | void EClientSocketBase::reqScannerSubscription(int tickerId, 847 | const ScannerSubscription& subscription) 848 | { 849 | // not connected? 850 | if( !m_connected) { 851 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 852 | return; 853 | } 854 | 855 | // Not needed anymore validation 856 | //if( m_serverVersion < 24) { 857 | // m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 858 | // " It does not support API scanner subscription."); 859 | // return; 860 | //} 861 | 862 | std::ostringstream msg; 863 | 864 | const int VERSION = 3; 865 | 866 | ENCODE_FIELD( REQ_SCANNER_SUBSCRIPTION); 867 | ENCODE_FIELD( VERSION); 868 | ENCODE_FIELD( tickerId); 869 | ENCODE_FIELD_MAX( subscription.numberOfRows); 870 | ENCODE_FIELD( subscription.instrument); 871 | ENCODE_FIELD( subscription.locationCode); 872 | ENCODE_FIELD( subscription.scanCode); 873 | ENCODE_FIELD_MAX( subscription.abovePrice); 874 | ENCODE_FIELD_MAX( subscription.belowPrice); 875 | ENCODE_FIELD_MAX( subscription.aboveVolume); 876 | ENCODE_FIELD_MAX( subscription.marketCapAbove); 877 | ENCODE_FIELD_MAX( subscription.marketCapBelow); 878 | ENCODE_FIELD( subscription.moodyRatingAbove); 879 | ENCODE_FIELD( subscription.moodyRatingBelow); 880 | ENCODE_FIELD( subscription.spRatingAbove); 881 | ENCODE_FIELD( subscription.spRatingBelow); 882 | ENCODE_FIELD( subscription.maturityDateAbove); 883 | ENCODE_FIELD( subscription.maturityDateBelow); 884 | ENCODE_FIELD_MAX( subscription.couponRateAbove); 885 | ENCODE_FIELD_MAX( subscription.couponRateBelow); 886 | ENCODE_FIELD_MAX( subscription.excludeConvertible); 887 | ENCODE_FIELD_MAX( subscription.averageOptionVolumeAbove); // srv v25 and above 888 | ENCODE_FIELD( subscription.scannerSettingPairs); // srv v25 and above 889 | ENCODE_FIELD( subscription.stockTypeFilter); // srv v27 and above 890 | 891 | bufferedSend( msg.str()); 892 | } 893 | 894 | void EClientSocketBase::cancelScannerSubscription(int tickerId) 895 | { 896 | // not connected? 897 | if( !m_connected) { 898 | m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 899 | return; 900 | } 901 | 902 | // Not needed anymore validation 903 | //if( m_serverVersion < 24) { 904 | // m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 905 | // " It does not support API scanner subscription."); 906 | // return; 907 | //} 908 | 909 | std::ostringstream msg; 910 | 911 | const int VERSION = 1; 912 | 913 | ENCODE_FIELD( CANCEL_SCANNER_SUBSCRIPTION); 914 | ENCODE_FIELD( VERSION); 915 | ENCODE_FIELD( tickerId); 916 | 917 | bufferedSend( msg.str()); 918 | } 919 | 920 | void EClientSocketBase::reqFundamentalData(TickerId reqId, const Contract& contract, 921 | const IBString& reportType) 922 | { 923 | // not connected? 924 | if( !m_connected) { 925 | m_pEWrapper->error( reqId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 926 | return; 927 | } 928 | 929 | if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { 930 | m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 931 | " It does not support fundamental data requests."); 932 | return; 933 | } 934 | 935 | std::ostringstream msg; 936 | 937 | const int VERSION = 1; 938 | 939 | ENCODE_FIELD( REQ_FUNDAMENTAL_DATA); 940 | ENCODE_FIELD( VERSION); 941 | ENCODE_FIELD( reqId); 942 | 943 | // send contract fields 944 | ENCODE_FIELD( contract.symbol); 945 | ENCODE_FIELD( contract.secType); 946 | ENCODE_FIELD( contract.exchange); 947 | ENCODE_FIELD( contract.primaryExchange); 948 | ENCODE_FIELD( contract.currency); 949 | ENCODE_FIELD( contract.localSymbol); 950 | 951 | ENCODE_FIELD( reportType); 952 | 953 | bufferedSend( msg.str()); 954 | } 955 | 956 | void EClientSocketBase::cancelFundamentalData( TickerId reqId) 957 | { 958 | // not connected? 959 | if( !m_connected) { 960 | m_pEWrapper->error( reqId, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 961 | return; 962 | } 963 | 964 | if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { 965 | m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 966 | " It does not support fundamental data requests."); 967 | return; 968 | } 969 | 970 | std::ostringstream msg; 971 | 972 | const int VERSION = 1; 973 | 974 | ENCODE_FIELD( CANCEL_FUNDAMENTAL_DATA); 975 | ENCODE_FIELD( VERSION); 976 | ENCODE_FIELD( reqId); 977 | 978 | bufferedSend( msg.str()); 979 | } 980 | 981 | void EClientSocketBase::calculateImpliedVolatility(TickerId reqId, const Contract &contract, double optionPrice, double underPrice) { 982 | 983 | // not connected? 984 | if( !m_connected) { 985 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 986 | return; 987 | } 988 | 989 | if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT) { 990 | m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 991 | " It does not support calculate implied volatility requests."); 992 | return; 993 | } 994 | 995 | std::ostringstream msg; 996 | 997 | const int VERSION = 1; 998 | 999 | ENCODE_FIELD( REQ_CALC_IMPLIED_VOLAT); 1000 | ENCODE_FIELD( VERSION); 1001 | ENCODE_FIELD( reqId); 1002 | 1003 | // send contract fields 1004 | ENCODE_FIELD( contract.conId); 1005 | ENCODE_FIELD( contract.symbol); 1006 | ENCODE_FIELD( contract.secType); 1007 | ENCODE_FIELD( contract.expiry); 1008 | ENCODE_FIELD( contract.strike); 1009 | ENCODE_FIELD( contract.right); 1010 | ENCODE_FIELD( contract.multiplier); 1011 | ENCODE_FIELD( contract.exchange); 1012 | ENCODE_FIELD( contract.primaryExchange); 1013 | ENCODE_FIELD( contract.currency); 1014 | ENCODE_FIELD( contract.localSymbol); 1015 | 1016 | ENCODE_FIELD( optionPrice); 1017 | ENCODE_FIELD( underPrice); 1018 | 1019 | bufferedSend( msg.str()); 1020 | } 1021 | 1022 | void EClientSocketBase::cancelCalculateImpliedVolatility(TickerId reqId) { 1023 | 1024 | // not connected? 1025 | if( !m_connected) { 1026 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1027 | return; 1028 | } 1029 | 1030 | if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT) { 1031 | m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1032 | " It does not support calculate implied volatility cancellation."); 1033 | return; 1034 | } 1035 | 1036 | std::ostringstream msg; 1037 | 1038 | const int VERSION = 1; 1039 | 1040 | ENCODE_FIELD( CANCEL_CALC_IMPLIED_VOLAT); 1041 | ENCODE_FIELD( VERSION); 1042 | ENCODE_FIELD( reqId); 1043 | 1044 | bufferedSend( msg.str()); 1045 | } 1046 | 1047 | void EClientSocketBase::calculateOptionPrice(TickerId reqId, const Contract &contract, double volatility, double underPrice) { 1048 | 1049 | // not connected? 1050 | if( !m_connected) { 1051 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1052 | return; 1053 | } 1054 | 1055 | if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_OPTION_PRICE) { 1056 | m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1057 | " It does not support calculate option price requests."); 1058 | return; 1059 | } 1060 | 1061 | std::ostringstream msg; 1062 | 1063 | const int VERSION = 1; 1064 | 1065 | ENCODE_FIELD( REQ_CALC_OPTION_PRICE); 1066 | ENCODE_FIELD( VERSION); 1067 | ENCODE_FIELD( reqId); 1068 | 1069 | // send contract fields 1070 | ENCODE_FIELD( contract.conId); 1071 | ENCODE_FIELD( contract.symbol); 1072 | ENCODE_FIELD( contract.secType); 1073 | ENCODE_FIELD( contract.expiry); 1074 | ENCODE_FIELD( contract.strike); 1075 | ENCODE_FIELD( contract.right); 1076 | ENCODE_FIELD( contract.multiplier); 1077 | ENCODE_FIELD( contract.exchange); 1078 | ENCODE_FIELD( contract.primaryExchange); 1079 | ENCODE_FIELD( contract.currency); 1080 | ENCODE_FIELD( contract.localSymbol); 1081 | 1082 | ENCODE_FIELD( volatility); 1083 | ENCODE_FIELD( underPrice); 1084 | 1085 | bufferedSend( msg.str()); 1086 | } 1087 | 1088 | void EClientSocketBase::cancelCalculateOptionPrice(TickerId reqId) { 1089 | 1090 | // not connected? 1091 | if( !m_connected) { 1092 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1093 | return; 1094 | } 1095 | 1096 | if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE) { 1097 | m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1098 | " It does not support calculate option price cancellation."); 1099 | return; 1100 | } 1101 | 1102 | std::ostringstream msg; 1103 | 1104 | const int VERSION = 1; 1105 | 1106 | ENCODE_FIELD( CANCEL_CALC_OPTION_PRICE); 1107 | ENCODE_FIELD( VERSION); 1108 | ENCODE_FIELD( reqId); 1109 | 1110 | bufferedSend( msg.str()); 1111 | } 1112 | 1113 | void EClientSocketBase::reqContractDetails( int reqId, const Contract& contract) 1114 | { 1115 | // not connected? 1116 | if( !m_connected) { 1117 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1118 | return; 1119 | } 1120 | 1121 | // Not needed anymore validation 1122 | // This feature is only available for versions of TWS >=4 1123 | //if( m_serverVersion < 4) { 1124 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 1125 | // return; 1126 | //} 1127 | if (m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { 1128 | if( !IsEmpty(contract.secIdType) || !IsEmpty(contract.secId)) { 1129 | m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1130 | " It does not support secIdType and secId parameters."); 1131 | return; 1132 | } 1133 | } 1134 | 1135 | std::ostringstream msg; 1136 | 1137 | const int VERSION = 6; 1138 | 1139 | // send req mkt data msg 1140 | ENCODE_FIELD( REQ_CONTRACT_DATA); 1141 | ENCODE_FIELD( VERSION); 1142 | 1143 | if( m_serverVersion >= MIN_SERVER_VER_CONTRACT_DATA_CHAIN) { 1144 | ENCODE_FIELD( reqId); 1145 | } 1146 | 1147 | // send contract fields 1148 | ENCODE_FIELD( contract.conId); // srv v37 and above 1149 | ENCODE_FIELD( contract.symbol); 1150 | ENCODE_FIELD( contract.secType); 1151 | ENCODE_FIELD( contract.expiry); 1152 | ENCODE_FIELD( contract.strike); 1153 | ENCODE_FIELD( contract.right); 1154 | ENCODE_FIELD( contract.multiplier); // srv v15 and above 1155 | ENCODE_FIELD( contract.exchange); 1156 | ENCODE_FIELD( contract.currency); 1157 | ENCODE_FIELD( contract.localSymbol); 1158 | ENCODE_FIELD( contract.includeExpired); // srv v31 and above 1159 | 1160 | if( m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE){ 1161 | ENCODE_FIELD( contract.secIdType); 1162 | ENCODE_FIELD( contract.secId); 1163 | } 1164 | 1165 | bufferedSend( msg.str()); 1166 | } 1167 | 1168 | void EClientSocketBase::reqCurrentTime() 1169 | { 1170 | // not connected? 1171 | if( !m_connected) { 1172 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1173 | return; 1174 | } 1175 | 1176 | // Not needed anymore validation 1177 | // This feature is only available for versions of TWS >= 33 1178 | //if( m_serverVersion < 33) { 1179 | // m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1180 | // " It does not support current time requests."); 1181 | // return; 1182 | //} 1183 | 1184 | std::ostringstream msg; 1185 | 1186 | const int VERSION = 1; 1187 | 1188 | // send current time req 1189 | ENCODE_FIELD( REQ_CURRENT_TIME); 1190 | ENCODE_FIELD( VERSION); 1191 | 1192 | bufferedSend( msg.str()); 1193 | } 1194 | 1195 | void EClientSocketBase::placeOrder( OrderId id, const Contract &contract, const Order &order) 1196 | { 1197 | // not connected? 1198 | if( !m_connected) { 1199 | m_pEWrapper->error( id, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1200 | return; 1201 | } 1202 | 1203 | // Not needed anymore validation 1204 | //if( m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS) { 1205 | // if( order.scaleNumComponents != UNSET_INTEGER || 1206 | // order.scaleComponentSize != UNSET_INTEGER || 1207 | // order.scalePriceIncrement != UNSET_DOUBLE) { 1208 | // m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1209 | // " It does not support Scale orders."); 1210 | // return; 1211 | // } 1212 | //} 1213 | // 1214 | //if( m_serverVersion < MIN_SERVER_VER_SSHORT_COMBO_LEGS) { 1215 | // if( contract.comboLegs && !contract.comboLegs->empty()) { 1216 | // typedef Contract::ComboLegList ComboLegList; 1217 | // const ComboLegList& comboLegs = *contract.comboLegs; 1218 | // ComboLegList::const_iterator iter = comboLegs.begin(); 1219 | // const ComboLegList::const_iterator iterEnd = comboLegs.end(); 1220 | // for( ; iter != iterEnd; ++iter) { 1221 | // const ComboLeg* comboLeg = *iter; 1222 | // assert( comboLeg); 1223 | // if( comboLeg->shortSaleSlot != 0 || 1224 | // !comboLeg->designatedLocation.IsEmpty()) { 1225 | // m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1226 | // " It does not support SSHORT flag for combo legs."); 1227 | // return; 1228 | // } 1229 | // } 1230 | // } 1231 | //} 1232 | // 1233 | //if( m_serverVersion < MIN_SERVER_VER_WHAT_IF_ORDERS) { 1234 | // if( order.whatIf) { 1235 | // m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1236 | // " It does not support what-if orders."); 1237 | // return; 1238 | // } 1239 | //} 1240 | 1241 | if( m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { 1242 | if( contract.underComp) { 1243 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1244 | " It does not support delta-neutral orders."); 1245 | return; 1246 | } 1247 | } 1248 | 1249 | if( m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS2) { 1250 | if( order.scaleSubsLevelSize != UNSET_INTEGER) { 1251 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1252 | " It does not support Subsequent Level Size for Scale orders."); 1253 | return; 1254 | } 1255 | } 1256 | 1257 | if( m_serverVersion < MIN_SERVER_VER_ALGO_ORDERS) { 1258 | 1259 | if( !IsEmpty(order.algoStrategy)) { 1260 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1261 | " It does not support algo orders."); 1262 | return; 1263 | } 1264 | } 1265 | 1266 | if( m_serverVersion < MIN_SERVER_VER_NOT_HELD) { 1267 | if (order.notHeld) { 1268 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1269 | " It does not support notHeld parameter."); 1270 | return; 1271 | } 1272 | } 1273 | 1274 | if (m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { 1275 | if( !IsEmpty(contract.secIdType) || !IsEmpty(contract.secId)) { 1276 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1277 | " It does not support secIdType and secId parameters."); 1278 | return; 1279 | } 1280 | } 1281 | 1282 | if (m_serverVersion < MIN_SERVER_VER_PLACE_ORDER_CONID) { 1283 | if( contract.conId > 0) { 1284 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1285 | " It does not support conId parameter."); 1286 | return; 1287 | } 1288 | } 1289 | 1290 | if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { 1291 | if( order.exemptCode != -1) { 1292 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1293 | " It does not support exemptCode parameter."); 1294 | return; 1295 | } 1296 | } 1297 | 1298 | if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { 1299 | if( contract.comboLegs && !contract.comboLegs->empty()) { 1300 | typedef Contract::ComboLegList ComboLegList; 1301 | const ComboLegList& comboLegs = *contract.comboLegs; 1302 | ComboLegList::const_iterator iter = comboLegs.begin(); 1303 | const ComboLegList::const_iterator iterEnd = comboLegs.end(); 1304 | for( ; iter != iterEnd; ++iter) { 1305 | const ComboLeg* comboLeg = *iter; 1306 | assert( comboLeg); 1307 | if( comboLeg->exemptCode != -1 ){ 1308 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1309 | " It does not support exemptCode parameter."); 1310 | return; 1311 | } 1312 | } 1313 | } 1314 | } 1315 | 1316 | if( m_serverVersion < MIN_SERVER_VER_HEDGE_ORDERS) { 1317 | if( !IsEmpty(order.hedgeType)) { 1318 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1319 | " It does not support hedge orders."); 1320 | return; 1321 | } 1322 | } 1323 | 1324 | if( m_serverVersion < MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) { 1325 | if (order.optOutSmartRouting) { 1326 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1327 | " It does not support optOutSmartRouting parameter."); 1328 | return; 1329 | } 1330 | } 1331 | 1332 | if (m_serverVersion < MIN_SERVER_VER_DELTA_NEUTRAL_CONID) { 1333 | if (order.deltaNeutralConId > 0 1334 | || !IsEmpty(order.deltaNeutralSettlingFirm) 1335 | || !IsEmpty(order.deltaNeutralClearingAccount) 1336 | || !IsEmpty(order.deltaNeutralClearingIntent) 1337 | ) { 1338 | m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1339 | " It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent."); 1340 | return; 1341 | } 1342 | } 1343 | 1344 | std::ostringstream msg; 1345 | 1346 | int VERSION = (m_serverVersion < MIN_SERVER_VER_NOT_HELD) ? 27 : 35; 1347 | 1348 | // send place order msg 1349 | ENCODE_FIELD( PLACE_ORDER); 1350 | ENCODE_FIELD( VERSION); 1351 | ENCODE_FIELD( id); 1352 | 1353 | // send contract fields 1354 | if( m_serverVersion >= MIN_SERVER_VER_PLACE_ORDER_CONID) { 1355 | ENCODE_FIELD( contract.conId); 1356 | } 1357 | ENCODE_FIELD( contract.symbol); 1358 | ENCODE_FIELD( contract.secType); 1359 | ENCODE_FIELD( contract.expiry); 1360 | ENCODE_FIELD( contract.strike); 1361 | ENCODE_FIELD( contract.right); 1362 | ENCODE_FIELD( contract.multiplier); // srv v15 and above 1363 | ENCODE_FIELD( contract.exchange); 1364 | ENCODE_FIELD( contract.primaryExchange); // srv v14 and above 1365 | ENCODE_FIELD( contract.currency); 1366 | ENCODE_FIELD( contract.localSymbol); // srv v2 and above 1367 | 1368 | if( m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE){ 1369 | ENCODE_FIELD( contract.secIdType); 1370 | ENCODE_FIELD( contract.secId); 1371 | } 1372 | 1373 | // send main order fields 1374 | ENCODE_FIELD( order.action); 1375 | ENCODE_FIELD( order.totalQuantity); 1376 | ENCODE_FIELD( order.orderType); 1377 | ENCODE_FIELD( order.lmtPrice); 1378 | ENCODE_FIELD( order.auxPrice); 1379 | 1380 | // send extended order fields 1381 | ENCODE_FIELD( order.tif); 1382 | ENCODE_FIELD( order.ocaGroup); 1383 | ENCODE_FIELD( order.account); 1384 | ENCODE_FIELD( order.openClose); 1385 | ENCODE_FIELD( order.origin); 1386 | ENCODE_FIELD( order.orderRef); 1387 | ENCODE_FIELD( order.transmit); 1388 | ENCODE_FIELD( order.parentId); // srv v4 and above 1389 | 1390 | ENCODE_FIELD( order.blockOrder); // srv v5 and above 1391 | ENCODE_FIELD( order.sweepToFill); // srv v5 and above 1392 | ENCODE_FIELD( order.displaySize); // srv v5 and above 1393 | ENCODE_FIELD( order.triggerMethod); // srv v5 and above 1394 | 1395 | //if( m_serverVersion < 38) { 1396 | // will never happen 1397 | // ENCODE_FIELD(/* order.ignoreRth */ false); 1398 | //} 1399 | //else { 1400 | ENCODE_FIELD( order.outsideRth); // srv v5 and above 1401 | //} 1402 | 1403 | ENCODE_FIELD( order.hidden); // srv v7 and above 1404 | 1405 | // Send combo legs for BAG requests (srv v8 and above) 1406 | if( /* m_serverVersion >= 8 && */ Compare(contract.secType, "BAG") == 0) 1407 | 1408 | { 1409 | if( !contract.comboLegs || contract.comboLegs->empty()) { 1410 | ENCODE_FIELD( 0); 1411 | } 1412 | else { 1413 | typedef Contract::ComboLegList ComboLegList; 1414 | const ComboLegList& comboLegs = *contract.comboLegs; 1415 | ENCODE_FIELD( (int)comboLegs.size()); 1416 | ComboLegList::const_iterator iter = comboLegs.begin(); 1417 | const ComboLegList::const_iterator iterEnd = comboLegs.end(); 1418 | for( ; iter != iterEnd; ++iter) { 1419 | const ComboLeg* comboLeg = *iter; 1420 | assert( comboLeg); 1421 | ENCODE_FIELD( comboLeg->conId); 1422 | ENCODE_FIELD( comboLeg->ratio); 1423 | ENCODE_FIELD( comboLeg->action); 1424 | ENCODE_FIELD( comboLeg->exchange); 1425 | ENCODE_FIELD( comboLeg->openClose); 1426 | 1427 | ENCODE_FIELD( comboLeg->shortSaleSlot); // srv v35 and above 1428 | ENCODE_FIELD( comboLeg->designatedLocation); // srv v35 and above 1429 | if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { 1430 | ENCODE_FIELD( comboLeg->exemptCode); 1431 | } 1432 | } 1433 | } 1434 | } 1435 | 1436 | if( m_serverVersion >= MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS && Compare(contract.secType, "BAG") == 0) { 1437 | const Order::TagValueList* const smartComboRoutingParams = order.smartComboRoutingParams.get(); 1438 | const int smartComboRoutingParamsCount = smartComboRoutingParams ? smartComboRoutingParams->size() : 0; 1439 | ENCODE_FIELD( smartComboRoutingParamsCount); 1440 | if( smartComboRoutingParamsCount > 0) { 1441 | for( int i = 0; i < smartComboRoutingParamsCount; ++i) { 1442 | const TagValue* tagValue = ((*smartComboRoutingParams)[i]).get(); 1443 | ENCODE_FIELD( tagValue->tag); 1444 | ENCODE_FIELD( tagValue->value); 1445 | } 1446 | } 1447 | } 1448 | 1449 | ///////////////////////////////////////////////////////////////////////////// 1450 | // Send the shares allocation. 1451 | // 1452 | // This specifies the number of order shares allocated to each Financial 1453 | // Advisor managed account. The format of the allocation string is as 1454 | // follows: 1455 | // /,/,...N 1456 | // E.g. 1457 | // To allocate 20 shares of a 100 share order to account 'U101' and the 1458 | // residual 80 to account 'U203' enter the following share allocation string: 1459 | // U101/20,U203/80 1460 | ///////////////////////////////////////////////////////////////////////////// 1461 | { 1462 | // send deprecated sharesAllocation field 1463 | ENCODE_FIELD( ""); // srv v9 and above 1464 | } 1465 | 1466 | ENCODE_FIELD( order.discretionaryAmt); // srv v10 and above 1467 | ENCODE_FIELD( order.goodAfterTime); // srv v11 and above 1468 | ENCODE_FIELD( order.goodTillDate); // srv v12 and above 1469 | 1470 | ENCODE_FIELD( order.faGroup); // srv v13 and above 1471 | ENCODE_FIELD( order.faMethod); // srv v13 and above 1472 | ENCODE_FIELD( order.faPercentage); // srv v13 and above 1473 | ENCODE_FIELD( order.faProfile); // srv v13 and above 1474 | 1475 | // institutional short saleslot data (srv v18 and above) 1476 | ENCODE_FIELD( order.shortSaleSlot); // 0 for retail, 1 or 2 for institutions 1477 | ENCODE_FIELD( order.designatedLocation); // populate only when shortSaleSlot = 2. 1478 | if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { 1479 | ENCODE_FIELD( order.exemptCode); 1480 | } 1481 | 1482 | // not needed anymore 1483 | //bool isVolOrder = (order.orderType.CompareNoCase("VOL") == 0); 1484 | 1485 | // srv v19 and above fields 1486 | ENCODE_FIELD( order.ocaType); 1487 | //if( m_serverVersion < 38) { 1488 | // will never happen 1489 | // send( /* order.rthOnly */ false); 1490 | //} 1491 | ENCODE_FIELD( order.rule80A); 1492 | ENCODE_FIELD( order.settlingFirm); 1493 | ENCODE_FIELD( order.allOrNone); 1494 | ENCODE_FIELD_MAX( order.minQty); 1495 | ENCODE_FIELD_MAX( order.percentOffset); 1496 | ENCODE_FIELD( order.eTradeOnly); 1497 | ENCODE_FIELD( order.firmQuoteOnly); 1498 | ENCODE_FIELD_MAX( order.nbboPriceCap); 1499 | ENCODE_FIELD( order.auctionStrategy); // AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT 1500 | ENCODE_FIELD_MAX( order.startingPrice); 1501 | ENCODE_FIELD_MAX( order.stockRefPrice); 1502 | ENCODE_FIELD_MAX( order.delta); 1503 | // Volatility orders had specific watermark price attribs in server version 26 1504 | //double lower = (m_serverVersion == 26 && isVolOrder) ? DBL_MAX : order.stockRangeLower; 1505 | //double upper = (m_serverVersion == 26 && isVolOrder) ? DBL_MAX : order.stockRangeUpper; 1506 | ENCODE_FIELD_MAX( order.stockRangeLower); 1507 | ENCODE_FIELD_MAX( order.stockRangeUpper); 1508 | 1509 | ENCODE_FIELD( order.overridePercentageConstraints); // srv v22 and above 1510 | 1511 | // Volatility orders (srv v26 and above) 1512 | ENCODE_FIELD_MAX( order.volatility); 1513 | ENCODE_FIELD_MAX( order.volatilityType); 1514 | // will never happen 1515 | //if( m_serverVersion < 28) { 1516 | // send( order.deltaNeutralOrderType.CompareNoCase("MKT") == 0); 1517 | //} 1518 | //else { 1519 | ENCODE_FIELD( order.deltaNeutralOrderType); // srv v28 and above 1520 | ENCODE_FIELD_MAX( order.deltaNeutralAuxPrice); // srv v28 and above 1521 | 1522 | if (m_serverVersion >= MIN_SERVER_VER_DELTA_NEUTRAL_CONID && !IsEmpty(order.deltaNeutralOrderType)){ 1523 | ENCODE_FIELD( order.deltaNeutralConId); 1524 | ENCODE_FIELD( order.deltaNeutralSettlingFirm); 1525 | ENCODE_FIELD( order.deltaNeutralClearingAccount); 1526 | ENCODE_FIELD( order.deltaNeutralClearingIntent); 1527 | } 1528 | 1529 | //} 1530 | ENCODE_FIELD( order.continuousUpdate); 1531 | //if( m_serverVersion == 26) { 1532 | // // Volatility orders had specific watermark price attribs in server version 26 1533 | // double lower = (isVolOrder ? order.stockRangeLower : DBL_MAX); 1534 | // double upper = (isVolOrder ? order.stockRangeUpper : DBL_MAX); 1535 | // ENCODE_FIELD_MAX( lower); 1536 | // ENCODE_FIELD_MAX( upper); 1537 | //} 1538 | ENCODE_FIELD_MAX( order.referencePriceType); 1539 | 1540 | ENCODE_FIELD_MAX( order.trailStopPrice); // srv v30 and above 1541 | 1542 | // SCALE orders 1543 | if( m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS2) { 1544 | ENCODE_FIELD_MAX( order.scaleInitLevelSize); 1545 | ENCODE_FIELD_MAX( order.scaleSubsLevelSize); 1546 | } 1547 | else { 1548 | // srv v35 and above) 1549 | ENCODE_FIELD( ""); // for not supported scaleNumComponents 1550 | ENCODE_FIELD_MAX( order.scaleInitLevelSize); // for scaleComponentSize 1551 | } 1552 | 1553 | ENCODE_FIELD_MAX( order.scalePriceIncrement); 1554 | 1555 | // HEDGE orders 1556 | if( m_serverVersion >= MIN_SERVER_VER_HEDGE_ORDERS) { 1557 | ENCODE_FIELD( order.hedgeType); 1558 | if ( !IsEmpty(order.hedgeType)) { 1559 | ENCODE_FIELD( order.hedgeParam); 1560 | } 1561 | } 1562 | 1563 | if( m_serverVersion >= MIN_SERVER_VER_OPT_OUT_SMART_ROUTING){ 1564 | ENCODE_FIELD( order.optOutSmartRouting); 1565 | } 1566 | 1567 | if( m_serverVersion >= MIN_SERVER_VER_PTA_ORDERS) { 1568 | ENCODE_FIELD( order.clearingAccount); 1569 | ENCODE_FIELD( order.clearingIntent); 1570 | } 1571 | 1572 | if( m_serverVersion >= MIN_SERVER_VER_NOT_HELD){ 1573 | ENCODE_FIELD( order.notHeld); 1574 | } 1575 | 1576 | if( m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { 1577 | if( contract.underComp) { 1578 | const UnderComp& underComp = *contract.underComp; 1579 | ENCODE_FIELD( true); 1580 | ENCODE_FIELD( underComp.conId); 1581 | ENCODE_FIELD( underComp.delta); 1582 | ENCODE_FIELD( underComp.price); 1583 | } 1584 | else { 1585 | ENCODE_FIELD( false); 1586 | } 1587 | } 1588 | 1589 | if( m_serverVersion >= MIN_SERVER_VER_ALGO_ORDERS) { 1590 | ENCODE_FIELD( order.algoStrategy); 1591 | 1592 | if( !IsEmpty(order.algoStrategy)) { 1593 | const Order::TagValueList* const algoParams = order.algoParams.get(); 1594 | const int algoParamsCount = algoParams ? algoParams->size() : 0; 1595 | ENCODE_FIELD( algoParamsCount); 1596 | if( algoParamsCount > 0) { 1597 | for( int i = 0; i < algoParamsCount; ++i) { 1598 | const TagValue* tagValue = ((*algoParams)[i]).get(); 1599 | ENCODE_FIELD( tagValue->tag); 1600 | ENCODE_FIELD( tagValue->value); 1601 | } 1602 | } 1603 | } 1604 | } 1605 | 1606 | ENCODE_FIELD( order.whatIf); // srv v36 and above 1607 | 1608 | bufferedSend( msg.str()); 1609 | } 1610 | 1611 | void EClientSocketBase::cancelOrder( OrderId id) 1612 | { 1613 | // not connected? 1614 | if( !m_connected) { 1615 | m_pEWrapper->error( id, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1616 | return; 1617 | } 1618 | 1619 | const int VERSION = 1; 1620 | 1621 | // send cancel order msg 1622 | std::ostringstream msg; 1623 | 1624 | ENCODE_FIELD( CANCEL_ORDER); 1625 | ENCODE_FIELD( VERSION); 1626 | ENCODE_FIELD( id); 1627 | 1628 | bufferedSend( msg.str()); 1629 | } 1630 | 1631 | void EClientSocketBase::reqAccountUpdates(bool subscribe, const IBString& acctCode) 1632 | { 1633 | // not connected? 1634 | if( !m_connected) { 1635 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1636 | return; 1637 | } 1638 | 1639 | std::ostringstream msg; 1640 | 1641 | const int VERSION = 2; 1642 | 1643 | // send req acct msg 1644 | ENCODE_FIELD( REQ_ACCT_DATA); 1645 | ENCODE_FIELD( VERSION); 1646 | ENCODE_FIELD( subscribe); // TRUE = subscribe, FALSE = unsubscribe. 1647 | 1648 | // Send the account code. This will only be used for FA clients 1649 | ENCODE_FIELD( acctCode); // srv v9 and above 1650 | 1651 | bufferedSend( msg.str()); 1652 | } 1653 | 1654 | void EClientSocketBase::reqOpenOrders() 1655 | { 1656 | // not connected? 1657 | if( !m_connected) { 1658 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1659 | return; 1660 | } 1661 | 1662 | std::ostringstream msg; 1663 | 1664 | const int VERSION = 1; 1665 | 1666 | // send req open orders msg 1667 | ENCODE_FIELD( REQ_OPEN_ORDERS); 1668 | ENCODE_FIELD( VERSION); 1669 | 1670 | bufferedSend( msg.str()); 1671 | } 1672 | 1673 | void EClientSocketBase::reqAutoOpenOrders(bool bAutoBind) 1674 | { 1675 | // not connected? 1676 | if( !m_connected) { 1677 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1678 | return; 1679 | } 1680 | 1681 | std::ostringstream msg; 1682 | 1683 | const int VERSION = 1; 1684 | 1685 | // send req open orders msg 1686 | ENCODE_FIELD( REQ_AUTO_OPEN_ORDERS); 1687 | ENCODE_FIELD( VERSION); 1688 | ENCODE_FIELD( bAutoBind); 1689 | 1690 | bufferedSend( msg.str()); 1691 | } 1692 | 1693 | void EClientSocketBase::reqAllOpenOrders() 1694 | { 1695 | // not connected? 1696 | if( !m_connected) { 1697 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1698 | return; 1699 | } 1700 | 1701 | std::ostringstream msg; 1702 | 1703 | const int VERSION = 1; 1704 | 1705 | // send req open orders msg 1706 | ENCODE_FIELD( REQ_ALL_OPEN_ORDERS); 1707 | ENCODE_FIELD( VERSION); 1708 | 1709 | bufferedSend( msg.str()); 1710 | } 1711 | 1712 | void EClientSocketBase::reqExecutions(int reqId, const ExecutionFilter& filter) 1713 | { 1714 | //NOTE: Time format must be 'yyyymmdd-hh:mm:ss' E.g. '20030702-14:55' 1715 | 1716 | // not connected? 1717 | if( !m_connected) { 1718 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1719 | return; 1720 | } 1721 | 1722 | std::ostringstream msg; 1723 | 1724 | const int VERSION = 3; 1725 | 1726 | // send req open orders msg 1727 | ENCODE_FIELD( REQ_EXECUTIONS); 1728 | ENCODE_FIELD( VERSION); 1729 | 1730 | if( m_serverVersion >= MIN_SERVER_VER_EXECUTION_DATA_CHAIN) { 1731 | ENCODE_FIELD( reqId); 1732 | } 1733 | 1734 | // Send the execution rpt filter data (srv v9 and above) 1735 | ENCODE_FIELD( filter.m_clientId); 1736 | ENCODE_FIELD( filter.m_acctCode); 1737 | ENCODE_FIELD( filter.m_time); 1738 | ENCODE_FIELD( filter.m_symbol); 1739 | ENCODE_FIELD( filter.m_secType); 1740 | ENCODE_FIELD( filter.m_exchange); 1741 | ENCODE_FIELD( filter.m_side); 1742 | 1743 | bufferedSend( msg.str()); 1744 | } 1745 | 1746 | void EClientSocketBase::reqIds( int numIds) 1747 | { 1748 | // not connected? 1749 | if( !m_connected) { 1750 | m_pEWrapper->error( numIds, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1751 | return; 1752 | } 1753 | 1754 | std::ostringstream msg; 1755 | 1756 | const int VERSION = 1; 1757 | 1758 | // send req open orders msg 1759 | ENCODE_FIELD( REQ_IDS); 1760 | ENCODE_FIELD( VERSION); 1761 | ENCODE_FIELD( numIds); 1762 | 1763 | bufferedSend( msg.str()); 1764 | } 1765 | 1766 | void EClientSocketBase::reqNewsBulletins(bool allMsgs) 1767 | { 1768 | // not connected? 1769 | if( !m_connected) { 1770 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1771 | return; 1772 | } 1773 | 1774 | std::ostringstream msg; 1775 | 1776 | const int VERSION = 1; 1777 | 1778 | // send req news bulletins msg 1779 | ENCODE_FIELD( REQ_NEWS_BULLETINS); 1780 | ENCODE_FIELD( VERSION); 1781 | ENCODE_FIELD( allMsgs); 1782 | 1783 | bufferedSend( msg.str()); 1784 | } 1785 | 1786 | void EClientSocketBase::cancelNewsBulletins() 1787 | { 1788 | // not connected? 1789 | if( !m_connected) { 1790 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1791 | return; 1792 | } 1793 | 1794 | std::ostringstream msg; 1795 | 1796 | const int VERSION = 1; 1797 | 1798 | // send req news bulletins msg 1799 | ENCODE_FIELD( CANCEL_NEWS_BULLETINS); 1800 | ENCODE_FIELD( VERSION); 1801 | 1802 | bufferedSend( msg.str()); 1803 | } 1804 | 1805 | void EClientSocketBase::setServerLogLevel(int logLevel) 1806 | { 1807 | // not connected? 1808 | if( !m_connected) { 1809 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1810 | return; 1811 | } 1812 | 1813 | std::ostringstream msg; 1814 | 1815 | const int VERSION = 1; 1816 | 1817 | // send the set server logging level message 1818 | ENCODE_FIELD( SET_SERVER_LOGLEVEL); 1819 | ENCODE_FIELD( VERSION); 1820 | ENCODE_FIELD( logLevel); 1821 | 1822 | bufferedSend( msg.str()); 1823 | } 1824 | 1825 | void EClientSocketBase::reqManagedAccts() 1826 | { 1827 | // not connected? 1828 | if( !m_connected) { 1829 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1830 | return; 1831 | } 1832 | 1833 | std::ostringstream msg; 1834 | 1835 | const int VERSION = 1; 1836 | 1837 | // send req FA managed accounts msg 1838 | ENCODE_FIELD( REQ_MANAGED_ACCTS); 1839 | ENCODE_FIELD( VERSION); 1840 | 1841 | bufferedSend( msg.str()); 1842 | } 1843 | 1844 | 1845 | void EClientSocketBase::requestFA(faDataType pFaDataType) 1846 | { 1847 | // not connected? 1848 | if( !m_connected) { 1849 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1850 | return; 1851 | } 1852 | 1853 | // Not needed anymore validation 1854 | //if( m_serverVersion < 13) { 1855 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 1856 | // return; 1857 | //} 1858 | 1859 | std::ostringstream msg; 1860 | 1861 | const int VERSION = 1; 1862 | 1863 | ENCODE_FIELD( REQ_FA); 1864 | ENCODE_FIELD( VERSION); 1865 | ENCODE_FIELD( (int)pFaDataType); 1866 | 1867 | bufferedSend( msg.str()); 1868 | } 1869 | 1870 | void EClientSocketBase::replaceFA(faDataType pFaDataType, const IBString& cxml) 1871 | { 1872 | // not connected? 1873 | if( !m_connected) { 1874 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1875 | return; 1876 | } 1877 | 1878 | // Not needed anymore validation 1879 | //if( m_serverVersion < 13) { 1880 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 1881 | // return; 1882 | //} 1883 | 1884 | std::ostringstream msg; 1885 | 1886 | const int VERSION = 1; 1887 | 1888 | ENCODE_FIELD( REPLACE_FA); 1889 | ENCODE_FIELD( VERSION); 1890 | ENCODE_FIELD( (int)pFaDataType); 1891 | ENCODE_FIELD( cxml); 1892 | 1893 | bufferedSend( msg.str()); 1894 | } 1895 | 1896 | 1897 | 1898 | void EClientSocketBase::exerciseOptions( TickerId tickerId, const Contract &contract, 1899 | int exerciseAction, int exerciseQuantity, 1900 | const IBString& account, int override) 1901 | { 1902 | // not connected? 1903 | if( !m_connected) { 1904 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1905 | return; 1906 | } 1907 | 1908 | // Not needed anymore validation 1909 | //if( m_serverVersion < 21) { 1910 | // m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 1911 | // return; 1912 | //} 1913 | 1914 | std::ostringstream msg; 1915 | 1916 | const int VERSION = 1; 1917 | 1918 | ENCODE_FIELD( EXERCISE_OPTIONS); 1919 | ENCODE_FIELD( VERSION); 1920 | ENCODE_FIELD( tickerId); 1921 | 1922 | // send contract fields 1923 | ENCODE_FIELD( contract.symbol); 1924 | ENCODE_FIELD( contract.secType); 1925 | ENCODE_FIELD( contract.expiry); 1926 | ENCODE_FIELD( contract.strike); 1927 | ENCODE_FIELD( contract.right); 1928 | ENCODE_FIELD( contract.multiplier); 1929 | ENCODE_FIELD( contract.exchange); 1930 | ENCODE_FIELD( contract.currency); 1931 | ENCODE_FIELD( contract.localSymbol); 1932 | ENCODE_FIELD( exerciseAction); 1933 | ENCODE_FIELD( exerciseQuantity); 1934 | ENCODE_FIELD( account); 1935 | ENCODE_FIELD( override); 1936 | 1937 | bufferedSend( msg.str()); 1938 | } 1939 | 1940 | void EClientSocketBase::reqGlobalCancel() 1941 | { 1942 | // not connected? 1943 | if( !m_connected) { 1944 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1945 | return; 1946 | } 1947 | 1948 | if (m_serverVersion < MIN_SERVER_VER_REQ_GLOBAL_CANCEL) { 1949 | m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1950 | " It does not support globalCancel requests."); 1951 | return; 1952 | } 1953 | 1954 | std::ostringstream msg; 1955 | 1956 | const int VERSION = 1; 1957 | 1958 | // send current time req 1959 | ENCODE_FIELD( REQ_GLOBAL_CANCEL); 1960 | ENCODE_FIELD( VERSION); 1961 | 1962 | bufferedSend( msg.str()); 1963 | } 1964 | 1965 | void EClientSocketBase::reqMarketDataType( int marketDataType) 1966 | { 1967 | // not connected? 1968 | if( !m_connected) { 1969 | m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg()); 1970 | return; 1971 | } 1972 | 1973 | if( m_serverVersion < MIN_SERVER_VER_REQ_MARKET_DATA_TYPE) { 1974 | m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() + 1975 | " It does not support market data type requests."); 1976 | return; 1977 | } 1978 | 1979 | std::ostringstream msg; 1980 | 1981 | const int VERSION = 1; 1982 | 1983 | ENCODE_FIELD( REQ_MARKET_DATA_TYPE); 1984 | ENCODE_FIELD( VERSION); 1985 | ENCODE_FIELD( marketDataType); 1986 | 1987 | bufferedSend( msg.str()); 1988 | } 1989 | 1990 | int EClientSocketBase::sendBufferedData() 1991 | { 1992 | if( m_outBuffer.empty()) 1993 | return 0; 1994 | 1995 | int nResult = send( &m_outBuffer[0], m_outBuffer.size()); 1996 | if( nResult <= 0) { 1997 | return nResult; 1998 | } 1999 | CleanupBuffer( m_outBuffer, nResult); 2000 | return nResult; 2001 | } 2002 | 2003 | int EClientSocketBase::bufferedSend(const char* buf, size_t sz) 2004 | { 2005 | if( sz <= 0) 2006 | return 0; 2007 | 2008 | if( !m_outBuffer.empty()) { 2009 | m_outBuffer.insert( m_outBuffer.end(), buf, buf + sz); 2010 | return sendBufferedData(); 2011 | } 2012 | 2013 | int nResult = send(buf, sz); 2014 | 2015 | if( nResult < (int)sz) { 2016 | int sent = (std::max)( nResult, 0); 2017 | m_outBuffer.insert( m_outBuffer.end(), buf + sent, buf + sz); 2018 | } 2019 | 2020 | return nResult; 2021 | } 2022 | 2023 | int EClientSocketBase::bufferedSend(const std::string& msg) 2024 | { 2025 | return bufferedSend( msg.data(), msg.size()); 2026 | } 2027 | 2028 | int EClientSocketBase::bufferedRead() 2029 | { 2030 | char buf[8192]; 2031 | int nResult = receive( buf, sizeof(buf)); 2032 | 2033 | if( nResult > 0) { 2034 | m_inBuffer.insert( m_inBuffer.end(), &buf[0], &buf[0] + nResult); 2035 | } 2036 | 2037 | return nResult; 2038 | } 2039 | 2040 | bool EClientSocketBase::checkMessages() 2041 | { 2042 | if( !isSocketOK()) 2043 | return false; 2044 | 2045 | if( bufferedRead() <= 0) {; 2046 | return false; 2047 | } 2048 | 2049 | const char* beginPtr = &m_inBuffer[0]; 2050 | const char* ptr = beginPtr; 2051 | const char* endPtr = ptr + m_inBuffer.size(); 2052 | 2053 | try { 2054 | while( (m_connected ? processMsg( ptr, endPtr) 2055 | : processConnectAck( ptr, endPtr)) > 0) { 2056 | if( (ptr - beginPtr) >= (int)m_inBuffer.size()) 2057 | break; 2058 | } 2059 | } 2060 | catch (...) { 2061 | CleanupBuffer( m_inBuffer, (ptr - beginPtr)); 2062 | throw; 2063 | } 2064 | 2065 | CleanupBuffer( m_inBuffer, (ptr - beginPtr)); 2066 | return true; 2067 | } 2068 | 2069 | int EClientSocketBase::processConnectAck(const char*& beginPtr, const char* endPtr) 2070 | { 2071 | // process a connect Ack message from the buffer; 2072 | // return number of bytes consumed 2073 | assert( beginPtr && beginPtr < endPtr); 2074 | 2075 | try { 2076 | 2077 | const char* ptr = beginPtr; 2078 | 2079 | // check server version 2080 | DECODE_FIELD( m_serverVersion); 2081 | if( m_serverVersion >= 20) { 2082 | DECODE_FIELD( m_TwsTime); 2083 | } 2084 | 2085 | if( m_serverVersion < SERVER_VERSION) { 2086 | eDisconnect(); 2087 | m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg()); 2088 | return -1; 2089 | } 2090 | 2091 | // send the clientId 2092 | if( m_serverVersion >= 3) { 2093 | std::ostringstream msg; 2094 | ENCODE_FIELD( m_clientId); 2095 | bufferedSend( msg.str()); 2096 | } 2097 | 2098 | m_connected = true; 2099 | 2100 | // That would be the place to notify client 2101 | // that we are fully connected 2102 | // e.g: m_pEWrapper->connected(); 2103 | 2104 | int processed = ptr - beginPtr; 2105 | beginPtr = ptr; 2106 | return processed; 2107 | } 2108 | #ifdef _MSC_VER 2109 | catch( CException* e) { 2110 | m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 2111 | SOCKET_EXCEPTION.msg() + errMsg(e)); 2112 | } 2113 | #endif 2114 | 2115 | catch( std::exception e) { 2116 | m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 2117 | SOCKET_EXCEPTION.msg() + errMsg( e) ); 2118 | } 2119 | return 0; 2120 | } 2121 | 2122 | int EClientSocketBase::processMsg(const char*& beginPtr, const char* endPtr) 2123 | { 2124 | // process a single message from the buffer; 2125 | // return number of bytes consumed 2126 | 2127 | assert( beginPtr && beginPtr < endPtr); 2128 | 2129 | try { 2130 | 2131 | const char* ptr = beginPtr; 2132 | 2133 | int msgId; 2134 | DECODE_FIELD( msgId); 2135 | 2136 | switch( msgId) { 2137 | case TICK_PRICE: 2138 | { 2139 | int version; 2140 | int tickerId; 2141 | int tickTypeInt; 2142 | double price; 2143 | 2144 | int size; 2145 | int canAutoExecute; 2146 | 2147 | DECODE_FIELD( version); 2148 | DECODE_FIELD( tickerId); 2149 | DECODE_FIELD( tickTypeInt); 2150 | DECODE_FIELD( price); 2151 | 2152 | DECODE_FIELD( size); // ver 2 field 2153 | DECODE_FIELD( canAutoExecute); // ver 3 field 2154 | 2155 | m_pEWrapper->tickPrice( tickerId, (TickType)tickTypeInt, price, canAutoExecute); 2156 | 2157 | // process ver 2 fields 2158 | { 2159 | TickType sizeTickType = NOT_SET; 2160 | switch( (TickType)tickTypeInt) { 2161 | case BID: 2162 | sizeTickType = BID_SIZE; 2163 | break; 2164 | case ASK: 2165 | sizeTickType = ASK_SIZE; 2166 | break; 2167 | case LAST: 2168 | sizeTickType = LAST_SIZE; 2169 | break; 2170 | } 2171 | if( sizeTickType != NOT_SET) 2172 | m_pEWrapper->tickSize( tickerId, sizeTickType, size); 2173 | } 2174 | 2175 | break; 2176 | } 2177 | 2178 | case TICK_SIZE: 2179 | { 2180 | int version; 2181 | int tickerId; 2182 | int tickTypeInt; 2183 | int size; 2184 | 2185 | DECODE_FIELD( version); 2186 | DECODE_FIELD( tickerId); 2187 | DECODE_FIELD( tickTypeInt); 2188 | DECODE_FIELD( size); 2189 | 2190 | m_pEWrapper->tickSize( tickerId, (TickType)tickTypeInt, size); 2191 | break; 2192 | } 2193 | 2194 | case TICK_OPTION_COMPUTATION: 2195 | { 2196 | int version; 2197 | int tickerId; 2198 | int tickTypeInt; 2199 | double impliedVol; 2200 | double delta; 2201 | 2202 | double optPrice = DBL_MAX; 2203 | double pvDividend = DBL_MAX; 2204 | 2205 | double gamma = DBL_MAX; 2206 | double vega = DBL_MAX; 2207 | double theta = DBL_MAX; 2208 | double undPrice = DBL_MAX; 2209 | 2210 | DECODE_FIELD( version); 2211 | DECODE_FIELD( tickerId); 2212 | DECODE_FIELD( tickTypeInt); 2213 | 2214 | DECODE_FIELD( impliedVol); 2215 | DECODE_FIELD( delta); 2216 | 2217 | if( impliedVol < 0) { // -1 is the "not computed" indicator 2218 | impliedVol = DBL_MAX; 2219 | } 2220 | if( delta > 1 || delta < -1) { // -2 is the "not computed" indicator 2221 | delta = DBL_MAX; 2222 | } 2223 | 2224 | if( version >= 6 || tickTypeInt == MODEL_OPTION) { // introduced in version == 5 2225 | 2226 | DECODE_FIELD( optPrice); 2227 | DECODE_FIELD( pvDividend); 2228 | 2229 | if( optPrice < 0) { // -1 is the "not computed" indicator 2230 | optPrice = DBL_MAX; 2231 | } 2232 | if( pvDividend < 0) { // -1 is the "not computed" indicator 2233 | pvDividend = DBL_MAX; 2234 | } 2235 | } 2236 | if( version >= 6) { 2237 | 2238 | DECODE_FIELD( gamma); 2239 | DECODE_FIELD( vega); 2240 | DECODE_FIELD( theta); 2241 | DECODE_FIELD( undPrice); 2242 | 2243 | if( gamma > 1 || gamma < -1) { // -2 is the "not yet computed" indicator 2244 | gamma = DBL_MAX; 2245 | } 2246 | if( vega > 1 || vega < -1) { // -2 is the "not yet computed" indicator 2247 | vega = DBL_MAX; 2248 | } 2249 | if( theta > 1 || theta < -1) { // -2 is the "not yet computed" indicator 2250 | theta = DBL_MAX; 2251 | } 2252 | if( undPrice < 0) { // -1 is the "not computed" indicator 2253 | undPrice = DBL_MAX; 2254 | } 2255 | } 2256 | m_pEWrapper->tickOptionComputation( tickerId, (TickType)tickTypeInt, 2257 | impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice); 2258 | 2259 | break; 2260 | } 2261 | 2262 | case TICK_GENERIC: 2263 | { 2264 | int version; 2265 | int tickerId; 2266 | int tickTypeInt; 2267 | double value; 2268 | 2269 | DECODE_FIELD( version); 2270 | DECODE_FIELD( tickerId); 2271 | DECODE_FIELD( tickTypeInt); 2272 | DECODE_FIELD( value); 2273 | 2274 | m_pEWrapper->tickGeneric( tickerId, (TickType)tickTypeInt, value); 2275 | break; 2276 | } 2277 | 2278 | case TICK_STRING: 2279 | { 2280 | int version; 2281 | int tickerId; 2282 | int tickTypeInt; 2283 | IBString value; 2284 | 2285 | DECODE_FIELD( version); 2286 | DECODE_FIELD( tickerId); 2287 | DECODE_FIELD( tickTypeInt); 2288 | DECODE_FIELD( value); 2289 | 2290 | m_pEWrapper->tickString( tickerId, (TickType)tickTypeInt, value); 2291 | break; 2292 | } 2293 | 2294 | case TICK_EFP: 2295 | { 2296 | int version; 2297 | int tickerId; 2298 | int tickTypeInt; 2299 | double basisPoints; 2300 | IBString formattedBasisPoints; 2301 | double impliedFuturesPrice; 2302 | int holdDays; 2303 | IBString futureExpiry; 2304 | double dividendImpact; 2305 | double dividendsToExpiry; 2306 | 2307 | DECODE_FIELD( version); 2308 | DECODE_FIELD( tickerId); 2309 | DECODE_FIELD( tickTypeInt); 2310 | DECODE_FIELD( basisPoints); 2311 | DECODE_FIELD( formattedBasisPoints); 2312 | DECODE_FIELD( impliedFuturesPrice); 2313 | DECODE_FIELD( holdDays); 2314 | DECODE_FIELD( futureExpiry); 2315 | DECODE_FIELD( dividendImpact); 2316 | DECODE_FIELD( dividendsToExpiry); 2317 | 2318 | m_pEWrapper->tickEFP( tickerId, (TickType)tickTypeInt, basisPoints, formattedBasisPoints, 2319 | impliedFuturesPrice, holdDays, futureExpiry, dividendImpact, dividendsToExpiry); 2320 | break; 2321 | } 2322 | 2323 | case ORDER_STATUS: 2324 | { 2325 | int version; 2326 | int orderId; 2327 | IBString status; 2328 | int filled; 2329 | int remaining; 2330 | double avgFillPrice; 2331 | int permId; 2332 | int parentId; 2333 | double lastFillPrice; 2334 | int clientId; 2335 | IBString whyHeld; 2336 | 2337 | DECODE_FIELD( version); 2338 | DECODE_FIELD( orderId); 2339 | DECODE_FIELD( status); 2340 | DECODE_FIELD( filled); 2341 | DECODE_FIELD( remaining); 2342 | DECODE_FIELD( avgFillPrice); 2343 | 2344 | DECODE_FIELD( permId); // ver 2 field 2345 | DECODE_FIELD( parentId); // ver 3 field 2346 | DECODE_FIELD( lastFillPrice); // ver 4 field 2347 | DECODE_FIELD( clientId); // ver 5 field 2348 | DECODE_FIELD( whyHeld); // ver 6 field 2349 | 2350 | m_pEWrapper->orderStatus( orderId, status, filled, remaining, 2351 | avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld); 2352 | 2353 | break; 2354 | } 2355 | 2356 | case ERR_MSG: 2357 | { 2358 | int version; 2359 | int id; // ver 2 field 2360 | int errorCode; // ver 2 field 2361 | IBString errorMsg; 2362 | 2363 | DECODE_FIELD( version); 2364 | DECODE_FIELD( id); 2365 | DECODE_FIELD( errorCode); 2366 | DECODE_FIELD( errorMsg); 2367 | 2368 | m_pEWrapper->error( id, errorCode, errorMsg); 2369 | break; 2370 | } 2371 | 2372 | case OPEN_ORDER: 2373 | { 2374 | // read version 2375 | int version; 2376 | DECODE_FIELD( version); 2377 | 2378 | // read order id 2379 | Order order; 2380 | DECODE_FIELD( order.orderId); 2381 | 2382 | // read contract fields 2383 | Contract contract; 2384 | DECODE_FIELD( contract.conId); // ver 17 field 2385 | DECODE_FIELD( contract.symbol); 2386 | DECODE_FIELD( contract.secType); 2387 | DECODE_FIELD( contract.expiry); 2388 | DECODE_FIELD( contract.strike); 2389 | DECODE_FIELD( contract.right); 2390 | DECODE_FIELD( contract.exchange); 2391 | DECODE_FIELD( contract.currency); 2392 | DECODE_FIELD( contract.localSymbol); // ver 2 field 2393 | 2394 | // read order fields 2395 | DECODE_FIELD( order.action); 2396 | DECODE_FIELD( order.totalQuantity); 2397 | DECODE_FIELD( order.orderType); 2398 | DECODE_FIELD( order.lmtPrice); 2399 | DECODE_FIELD( order.auxPrice); 2400 | DECODE_FIELD( order.tif); 2401 | DECODE_FIELD( order.ocaGroup); 2402 | DECODE_FIELD( order.account); 2403 | DECODE_FIELD( order.openClose); 2404 | 2405 | int orderOriginInt; 2406 | DECODE_FIELD( orderOriginInt); 2407 | order.origin = (Origin)orderOriginInt; 2408 | 2409 | DECODE_FIELD( order.orderRef); 2410 | DECODE_FIELD( order.clientId); // ver 3 field 2411 | DECODE_FIELD( order.permId); // ver 4 field 2412 | 2413 | //if( version < 18) { 2414 | // // will never happen 2415 | // /* order.ignoreRth = */ readBoolFromInt(); 2416 | //} 2417 | 2418 | DECODE_FIELD( order.outsideRth); // ver 18 field 2419 | DECODE_FIELD( order.hidden); // ver 4 field 2420 | DECODE_FIELD( order.discretionaryAmt); // ver 4 field 2421 | DECODE_FIELD( order.goodAfterTime); // ver 5 field 2422 | 2423 | { 2424 | IBString sharesAllocation; 2425 | DECODE_FIELD( sharesAllocation); // deprecated ver 6 field 2426 | } 2427 | 2428 | DECODE_FIELD( order.faGroup); // ver 7 field 2429 | DECODE_FIELD( order.faMethod); // ver 7 field 2430 | DECODE_FIELD( order.faPercentage); // ver 7 field 2431 | DECODE_FIELD( order.faProfile); // ver 7 field 2432 | 2433 | DECODE_FIELD( order.goodTillDate); // ver 8 field 2434 | 2435 | DECODE_FIELD( order.rule80A); // ver 9 field 2436 | DECODE_FIELD( order.percentOffset); // ver 9 field 2437 | DECODE_FIELD( order.settlingFirm); // ver 9 field 2438 | DECODE_FIELD( order.shortSaleSlot); // ver 9 field 2439 | DECODE_FIELD( order.designatedLocation); // ver 9 field 2440 | if( m_serverVersion == MIN_SERVER_VER_SSHORTX_OLD){ 2441 | int exemptCode; 2442 | DECODE_FIELD( exemptCode); 2443 | } 2444 | else if( version >= 23){ 2445 | DECODE_FIELD( order.exemptCode); 2446 | } 2447 | DECODE_FIELD( order.auctionStrategy); // ver 9 field 2448 | DECODE_FIELD( order.startingPrice); // ver 9 field 2449 | DECODE_FIELD( order.stockRefPrice); // ver 9 field 2450 | DECODE_FIELD( order.delta); // ver 9 field 2451 | DECODE_FIELD( order.stockRangeLower); // ver 9 field 2452 | DECODE_FIELD( order.stockRangeUpper); // ver 9 field 2453 | DECODE_FIELD( order.displaySize); // ver 9 field 2454 | 2455 | //if( version < 18) { 2456 | // // will never happen 2457 | // /* order.rthOnly = */ readBoolFromInt(); 2458 | //} 2459 | 2460 | DECODE_FIELD( order.blockOrder); // ver 9 field 2461 | DECODE_FIELD( order.sweepToFill); // ver 9 field 2462 | DECODE_FIELD( order.allOrNone); // ver 9 field 2463 | DECODE_FIELD( order.minQty); // ver 9 field 2464 | DECODE_FIELD( order.ocaType); // ver 9 field 2465 | DECODE_FIELD( order.eTradeOnly); // ver 9 field 2466 | DECODE_FIELD( order.firmQuoteOnly); // ver 9 field 2467 | DECODE_FIELD( order.nbboPriceCap); // ver 9 field 2468 | 2469 | DECODE_FIELD( order.parentId); // ver 10 field 2470 | DECODE_FIELD( order.triggerMethod); // ver 10 field 2471 | 2472 | DECODE_FIELD( order.volatility); // ver 11 field 2473 | DECODE_FIELD( order.volatilityType); // ver 11 field 2474 | DECODE_FIELD( order.deltaNeutralOrderType); // ver 11 field (had a hack for ver 11) 2475 | DECODE_FIELD( order.deltaNeutralAuxPrice); // ver 12 field 2476 | 2477 | if (version >= 27 && !IsEmpty(order.deltaNeutralOrderType)) { 2478 | DECODE_FIELD( order.deltaNeutralConId); 2479 | DECODE_FIELD( order.deltaNeutralSettlingFirm); 2480 | DECODE_FIELD( order.deltaNeutralClearingAccount); 2481 | DECODE_FIELD( order.deltaNeutralClearingIntent); 2482 | } 2483 | 2484 | DECODE_FIELD( order.continuousUpdate); // ver 11 field 2485 | 2486 | // will never happen 2487 | //if( m_serverVersion == 26) { 2488 | // order.stockRangeLower = readDouble(); 2489 | // order.stockRangeUpper = readDouble(); 2490 | //} 2491 | 2492 | DECODE_FIELD( order.referencePriceType); // ver 11 field 2493 | 2494 | DECODE_FIELD( order.trailStopPrice); // ver 13 field 2495 | 2496 | DECODE_FIELD( order.basisPoints); // ver 14 field 2497 | DECODE_FIELD( order.basisPointsType); // ver 14 field 2498 | DECODE_FIELD( contract.comboLegsDescrip); // ver 14 field 2499 | 2500 | if (version >= 26) { 2501 | int smartComboRoutingParamsCount = 0; 2502 | DECODE_FIELD( smartComboRoutingParamsCount); 2503 | if( smartComboRoutingParamsCount > 0) { 2504 | Order::TagValueListSPtr smartComboRoutingParams( new Order::TagValueList); 2505 | smartComboRoutingParams->reserve( smartComboRoutingParamsCount); 2506 | for( int i = 0; i < smartComboRoutingParamsCount; ++i) { 2507 | TagValueSPtr tagValue( new TagValue()); 2508 | DECODE_FIELD( tagValue->tag); 2509 | DECODE_FIELD( tagValue->value); 2510 | smartComboRoutingParams->push_back( tagValue); 2511 | } 2512 | order.smartComboRoutingParams = smartComboRoutingParams; 2513 | } 2514 | } 2515 | 2516 | if( version >= 20) { 2517 | DECODE_FIELD_MAX( order.scaleInitLevelSize); 2518 | DECODE_FIELD_MAX( order.scaleSubsLevelSize); 2519 | } 2520 | else { 2521 | // ver 15 fields 2522 | int notSuppScaleNumComponents = 0; 2523 | DECODE_FIELD_MAX( notSuppScaleNumComponents); 2524 | DECODE_FIELD_MAX( order.scaleInitLevelSize); // scaleComponectSize 2525 | } 2526 | DECODE_FIELD_MAX( order.scalePriceIncrement); // ver 15 field 2527 | 2528 | if( version >= 24) { 2529 | DECODE_FIELD( order.hedgeType); 2530 | if( !IsEmpty(order.hedgeType)) { 2531 | DECODE_FIELD( order.hedgeParam); 2532 | } 2533 | } 2534 | 2535 | if( version >= 25) { 2536 | DECODE_FIELD( order.optOutSmartRouting); 2537 | } 2538 | 2539 | DECODE_FIELD( order.clearingAccount); // ver 19 field 2540 | DECODE_FIELD( order.clearingIntent); // ver 19 field 2541 | 2542 | if( version >= 22) { 2543 | DECODE_FIELD( order.notHeld); 2544 | } 2545 | 2546 | UnderComp underComp; 2547 | if( version >= 20) { 2548 | bool underCompPresent = false; 2549 | DECODE_FIELD(underCompPresent); 2550 | if( underCompPresent){ 2551 | DECODE_FIELD(underComp.conId); 2552 | DECODE_FIELD(underComp.delta); 2553 | DECODE_FIELD(underComp.price); 2554 | contract.underComp = &underComp; 2555 | } 2556 | } 2557 | 2558 | 2559 | if( version >= 21) { 2560 | DECODE_FIELD( order.algoStrategy); 2561 | if( !IsEmpty(order.algoStrategy)) { 2562 | int algoParamsCount = 0; 2563 | DECODE_FIELD( algoParamsCount); 2564 | if( algoParamsCount > 0) { 2565 | Order::TagValueListSPtr algoParams( new Order::TagValueList); 2566 | algoParams->reserve( algoParamsCount); 2567 | for( int i = 0; i < algoParamsCount; ++i) { 2568 | TagValueSPtr tagValue( new TagValue()); 2569 | DECODE_FIELD( tagValue->tag); 2570 | DECODE_FIELD( tagValue->value); 2571 | algoParams->push_back( tagValue); 2572 | } 2573 | order.algoParams = algoParams; 2574 | } 2575 | } 2576 | } 2577 | 2578 | OrderState orderState; 2579 | 2580 | DECODE_FIELD( order.whatIf); // ver 16 field 2581 | 2582 | DECODE_FIELD( orderState.status); // ver 16 field 2583 | DECODE_FIELD( orderState.initMargin); // ver 16 field 2584 | DECODE_FIELD( orderState.maintMargin); // ver 16 field 2585 | DECODE_FIELD( orderState.equityWithLoan); // ver 16 field 2586 | DECODE_FIELD_MAX( orderState.commission); // ver 16 field 2587 | DECODE_FIELD_MAX( orderState.minCommission); // ver 16 field 2588 | DECODE_FIELD_MAX( orderState.maxCommission); // ver 16 field 2589 | DECODE_FIELD( orderState.commissionCurrency); // ver 16 field 2590 | DECODE_FIELD( orderState.warningText); // ver 16 field 2591 | 2592 | m_pEWrapper->openOrder( (OrderId)order.orderId, contract, order, orderState); 2593 | break; 2594 | } 2595 | 2596 | case ACCT_VALUE: 2597 | { 2598 | int version; 2599 | IBString key; 2600 | IBString val; 2601 | IBString cur; 2602 | IBString accountName; 2603 | 2604 | DECODE_FIELD( version); 2605 | DECODE_FIELD( key); 2606 | DECODE_FIELD( val); 2607 | DECODE_FIELD( cur); 2608 | DECODE_FIELD( accountName); // ver 2 field 2609 | 2610 | m_pEWrapper->updateAccountValue( key, val, cur, accountName); 2611 | break; 2612 | } 2613 | 2614 | case PORTFOLIO_VALUE: 2615 | { 2616 | // decode version 2617 | int version; 2618 | DECODE_FIELD( version); 2619 | 2620 | // read contract fields 2621 | Contract contract; 2622 | DECODE_FIELD( contract.conId); // ver 6 field 2623 | DECODE_FIELD( contract.symbol); 2624 | DECODE_FIELD( contract.secType); 2625 | DECODE_FIELD( contract.expiry); 2626 | DECODE_FIELD( contract.strike); 2627 | DECODE_FIELD( contract.right); 2628 | 2629 | if( version >= 7) { 2630 | DECODE_FIELD( contract.multiplier); 2631 | DECODE_FIELD( contract.primaryExchange); 2632 | } 2633 | 2634 | DECODE_FIELD( contract.currency); 2635 | DECODE_FIELD( contract.localSymbol); // ver 2 field 2636 | 2637 | int position; 2638 | double marketPrice; 2639 | double marketValue; 2640 | double averageCost; 2641 | double unrealizedPNL; 2642 | double realizedPNL; 2643 | 2644 | DECODE_FIELD( position); 2645 | DECODE_FIELD( marketPrice); 2646 | DECODE_FIELD( marketValue); 2647 | DECODE_FIELD( averageCost); // ver 3 field 2648 | DECODE_FIELD( unrealizedPNL); // ver 3 field 2649 | DECODE_FIELD( realizedPNL); // ver 3 field 2650 | 2651 | IBString accountName; 2652 | DECODE_FIELD( accountName); // ver 4 field 2653 | 2654 | if( version == 6 && serverVersion() == 39) { 2655 | DECODE_FIELD( contract.primaryExchange); 2656 | } 2657 | 2658 | m_pEWrapper->updatePortfolio( contract, 2659 | position, marketPrice, marketValue, averageCost, 2660 | unrealizedPNL, realizedPNL, accountName); 2661 | 2662 | break; 2663 | } 2664 | 2665 | case ACCT_UPDATE_TIME: 2666 | { 2667 | int version; 2668 | IBString accountTime; 2669 | 2670 | DECODE_FIELD( version); 2671 | DECODE_FIELD( accountTime); 2672 | 2673 | m_pEWrapper->updateAccountTime( accountTime); 2674 | break; 2675 | } 2676 | 2677 | case NEXT_VALID_ID: 2678 | { 2679 | int version; 2680 | int orderId; 2681 | 2682 | DECODE_FIELD( version); 2683 | DECODE_FIELD( orderId); 2684 | 2685 | m_pEWrapper->nextValidId(orderId); 2686 | break; 2687 | } 2688 | 2689 | case CONTRACT_DATA: 2690 | { 2691 | int version; 2692 | DECODE_FIELD( version); 2693 | 2694 | int reqId = -1; 2695 | if( version >= 3) { 2696 | DECODE_FIELD( reqId); 2697 | } 2698 | 2699 | ContractDetails contract; 2700 | DECODE_FIELD( contract.summary.symbol); 2701 | DECODE_FIELD( contract.summary.secType); 2702 | DECODE_FIELD( contract.summary.expiry); 2703 | DECODE_FIELD( contract.summary.strike); 2704 | DECODE_FIELD( contract.summary.right); 2705 | DECODE_FIELD( contract.summary.exchange); 2706 | DECODE_FIELD( contract.summary.currency); 2707 | DECODE_FIELD( contract.summary.localSymbol); 2708 | DECODE_FIELD( contract.marketName); 2709 | DECODE_FIELD( contract.tradingClass); 2710 | DECODE_FIELD( contract.summary.conId); 2711 | DECODE_FIELD( contract.minTick); 2712 | DECODE_FIELD( contract.summary.multiplier); 2713 | DECODE_FIELD( contract.orderTypes); 2714 | DECODE_FIELD( contract.validExchanges); 2715 | DECODE_FIELD( contract.priceMagnifier); // ver 2 field 2716 | if( version >= 4) { 2717 | DECODE_FIELD( contract.underConId); 2718 | } 2719 | if( version >= 5) { 2720 | DECODE_FIELD( contract.longName); 2721 | DECODE_FIELD( contract.summary.primaryExchange); 2722 | } 2723 | if( version >= 6) { 2724 | DECODE_FIELD( contract.contractMonth); 2725 | DECODE_FIELD( contract.industry); 2726 | DECODE_FIELD( contract.category); 2727 | DECODE_FIELD( contract.subcategory); 2728 | DECODE_FIELD( contract.timeZoneId); 2729 | DECODE_FIELD( contract.tradingHours); 2730 | DECODE_FIELD( contract.liquidHours); 2731 | } 2732 | 2733 | m_pEWrapper->contractDetails( reqId, contract); 2734 | break; 2735 | } 2736 | 2737 | case BOND_CONTRACT_DATA: 2738 | { 2739 | int version; 2740 | DECODE_FIELD( version); 2741 | 2742 | int reqId = -1; 2743 | if( version >= 3) { 2744 | DECODE_FIELD( reqId); 2745 | } 2746 | 2747 | ContractDetails contract; 2748 | DECODE_FIELD( contract.summary.symbol); 2749 | DECODE_FIELD( contract.summary.secType); 2750 | DECODE_FIELD( contract.cusip); 2751 | DECODE_FIELD( contract.coupon); 2752 | DECODE_FIELD( contract.maturity); 2753 | DECODE_FIELD( contract.issueDate); 2754 | DECODE_FIELD( contract.ratings); 2755 | DECODE_FIELD( contract.bondType); 2756 | DECODE_FIELD( contract.couponType); 2757 | DECODE_FIELD( contract.convertible); 2758 | DECODE_FIELD( contract.callable); 2759 | DECODE_FIELD( contract.putable); 2760 | DECODE_FIELD( contract.descAppend); 2761 | DECODE_FIELD( contract.summary.exchange); 2762 | DECODE_FIELD( contract.summary.currency); 2763 | DECODE_FIELD( contract.marketName); 2764 | DECODE_FIELD( contract.tradingClass); 2765 | DECODE_FIELD( contract.summary.conId); 2766 | DECODE_FIELD( contract.minTick); 2767 | DECODE_FIELD( contract.orderTypes); 2768 | DECODE_FIELD( contract.validExchanges); 2769 | DECODE_FIELD( contract.nextOptionDate); // ver 2 field 2770 | DECODE_FIELD( contract.nextOptionType); // ver 2 field 2771 | DECODE_FIELD( contract.nextOptionPartial); // ver 2 field 2772 | DECODE_FIELD( contract.notes); // ver 2 field 2773 | if( version >= 4) { 2774 | DECODE_FIELD( contract.longName); 2775 | } 2776 | 2777 | m_pEWrapper->bondContractDetails( reqId, contract); 2778 | break; 2779 | } 2780 | 2781 | case EXECUTION_DATA: 2782 | { 2783 | int version; 2784 | DECODE_FIELD( version); 2785 | 2786 | int reqId = -1; 2787 | if( version >= 7) { 2788 | DECODE_FIELD(reqId); 2789 | } 2790 | 2791 | int orderId; 2792 | DECODE_FIELD( orderId); 2793 | 2794 | // decode contract fields 2795 | Contract contract; 2796 | DECODE_FIELD( contract.conId); // ver 5 field 2797 | DECODE_FIELD( contract.symbol); 2798 | DECODE_FIELD( contract.secType); 2799 | DECODE_FIELD( contract.expiry); 2800 | DECODE_FIELD( contract.strike); 2801 | DECODE_FIELD( contract.right); 2802 | DECODE_FIELD( contract.exchange); 2803 | DECODE_FIELD( contract.currency); 2804 | DECODE_FIELD( contract.localSymbol); 2805 | 2806 | // decode execution fields 2807 | Execution exec; 2808 | exec.orderId = orderId; 2809 | DECODE_FIELD( exec.execId); 2810 | DECODE_FIELD( exec.time); 2811 | DECODE_FIELD( exec.acctNumber); 2812 | DECODE_FIELD( exec.exchange); 2813 | DECODE_FIELD( exec.side); 2814 | DECODE_FIELD( exec.shares); 2815 | DECODE_FIELD( exec.price); 2816 | DECODE_FIELD( exec.permId); // ver 2 field 2817 | DECODE_FIELD( exec.clientId); // ver 3 field 2818 | DECODE_FIELD( exec.liquidation); // ver 4 field 2819 | 2820 | if( version >= 6) { 2821 | DECODE_FIELD( exec.cumQty); 2822 | DECODE_FIELD( exec.avgPrice); 2823 | } 2824 | 2825 | if( version >= 8) { 2826 | DECODE_FIELD( exec.orderRef); 2827 | } 2828 | 2829 | m_pEWrapper->execDetails( reqId, contract, exec); 2830 | break; 2831 | } 2832 | 2833 | case MARKET_DEPTH: 2834 | { 2835 | int version; 2836 | int id; 2837 | int position; 2838 | int operation; 2839 | int side; 2840 | double price; 2841 | int size; 2842 | 2843 | DECODE_FIELD( version); 2844 | DECODE_FIELD( id); 2845 | DECODE_FIELD( position); 2846 | DECODE_FIELD( operation); 2847 | DECODE_FIELD( side); 2848 | DECODE_FIELD( price); 2849 | DECODE_FIELD( size); 2850 | 2851 | m_pEWrapper->updateMktDepth( id, position, operation, side, price, size); 2852 | break; 2853 | } 2854 | 2855 | case MARKET_DEPTH_L2: 2856 | { 2857 | int version; 2858 | int id; 2859 | int position; 2860 | IBString marketMaker; 2861 | int operation; 2862 | int side; 2863 | double price; 2864 | int size; 2865 | 2866 | DECODE_FIELD( version); 2867 | DECODE_FIELD( id); 2868 | DECODE_FIELD( position); 2869 | DECODE_FIELD( marketMaker); 2870 | DECODE_FIELD( operation); 2871 | DECODE_FIELD( side); 2872 | DECODE_FIELD( price); 2873 | DECODE_FIELD( size); 2874 | 2875 | m_pEWrapper->updateMktDepthL2( id, position, marketMaker, operation, side, 2876 | price, size); 2877 | 2878 | break; 2879 | } 2880 | 2881 | case NEWS_BULLETINS: 2882 | { 2883 | int version; 2884 | int msgId; 2885 | int msgType; 2886 | IBString newsMessage; 2887 | IBString originatingExch; 2888 | 2889 | DECODE_FIELD( version); 2890 | DECODE_FIELD( msgId); 2891 | DECODE_FIELD( msgType); 2892 | DECODE_FIELD( newsMessage); 2893 | DECODE_FIELD( originatingExch); 2894 | 2895 | m_pEWrapper->updateNewsBulletin( msgId, msgType, newsMessage, originatingExch); 2896 | break; 2897 | } 2898 | 2899 | case MANAGED_ACCTS: 2900 | { 2901 | int version; 2902 | IBString accountsList; 2903 | 2904 | DECODE_FIELD( version); 2905 | DECODE_FIELD( accountsList); 2906 | 2907 | m_pEWrapper->managedAccounts( accountsList); 2908 | break; 2909 | } 2910 | 2911 | case RECEIVE_FA: 2912 | { 2913 | int version; 2914 | int faDataTypeInt; 2915 | IBString cxml; 2916 | 2917 | DECODE_FIELD( version); 2918 | DECODE_FIELD( faDataTypeInt); 2919 | DECODE_FIELD( cxml); 2920 | 2921 | m_pEWrapper->receiveFA( (faDataType)faDataTypeInt, cxml); 2922 | break; 2923 | } 2924 | 2925 | case HISTORICAL_DATA: 2926 | { 2927 | int version; 2928 | int reqId; 2929 | IBString startDateStr; 2930 | IBString endDateStr; 2931 | 2932 | DECODE_FIELD( version); 2933 | DECODE_FIELD( reqId); 2934 | DECODE_FIELD( startDateStr); // ver 2 field 2935 | DECODE_FIELD( endDateStr); // ver 2 field 2936 | 2937 | int itemCount; 2938 | DECODE_FIELD( itemCount); 2939 | 2940 | typedef std::vector BarDataList; 2941 | BarDataList bars; 2942 | 2943 | bars.reserve( itemCount); 2944 | 2945 | for( int ctr = 0; ctr < itemCount; ++ctr) { 2946 | 2947 | BarData bar; 2948 | DECODE_FIELD( bar.date); 2949 | DECODE_FIELD( bar.open); 2950 | DECODE_FIELD( bar.high); 2951 | DECODE_FIELD( bar.low); 2952 | DECODE_FIELD( bar.close); 2953 | DECODE_FIELD( bar.volume); 2954 | DECODE_FIELD( bar.average); 2955 | DECODE_FIELD( bar.hasGaps); 2956 | DECODE_FIELD( bar.barCount); // ver 3 field 2957 | 2958 | bars.push_back(bar); 2959 | } 2960 | 2961 | assert( (int)bars.size() == itemCount); 2962 | 2963 | for( int ctr = 0; ctr < itemCount; ++ctr) { 2964 | 2965 | const BarData& bar = bars[ctr]; 2966 | m_pEWrapper->historicalData( reqId, bar.date, bar.open, bar.high, bar.low, 2967 | bar.close, bar.volume, bar.barCount, bar.average, 2968 | Compare(bar.hasGaps, "true") == 0); 2969 | } 2970 | 2971 | // send end of dataset marker 2972 | IBString finishedStr = IBString("finished-") + startDateStr + "-" + endDateStr; 2973 | m_pEWrapper->historicalData( reqId, finishedStr, -1, -1, -1, -1, -1, -1, -1, 0); 2974 | break; 2975 | } 2976 | 2977 | case SCANNER_DATA: 2978 | { 2979 | int version; 2980 | int tickerId; 2981 | 2982 | DECODE_FIELD( version); 2983 | DECODE_FIELD( tickerId); 2984 | 2985 | int numberOfElements; 2986 | DECODE_FIELD( numberOfElements); 2987 | 2988 | typedef std::vector ScanDataList; 2989 | ScanDataList scannerDataList; 2990 | 2991 | scannerDataList.reserve( numberOfElements); 2992 | 2993 | for( int ctr=0; ctr < numberOfElements; ++ctr) { 2994 | 2995 | ScanData data; 2996 | 2997 | DECODE_FIELD( data.rank); 2998 | DECODE_FIELD( data.contract.summary.conId); // ver 3 field 2999 | DECODE_FIELD( data.contract.summary.symbol); 3000 | DECODE_FIELD( data.contract.summary.secType); 3001 | DECODE_FIELD( data.contract.summary.expiry); 3002 | DECODE_FIELD( data.contract.summary.strike); 3003 | DECODE_FIELD( data.contract.summary.right); 3004 | DECODE_FIELD( data.contract.summary.exchange); 3005 | DECODE_FIELD( data.contract.summary.currency); 3006 | DECODE_FIELD( data.contract.summary.localSymbol); 3007 | DECODE_FIELD( data.contract.marketName); 3008 | DECODE_FIELD( data.contract.tradingClass); 3009 | DECODE_FIELD( data.distance); 3010 | DECODE_FIELD( data.benchmark); 3011 | DECODE_FIELD( data.projection); 3012 | DECODE_FIELD( data.legsStr); 3013 | 3014 | scannerDataList.push_back( data); 3015 | } 3016 | 3017 | assert( (int)scannerDataList.size() == numberOfElements); 3018 | 3019 | for( int ctr=0; ctr < numberOfElements; ++ctr) { 3020 | 3021 | const ScanData& data = scannerDataList[ctr]; 3022 | m_pEWrapper->scannerData( tickerId, data.rank, data.contract, 3023 | data.distance, data.benchmark, data.projection, data.legsStr); 3024 | } 3025 | 3026 | m_pEWrapper->scannerDataEnd( tickerId); 3027 | break; 3028 | } 3029 | 3030 | case SCANNER_PARAMETERS: 3031 | { 3032 | int version; 3033 | IBString xml; 3034 | 3035 | DECODE_FIELD( version); 3036 | DECODE_FIELD( xml); 3037 | 3038 | m_pEWrapper->scannerParameters( xml); 3039 | break; 3040 | } 3041 | 3042 | case CURRENT_TIME: 3043 | { 3044 | int version; 3045 | int time; 3046 | 3047 | DECODE_FIELD(version); 3048 | DECODE_FIELD(time); 3049 | 3050 | m_pEWrapper->currentTime( time); 3051 | break; 3052 | } 3053 | 3054 | case REAL_TIME_BARS: 3055 | { 3056 | int version; 3057 | int reqId; 3058 | int time; 3059 | double open; 3060 | double high; 3061 | double low; 3062 | double close; 3063 | int volume; 3064 | double average; 3065 | int count; 3066 | 3067 | DECODE_FIELD( version); 3068 | DECODE_FIELD( reqId); 3069 | DECODE_FIELD( time); 3070 | DECODE_FIELD( open); 3071 | DECODE_FIELD( high); 3072 | DECODE_FIELD( low); 3073 | DECODE_FIELD( close); 3074 | DECODE_FIELD( volume); 3075 | DECODE_FIELD( average); 3076 | DECODE_FIELD( count); 3077 | 3078 | m_pEWrapper->realtimeBar( reqId, time, open, high, low, close, 3079 | volume, average, count); 3080 | 3081 | break; 3082 | } 3083 | 3084 | case FUNDAMENTAL_DATA: 3085 | { 3086 | int version; 3087 | int reqId; 3088 | IBString data; 3089 | 3090 | DECODE_FIELD( version); 3091 | DECODE_FIELD( reqId); 3092 | DECODE_FIELD( data); 3093 | 3094 | m_pEWrapper->fundamentalData( reqId, data); 3095 | break; 3096 | } 3097 | 3098 | case CONTRACT_DATA_END: 3099 | { 3100 | int version; 3101 | int reqId; 3102 | 3103 | DECODE_FIELD( version); 3104 | DECODE_FIELD( reqId); 3105 | 3106 | m_pEWrapper->contractDetailsEnd( reqId); 3107 | break; 3108 | } 3109 | 3110 | case OPEN_ORDER_END: 3111 | { 3112 | int version; 3113 | 3114 | DECODE_FIELD( version); 3115 | 3116 | m_pEWrapper->openOrderEnd(); 3117 | break; 3118 | } 3119 | 3120 | case ACCT_DOWNLOAD_END: 3121 | { 3122 | int version; 3123 | IBString account; 3124 | 3125 | DECODE_FIELD( version); 3126 | DECODE_FIELD( account); 3127 | 3128 | m_pEWrapper->accountDownloadEnd( account); 3129 | break; 3130 | } 3131 | 3132 | case EXECUTION_DATA_END: 3133 | { 3134 | int version; 3135 | int reqId; 3136 | 3137 | DECODE_FIELD( version); 3138 | DECODE_FIELD( reqId); 3139 | 3140 | m_pEWrapper->execDetailsEnd( reqId); 3141 | break; 3142 | } 3143 | 3144 | case DELTA_NEUTRAL_VALIDATION: 3145 | { 3146 | int version; 3147 | int reqId; 3148 | 3149 | DECODE_FIELD( version); 3150 | DECODE_FIELD( reqId); 3151 | 3152 | UnderComp underComp; 3153 | 3154 | DECODE_FIELD( underComp.conId); 3155 | DECODE_FIELD( underComp.delta); 3156 | DECODE_FIELD( underComp.price); 3157 | 3158 | m_pEWrapper->deltaNeutralValidation( reqId, underComp); 3159 | break; 3160 | } 3161 | 3162 | case TICK_SNAPSHOT_END: 3163 | { 3164 | int version; 3165 | int reqId; 3166 | 3167 | DECODE_FIELD( version); 3168 | DECODE_FIELD( reqId); 3169 | 3170 | m_pEWrapper->tickSnapshotEnd( reqId); 3171 | break; 3172 | } 3173 | 3174 | case MARKET_DATA_TYPE: 3175 | { 3176 | int version; 3177 | int reqId; 3178 | int marketDataType; 3179 | 3180 | DECODE_FIELD( version); 3181 | DECODE_FIELD( reqId); 3182 | DECODE_FIELD( marketDataType); 3183 | 3184 | m_pEWrapper->marketDataType( reqId, marketDataType); 3185 | break; 3186 | } 3187 | 3188 | default: 3189 | { 3190 | m_pEWrapper->error( msgId, UNKNOWN_ID.code(), UNKNOWN_ID.msg()); 3191 | eDisconnect(); 3192 | m_pEWrapper->connectionClosed(); 3193 | break; 3194 | } 3195 | } 3196 | 3197 | int processed = ptr - beginPtr; 3198 | beginPtr = ptr; 3199 | return processed; 3200 | } 3201 | 3202 | #ifdef _MSC_VER 3203 | catch( CException* e) { 3204 | m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 3205 | SOCKET_EXCEPTION.msg() + errMsg(e)); 3206 | } 3207 | #endif 3208 | 3209 | catch( std::exception e) { 3210 | m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 3211 | SOCKET_EXCEPTION.msg() + errMsg(e)); 3212 | } 3213 | return 0; 3214 | } 3215 | 3216 | bool EClientSocketBase::isConnected() const 3217 | { 3218 | return m_connected; 3219 | } 3220 | 3221 | EWrapper * EClientSocketBase::getWrapper() const 3222 | { 3223 | return m_pEWrapper; 3224 | } 3225 | 3226 | void EClientSocketBase::setClientId( int clientId) 3227 | { 3228 | m_clientId = clientId; 3229 | } 3230 | 3231 | /////////////////////////////////////////////////////////// 3232 | // callbacks from socket 3233 | void EClientSocketBase::onConnectBase() 3234 | { 3235 | // send client version 3236 | std::ostringstream msg; 3237 | ENCODE_FIELD( CLIENT_VERSION); 3238 | bufferedSend( msg.str()); 3239 | } 3240 | 3241 | bool EClientSocketBase::isInBufferEmpty() const 3242 | { 3243 | return m_inBuffer.empty(); 3244 | } 3245 | 3246 | bool EClientSocketBase::isOutBufferEmpty() const 3247 | { 3248 | return m_outBuffer.empty(); 3249 | } 3250 | 3251 | #endif 3252 | -------------------------------------------------------------------------------- /shared/EClientSocketBase.h: -------------------------------------------------------------------------------- 1 | #ifndef eclientsocketbase_h__INCLUDED 2 | #define eclientsocketbase_h__INCLUDED 3 | 4 | #include "EClient.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | class EWrapper; 11 | 12 | class EClientSocketBase : public EClient 13 | { 14 | public: 15 | 16 | explicit EClientSocketBase(EWrapper *ptr); 17 | ~EClientSocketBase(); 18 | 19 | virtual bool eConnect(const char *host, unsigned int port, int clientId=0) = 0; 20 | virtual void eDisconnect() = 0; 21 | 22 | int clientId() const { return m_clientId; } 23 | 24 | protected: 25 | 26 | void eConnectBase(); 27 | void eDisconnectBase(); 28 | 29 | public: 30 | 31 | // connection state 32 | bool isConnected() const; 33 | 34 | protected: 35 | 36 | // access to protected variables 37 | EWrapper * getWrapper() const; 38 | void setClientId( int clientId); 39 | 40 | public: 41 | 42 | bool isInBufferEmpty() const; 43 | bool isOutBufferEmpty() const; 44 | 45 | // override virtual funcs from EClient 46 | int serverVersion(); 47 | IBString TwsConnectionTime(); 48 | void reqMktData(TickerId id, const Contract &contract, 49 | const IBString &genericTicks, bool snapshot); 50 | void cancelMktData(TickerId id); 51 | void placeOrder(OrderId id, const Contract &contract, const Order &order); 52 | void cancelOrder(OrderId id) ; 53 | void reqOpenOrders(); 54 | void reqAccountUpdates(bool subscribe, const IBString& acctCode); 55 | void reqExecutions(int reqId, const ExecutionFilter& filter); 56 | void reqIds(int numIds); 57 | bool checkMessages(); 58 | void reqContractDetails(int reqId, const Contract &contract); 59 | void reqMktDepth(TickerId tickerId, const Contract &contract, int numRows); 60 | void cancelMktDepth(TickerId tickerId); 61 | void reqNewsBulletins(bool allMsgs); 62 | void cancelNewsBulletins(); 63 | void setServerLogLevel(int level); 64 | void reqAutoOpenOrders(bool bAutoBind); 65 | void reqAllOpenOrders(); 66 | void reqManagedAccts(); 67 | void requestFA(faDataType pFaDataType); 68 | void replaceFA(faDataType pFaDataType, const IBString& cxml); 69 | void reqHistoricalData( TickerId id, const Contract &contract, 70 | const IBString &endDateTime, const IBString &durationStr, 71 | const IBString & barSizeSetting, const IBString &whatToShow, 72 | int useRTH, int formatDate); 73 | void exerciseOptions(TickerId tickerId, const Contract &contract, 74 | int exerciseAction, int exerciseQuantity, 75 | const IBString &account, int override); 76 | void cancelHistoricalData(TickerId tickerId ); 77 | void reqRealTimeBars(TickerId id, const Contract &contract, int barSize, 78 | const IBString &whatToShow, bool useRTH); 79 | void cancelRealTimeBars(TickerId tickerId ); 80 | void cancelScannerSubscription(int tickerId); 81 | void reqScannerParameters(); 82 | void reqScannerSubscription(int tickerId, const ScannerSubscription &subscription); 83 | void reqCurrentTime(); 84 | void reqFundamentalData(TickerId reqId, const Contract&, const IBString& reportType); 85 | void cancelFundamentalData(TickerId reqId); 86 | void calculateImpliedVolatility(TickerId reqId, const Contract &contract, double optionPrice, double underPrice); 87 | void calculateOptionPrice(TickerId reqId, const Contract &contract, double volatility, double underPrice); 88 | void cancelCalculateImpliedVolatility(TickerId reqId); 89 | void cancelCalculateOptionPrice(TickerId reqId); 90 | void reqGlobalCancel(); 91 | void reqMarketDataType(int marketDataType); 92 | 93 | private: 94 | 95 | virtual int send(const char* buf, size_t sz) = 0; 96 | virtual int receive(char* buf, size_t sz) = 0; 97 | 98 | protected: 99 | 100 | int sendBufferedData(); 101 | 102 | private: 103 | 104 | int bufferedSend(const char* buf, size_t sz); 105 | int bufferedSend(const std::string& msg); 106 | 107 | // read and buffer what's available 108 | int bufferedRead(); 109 | 110 | // try to process connection request ack 111 | int processConnectAck(const char*& ptr, const char* endPtr); 112 | 113 | // try to process single msg 114 | int processMsg(const char*& ptr, const char* endPtr); 115 | 116 | static bool CheckOffset(const char* ptr, const char* endPtr); 117 | static const char* FindFieldEnd(const char* ptr, const char* endPtr); 118 | 119 | // decoders 120 | static bool DecodeField(bool&, const char*& ptr, const char* endPtr); 121 | static bool DecodeField(int&, const char*& ptr, const char* endPtr); 122 | static bool DecodeField(long&, const char*& ptr, const char* endPtr); 123 | static bool DecodeField(double&, const char*& ptr, const char* endPtr); 124 | static bool DecodeField(IBString&, const char*& ptr, const char* endPtr); 125 | 126 | static bool DecodeFieldMax(int&, const char*& ptr, const char* endPtr); 127 | static bool DecodeFieldMax(long&, const char*& ptr, const char* endPtr); 128 | static bool DecodeFieldMax(double&, const char*& ptr, const char* endPtr); 129 | 130 | // encoders 131 | template static void EncodeField(std::ostream&, T); 132 | 133 | // "max" encoders 134 | static void EncodeFieldMax(std::ostream& os, int); 135 | static void EncodeFieldMax(std::ostream& os, double); 136 | 137 | // socket state 138 | virtual bool isSocketOK() const = 0; 139 | 140 | protected: 141 | 142 | void onConnectBase(); 143 | 144 | private: 145 | 146 | typedef std::vector BytesVec; 147 | 148 | private: 149 | 150 | static void CleanupBuffer(BytesVec&, int processed); 151 | 152 | private: 153 | 154 | EWrapper *m_pEWrapper; 155 | 156 | BytesVec m_inBuffer; 157 | BytesVec m_outBuffer; 158 | 159 | int m_clientId; 160 | 161 | bool m_connected; 162 | int m_serverVersion; 163 | IBString m_TwsTime; 164 | 165 | }; 166 | 167 | template<> void EClientSocketBase::EncodeField(std::ostream& os, bool); 168 | template<> void EClientSocketBase::EncodeField(std::ostream& os, double); 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /shared/EPosixClientSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "EPosixClientSocket.h" 2 | 3 | #include "EPosixClientSocketPlatform.h" 4 | #include "TwsSocketClientErrors.h" 5 | #include "EWrapper.h" 6 | 7 | #include 8 | 9 | /////////////////////////////////////////////////////////// 10 | // member funcs 11 | EPosixClientSocket::EPosixClientSocket( EWrapper *ptr) : EClientSocketBase( ptr) 12 | { 13 | m_fd = -1; 14 | } 15 | 16 | EPosixClientSocket::~EPosixClientSocket() 17 | { 18 | } 19 | 20 | bool EPosixClientSocket::eConnect( const char *host, unsigned int port, int clientId) 21 | { 22 | // reset errno 23 | errno = 0; 24 | 25 | // already connected? 26 | if( m_fd >= 0) { 27 | errno = EISCONN; 28 | getWrapper()->error( NO_VALID_ID, ALREADY_CONNECTED.code(), ALREADY_CONNECTED.msg()); 29 | return false; 30 | } 31 | 32 | // initialize Winsock DLL (only for Windows) 33 | if ( !SocketsInit()) { 34 | return false; 35 | } 36 | 37 | // create socket 38 | m_fd = socket(AF_INET, SOCK_STREAM, 0); 39 | 40 | // cannot create socket 41 | if( m_fd < 0) { 42 | // uninitialize Winsock DLL (only for Windows) 43 | SocketsDestroy(); 44 | getWrapper()->error( NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg()); 45 | return false; 46 | } 47 | 48 | // use local machine if no host passed in 49 | if ( !( host && *host)) { 50 | host = "127.0.0.1"; 51 | } 52 | 53 | // starting to connect to server 54 | struct sockaddr_in sa; 55 | memset( &sa, 0, sizeof(sa)); 56 | sa.sin_family = AF_INET; 57 | sa.sin_port = htons( port); 58 | sa.sin_addr.s_addr = inet_addr( host); 59 | 60 | // try to connect 61 | if( (connect( m_fd, (struct sockaddr *) &sa, sizeof( sa))) < 0) { 62 | // error connecting 63 | // uninitialize Winsock DLL (only for Windows) 64 | SocketsDestroy(); 65 | getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); 66 | return false; 67 | } 68 | 69 | // set client id 70 | setClientId( clientId); 71 | 72 | onConnectBase(); 73 | 74 | while( isSocketOK() && !isConnected()) { 75 | if ( !checkMessages()) { 76 | // uninitialize Winsock DLL (only for Windows) 77 | SocketsDestroy(); 78 | getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); 79 | return false; 80 | } 81 | } 82 | 83 | // successfully connected 84 | return true; 85 | } 86 | 87 | void EPosixClientSocket::eDisconnect() 88 | { 89 | if ( m_fd >= 0 ) 90 | // close socket 91 | SocketClose( m_fd); 92 | m_fd = -1; 93 | // uninitialize Winsock DLL (only for Windows) 94 | SocketsDestroy(); 95 | eDisconnectBase(); 96 | } 97 | 98 | bool EPosixClientSocket::isSocketOK() const 99 | { 100 | return ( m_fd >= 0); 101 | } 102 | 103 | int EPosixClientSocket::fd() const 104 | { 105 | return m_fd; 106 | } 107 | 108 | int EPosixClientSocket::send(const char* buf, size_t sz) 109 | { 110 | if( sz <= 0) 111 | return 0; 112 | 113 | int nResult = ::send( m_fd, buf, sz, 0); 114 | 115 | if( nResult == -1 && !handleSocketError()) { 116 | return -1; 117 | } 118 | if( nResult <= 0) { 119 | return 0; 120 | } 121 | return nResult; 122 | } 123 | 124 | int EPosixClientSocket::receive(char* buf, size_t sz) 125 | { 126 | if( sz <= 0) 127 | return 0; 128 | 129 | int nResult = ::recv( m_fd, buf, sz, 0); 130 | 131 | if( nResult == -1 && !handleSocketError()) { 132 | return -1; 133 | } 134 | if( nResult <= 0) { 135 | return 0; 136 | } 137 | return nResult; 138 | } 139 | 140 | /////////////////////////////////////////////////////////// 141 | // callbacks from socket 142 | 143 | void EPosixClientSocket::onConnect() 144 | { 145 | if( !handleSocketError()) 146 | return; 147 | 148 | onConnectBase(); 149 | } 150 | 151 | void EPosixClientSocket::onReceive() 152 | { 153 | if( !handleSocketError()) 154 | return; 155 | 156 | checkMessages(); 157 | } 158 | 159 | void EPosixClientSocket::onSend() 160 | { 161 | if( !handleSocketError()) 162 | return; 163 | 164 | sendBufferedData(); 165 | } 166 | 167 | void EPosixClientSocket::onClose() 168 | { 169 | if( !handleSocketError()) 170 | return; 171 | 172 | eDisconnect(); 173 | getWrapper()->connectionClosed(); 174 | } 175 | 176 | void EPosixClientSocket::onError() 177 | { 178 | handleSocketError(); 179 | } 180 | 181 | /////////////////////////////////////////////////////////// 182 | // helper 183 | bool EPosixClientSocket::handleSocketError() 184 | { 185 | // no error 186 | if( errno == 0) 187 | return true; 188 | 189 | // Socket is already connected 190 | if( errno == EISCONN) { 191 | return true; 192 | } 193 | 194 | if( errno == EWOULDBLOCK) 195 | return false; 196 | 197 | if( errno == ECONNREFUSED) { 198 | getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); 199 | } 200 | else { 201 | getWrapper()->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 202 | SOCKET_EXCEPTION.msg() + strerror(errno)); 203 | } 204 | // reset errno 205 | errno = 0; 206 | eDisconnect(); 207 | return false; 208 | } 209 | -------------------------------------------------------------------------------- /shared/EPosixClientSocket.h: -------------------------------------------------------------------------------- 1 | #ifndef eposixclientsocket_def 2 | #define eposixclientsocket_def 3 | 4 | #include "EClientSocketBase.h" 5 | 6 | class EWrapper; 7 | 8 | class EPosixClientSocket : public EClientSocketBase 9 | { 10 | public: 11 | 12 | explicit EPosixClientSocket( EWrapper *ptr); 13 | ~EPosixClientSocket(); 14 | 15 | // override virtual funcs from EClient 16 | bool eConnect( const char *host, unsigned int port, int clientId=0); 17 | void eDisconnect(); 18 | 19 | bool isSocketOK() const; 20 | int fd() const; 21 | 22 | private: 23 | 24 | int send( const char* buf, size_t sz); 25 | int receive( char* buf, size_t sz); 26 | 27 | public: 28 | // callback from socket 29 | void onReceive(); 30 | void onSend(); 31 | void onError(); 32 | 33 | private: 34 | 35 | void onConnect(); 36 | void onClose(); 37 | 38 | public: 39 | // helper 40 | bool handleSocketError(); 41 | 42 | private: 43 | 44 | int m_fd; 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /shared/EPosixClientSocketPlatform.h: -------------------------------------------------------------------------------- 1 | #ifndef eposixclientsocketcommon_def 2 | #define eposixclientsocketcommon_def 3 | 4 | #ifdef _WIN32 5 | // Windows 6 | // includes 7 | #include 8 | #include 9 | 10 | // defines 11 | #define EISCONN WSAEISCONN 12 | #define EWOULDBLOCK WSAEWOULDBLOCK 13 | #define ECONNREFUSED WSAECONNREFUSED 14 | 15 | // helpers 16 | inline bool SocketsInit( void) { 17 | WSADATA data; 18 | return ( !WSAStartup( MAKEWORD(2, 2), &data)); 19 | }; 20 | inline bool SocketsDestroy() { return ( !WSACleanup()); }; 21 | inline int SocketClose(int sockfd) { return closesocket( sockfd); }; 22 | 23 | #else 24 | // LINUX 25 | // includes 26 | #include 27 | #include 28 | #include 29 | 30 | // helpers 31 | inline bool SocketsInit() { return true; }; 32 | inline bool SocketsDestroy() { return true; }; 33 | inline int SocketClose(int sockfd) { return close( sockfd); }; 34 | 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /shared/EWrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef ewrapper_def 2 | #define ewrapper_def 3 | 4 | #include "CommonDefs.h" 5 | #include "IBString.h" 6 | 7 | enum TickType { BID_SIZE, BID, ASK, ASK_SIZE, LAST, LAST_SIZE, 8 | HIGH, LOW, VOLUME, CLOSE, 9 | BID_OPTION_COMPUTATION, 10 | ASK_OPTION_COMPUTATION, 11 | LAST_OPTION_COMPUTATION, 12 | MODEL_OPTION, 13 | OPEN, 14 | LOW_13_WEEK, 15 | HIGH_13_WEEK, 16 | LOW_26_WEEK, 17 | HIGH_26_WEEK, 18 | LOW_52_WEEK, 19 | HIGH_52_WEEK, 20 | AVG_VOLUME, 21 | OPEN_INTEREST, 22 | OPTION_HISTORICAL_VOL, 23 | OPTION_IMPLIED_VOL, 24 | OPTION_BID_EXCH, 25 | OPTION_ASK_EXCH, 26 | OPTION_CALL_OPEN_INTEREST, 27 | OPTION_PUT_OPEN_INTEREST, 28 | OPTION_CALL_VOLUME, 29 | OPTION_PUT_VOLUME, 30 | INDEX_FUTURE_PREMIUM, 31 | BID_EXCH, 32 | ASK_EXCH, 33 | AUCTION_VOLUME, 34 | AUCTION_PRICE, 35 | AUCTION_IMBALANCE, 36 | MARK_PRICE, 37 | BID_EFP_COMPUTATION, 38 | ASK_EFP_COMPUTATION, 39 | LAST_EFP_COMPUTATION, 40 | OPEN_EFP_COMPUTATION, 41 | HIGH_EFP_COMPUTATION, 42 | LOW_EFP_COMPUTATION, 43 | CLOSE_EFP_COMPUTATION, 44 | LAST_TIMESTAMP, 45 | SHORTABLE, 46 | FUNDAMENTAL_RATIOS, 47 | RT_VOLUME, 48 | HALTED, 49 | BID_YIELD, 50 | ASK_YIELD, 51 | LAST_YIELD, 52 | CUST_OPTION_COMPUTATION, 53 | TRADE_COUNT, 54 | TRADE_RATE, 55 | VOLUME_RATE, 56 | LAST_RTH_TRADE, 57 | NOT_SET }; 58 | inline bool toString( TickType tickType) 59 | { 60 | if (tickType == BID_SIZE) return "BID_SIZE"; 61 | if (tickType == BID) return "BID"; 62 | if (tickType == ASK) return "ASK"; 63 | if (tickType == ASK_SIZE) return "ASK_SIZE"; 64 | return "UNKNOWN"; 65 | } 66 | inline bool isPrice( TickType tickType) 67 | { 68 | return tickType == BID || tickType == ASK || tickType == LAST; 69 | } 70 | 71 | struct Contract; 72 | struct ContractDetails; 73 | struct Order; 74 | struct OrderState; 75 | struct Execution; 76 | struct UnderComp; 77 | 78 | class EWrapper 79 | { 80 | public: 81 | virtual ~EWrapper() {}; 82 | 83 | virtual void tickPrice( TickerId tickerId, TickType field, double price, int canAutoExecute) = 0; 84 | virtual void tickSize( TickerId tickerId, TickType field, int size) = 0; 85 | virtual void tickOptionComputation( TickerId tickerId, TickType tickType, double impliedVol, double delta, 86 | double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) = 0; 87 | virtual void tickGeneric(TickerId tickerId, TickType tickType, double value) = 0; 88 | virtual void tickString(TickerId tickerId, TickType tickType, const IBString& value) = 0; 89 | virtual void tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const IBString& formattedBasisPoints, 90 | double totalDividends, int holdDays, const IBString& futureExpiry, double dividendImpact, double dividendsToExpiry) = 0; 91 | virtual void orderStatus( OrderId orderId, const IBString &status, int filled, 92 | int remaining, double avgFillPrice, int permId, int parentId, 93 | double lastFillPrice, int clientId, const IBString& whyHeld) = 0; 94 | virtual void openOrder( OrderId orderId, const Contract&, const Order&, const OrderState&) = 0; 95 | virtual void openOrderEnd() = 0; 96 | virtual void winError( const IBString &str, int lastError) = 0; 97 | virtual void connectionClosed() = 0; 98 | virtual void updateAccountValue(const IBString& key, const IBString& val, 99 | const IBString& currency, const IBString& accountName) = 0; 100 | virtual void updatePortfolio( const Contract& contract, int position, 101 | double marketPrice, double marketValue, double averageCost, 102 | double unrealizedPNL, double realizedPNL, const IBString& accountName) = 0; 103 | virtual void updateAccountTime(const IBString& timeStamp) = 0; 104 | virtual void accountDownloadEnd(const IBString& accountName) = 0; 105 | virtual void nextValidId( OrderId orderId) = 0; 106 | virtual void contractDetails( int reqId, const ContractDetails& contractDetails) = 0; 107 | virtual void bondContractDetails( int reqId, const ContractDetails& contractDetails) = 0; 108 | virtual void contractDetailsEnd( int reqId) = 0; 109 | virtual void execDetails( int reqId, const Contract& contract, const Execution& execution) =0; 110 | virtual void execDetailsEnd( int reqId) =0; 111 | virtual void error(const int id, const int errorCode, const IBString errorString) = 0; 112 | virtual void updateMktDepth(TickerId id, int position, int operation, int side, 113 | double price, int size) = 0; 114 | virtual void updateMktDepthL2(TickerId id, int position, IBString marketMaker, int operation, 115 | int side, double price, int size) = 0; 116 | virtual void updateNewsBulletin(int msgId, int msgType, const IBString& newsMessage, const IBString& originExch) = 0; 117 | virtual void managedAccounts( const IBString& accountsList) = 0; 118 | virtual void receiveFA(faDataType pFaDataType, const IBString& cxml) = 0; 119 | virtual void historicalData(TickerId reqId, const IBString& date, double open, double high, 120 | double low, double close, int volume, int barCount, double WAP, int hasGaps) = 0; 121 | virtual void scannerParameters(const IBString &xml) = 0; 122 | virtual void scannerData(int reqId, int rank, const ContractDetails &contractDetails, 123 | const IBString &distance, const IBString &benchmark, const IBString &projection, 124 | const IBString &legsStr) = 0; 125 | virtual void scannerDataEnd(int reqId) = 0; 126 | virtual void realtimeBar(TickerId reqId, long time, double open, double high, double low, double close, 127 | long volume, double wap, int count) = 0; 128 | virtual void currentTime(long time) = 0; 129 | virtual void fundamentalData(TickerId reqId, const IBString& data) = 0; 130 | virtual void deltaNeutralValidation(int reqId, const UnderComp& underComp) = 0; 131 | virtual void tickSnapshotEnd( int reqId) = 0; 132 | virtual void marketDataType( TickerId reqId, int marketDataType) = 0; 133 | }; 134 | 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /shared/Execution.h: -------------------------------------------------------------------------------- 1 | #ifndef execution_def 2 | #define execution_def 3 | 4 | #include "IBString.h" 5 | 6 | struct Execution 7 | { 8 | Execution() 9 | { 10 | shares = 0; 11 | price = 0; 12 | permId = 0; 13 | clientId = 0; 14 | orderId = 0; 15 | cumQty = 0; 16 | avgPrice = 0; 17 | } 18 | 19 | // main order fields 20 | IBString execId; 21 | IBString time; 22 | IBString acctNumber; 23 | IBString exchange; 24 | IBString side; 25 | int shares; 26 | double price; 27 | int permId; 28 | long clientId; 29 | long orderId; 30 | int liquidation; 31 | int cumQty; 32 | double avgPrice; 33 | IBString orderRef; 34 | }; 35 | 36 | struct ExecutionFilter 37 | { 38 | ExecutionFilter() 39 | : m_clientId(0) 40 | { 41 | } 42 | 43 | // Filter fields 44 | long m_clientId; 45 | IBString m_acctCode; 46 | IBString m_time; 47 | IBString m_symbol; 48 | IBString m_secType; 49 | IBString m_exchange; 50 | IBString m_side; 51 | }; 52 | 53 | #endif // execution_def 54 | -------------------------------------------------------------------------------- /shared/IBString.h: -------------------------------------------------------------------------------- 1 | #ifndef ibstring_h__INCLUDED 2 | #define ibstring_h__INCLUDED 3 | 4 | #ifdef IB_USE_STD_STRING 5 | #include 6 | typedef std::string IBString; 7 | #else 8 | #include 9 | typedef CString IBString; 10 | #endif 11 | 12 | #include 13 | 14 | inline bool IsEmpty(const IBString& str) 15 | { 16 | #ifdef IB_USE_STD_STRING 17 | return str.empty(); 18 | #else 19 | return str.IsEmpty(); 20 | #endif 21 | }; 22 | 23 | inline void Empty(IBString& str) 24 | { 25 | #ifdef IB_USE_STD_STRING 26 | str.erase(); 27 | #else 28 | str.Empty(); 29 | #endif 30 | }; 31 | 32 | inline bool Compare(IBString str, const char* strToCompare) 33 | { 34 | #ifdef IB_USE_STD_STRING 35 | return str.compare(strToCompare); 36 | #else 37 | return str.CompareNoCase(strToCompare); 38 | #endif 39 | }; 40 | 41 | inline bool Compare(IBString str, IBString strToCompare) 42 | { 43 | #ifdef IB_USE_STD_STRING 44 | return str.compare(strToCompare); 45 | #else 46 | return str.CompareNoCase(strToCompare); 47 | #endif 48 | }; 49 | 50 | inline double Atof(IBString str) 51 | { 52 | #ifdef IB_USE_STD_STRING 53 | return atof(str.c_str()); 54 | #else 55 | return atof(str); 56 | #endif 57 | }; 58 | 59 | inline int Atoi(IBString str) 60 | { 61 | #ifdef IB_USE_STD_STRING 62 | return atoi(str.c_str()); 63 | #else 64 | return atoi(str); 65 | #endif 66 | }; 67 | 68 | #endif 69 | 70 | 71 | -------------------------------------------------------------------------------- /shared/Order.h: -------------------------------------------------------------------------------- 1 | #ifndef order_def 2 | #define order_def 3 | 4 | #include "shared_ptr.h" 5 | #include "IBString.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #define UNSET_DOUBLE DBL_MAX 13 | #define UNSET_INTEGER INT_MAX 14 | 15 | enum Origin { CUSTOMER, 16 | FIRM, 17 | UNKNOWN }; 18 | 19 | enum AuctionStrategy { AUCTION_UNSET = 0, 20 | AUCTION_MATCH = 1, 21 | AUCTION_IMPROVEMENT = 2, 22 | AUCTION_TRANSPARENT = 3 }; 23 | 24 | struct TagValue 25 | { 26 | TagValue() {} 27 | TagValue(const IBString& p_tag, const IBString& p_value) 28 | : tag(p_tag), value(p_value) 29 | {} 30 | 31 | IBString tag; 32 | IBString value; 33 | }; 34 | 35 | typedef shared_ptr TagValueSPtr; 36 | 37 | struct Order 38 | { 39 | Order() 40 | { 41 | // order identifier 42 | orderId = 0; 43 | clientId = 0; 44 | permId = 0; 45 | 46 | // main order fields 47 | totalQuantity = 0; 48 | lmtPrice = 0; 49 | auxPrice = 0; 50 | 51 | // extended order fields 52 | ocaType = 0; 53 | transmit = true; 54 | parentId = 0; 55 | blockOrder = false; 56 | sweepToFill = false; 57 | displaySize = 0; 58 | triggerMethod = 0; 59 | outsideRth = false; 60 | hidden = false; 61 | allOrNone = false; 62 | minQty = UNSET_INTEGER; 63 | percentOffset = UNSET_DOUBLE; 64 | overridePercentageConstraints = false; 65 | trailStopPrice = UNSET_DOUBLE; 66 | 67 | // institutional (ie non-cleared) only 68 | openClose = "O"; 69 | origin = CUSTOMER; 70 | shortSaleSlot = 0; 71 | exemptCode = -1; 72 | 73 | // SMART routing only 74 | discretionaryAmt = 0; 75 | eTradeOnly = true; 76 | firmQuoteOnly = true; 77 | nbboPriceCap = UNSET_DOUBLE; 78 | optOutSmartRouting = false; 79 | 80 | // BOX exchange orders only 81 | auctionStrategy = AUCTION_UNSET; 82 | startingPrice = UNSET_DOUBLE; 83 | stockRefPrice = UNSET_DOUBLE; 84 | delta = UNSET_DOUBLE; 85 | 86 | // pegged to stock and VOL orders only 87 | stockRangeLower = UNSET_DOUBLE; 88 | stockRangeUpper = UNSET_DOUBLE; 89 | 90 | // VOLATILITY ORDERS ONLY 91 | volatility = UNSET_DOUBLE; 92 | volatilityType = UNSET_INTEGER; // 1=daily, 2=annual 93 | deltaNeutralOrderType = ""; 94 | deltaNeutralAuxPrice = UNSET_DOUBLE; 95 | deltaNeutralConId = 0; 96 | deltaNeutralSettlingFirm = ""; 97 | deltaNeutralClearingAccount = ""; 98 | deltaNeutralClearingIntent = ""; 99 | continuousUpdate = false; 100 | referencePriceType = UNSET_INTEGER; // 1=Average, 2 = BidOrAsk 101 | 102 | // COMBO ORDERS ONLY 103 | basisPoints = UNSET_DOUBLE; // EFP orders only 104 | basisPointsType = UNSET_INTEGER; // EFP orders only 105 | 106 | // SCALE ORDERS ONLY 107 | scaleInitLevelSize = UNSET_INTEGER; 108 | scaleSubsLevelSize = UNSET_INTEGER; 109 | scalePriceIncrement = UNSET_DOUBLE; 110 | 111 | // What-if 112 | whatIf = false; 113 | 114 | // Not Held 115 | notHeld = false; 116 | } 117 | 118 | // order identifier 119 | long orderId; 120 | long clientId; 121 | long permId; 122 | 123 | // main order fields 124 | IBString action; 125 | long totalQuantity; 126 | IBString orderType; 127 | double lmtPrice; 128 | double auxPrice; 129 | 130 | // extended order fields 131 | IBString tif; // "Time in Force" - DAY, GTC, etc. 132 | IBString ocaGroup; // one cancels all group name 133 | int ocaType; // 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK 134 | IBString orderRef; // order reference 135 | bool transmit; // if false, order will be created but not transmited 136 | long parentId; // Parent order Id, to associate Auto STP or TRAIL orders with the original order. 137 | bool blockOrder; 138 | bool sweepToFill; 139 | int displaySize; 140 | int triggerMethod; // 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point 141 | bool outsideRth; 142 | bool hidden; 143 | IBString goodAfterTime; // Format: 20060505 08:00:00 {time zone} 144 | IBString goodTillDate; // Format: 20060505 08:00:00 {time zone} 145 | IBString rule80A; // Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N' 146 | bool allOrNone; 147 | int minQty; 148 | double percentOffset; // REL orders only 149 | bool overridePercentageConstraints; 150 | double trailStopPrice; // TRAILLIMIT orders only 151 | 152 | // financial advisors only 153 | IBString faGroup; 154 | IBString faProfile; 155 | IBString faMethod; 156 | IBString faPercentage; 157 | 158 | // institutional (ie non-cleared) only 159 | IBString openClose; // O=Open, C=Close 160 | Origin origin; // 0=Customer, 1=Firm 161 | int shortSaleSlot; // 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action="SSHORT 162 | IBString designatedLocation; // set when slot=2 only. 163 | int exemptCode; 164 | 165 | // SMART routing only 166 | double discretionaryAmt; 167 | bool eTradeOnly; 168 | bool firmQuoteOnly; 169 | double nbboPriceCap; 170 | bool optOutSmartRouting; 171 | 172 | // BOX exchange orders only 173 | int auctionStrategy; // AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT 174 | double startingPrice; 175 | double stockRefPrice; 176 | double delta; 177 | 178 | // pegged to stock and VOL orders only 179 | double stockRangeLower; 180 | double stockRangeUpper; 181 | 182 | // VOLATILITY ORDERS ONLY 183 | double volatility; 184 | int volatilityType; // 1=daily, 2=annual 185 | IBString deltaNeutralOrderType; 186 | double deltaNeutralAuxPrice; 187 | long deltaNeutralConId; 188 | IBString deltaNeutralSettlingFirm; 189 | IBString deltaNeutralClearingAccount; 190 | IBString deltaNeutralClearingIntent; 191 | bool continuousUpdate; 192 | int referencePriceType; // 1=Average, 2 = BidOrAsk 193 | 194 | // COMBO ORDERS ONLY 195 | double basisPoints; // EFP orders only 196 | int basisPointsType; // EFP orders only 197 | 198 | // SCALE ORDERS ONLY 199 | int scaleInitLevelSize; 200 | int scaleSubsLevelSize; 201 | double scalePriceIncrement; 202 | 203 | // HEDGE ORDERS 204 | IBString hedgeType; // 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair 205 | IBString hedgeParam; // 'beta=X' value for beta hedge, 'ratio=Y' for pair hedge 206 | 207 | // Clearing info 208 | IBString account; // IB account 209 | IBString settlingFirm; 210 | IBString clearingAccount; // True beneficiary of the order 211 | IBString clearingIntent; // "" (Default), "IB", "Away", "PTA" (PostTrade) 212 | 213 | // ALGO ORDERS ONLY 214 | IBString algoStrategy; 215 | 216 | typedef std::vector TagValueList; 217 | typedef shared_ptr TagValueListSPtr; 218 | 219 | TagValueListSPtr algoParams; 220 | TagValueListSPtr smartComboRoutingParams; 221 | 222 | // What-if 223 | bool whatIf; 224 | 225 | // Not Held 226 | bool notHeld; 227 | }; 228 | 229 | #endif 230 | -------------------------------------------------------------------------------- /shared/OrderState.h: -------------------------------------------------------------------------------- 1 | #ifndef ORDER_STATE_H__INCLUDED 2 | #define ORDER_STATE_H__INCLUDED 3 | 4 | #include "Order.h" 5 | 6 | struct OrderState { 7 | 8 | explicit OrderState() 9 | : 10 | commission(UNSET_DOUBLE), 11 | minCommission(UNSET_DOUBLE), 12 | maxCommission(UNSET_DOUBLE) 13 | {} 14 | 15 | IBString status; 16 | 17 | IBString initMargin; 18 | IBString maintMargin; 19 | IBString equityWithLoan; 20 | 21 | double commission; 22 | double minCommission; 23 | double maxCommission; 24 | IBString commissionCurrency; 25 | 26 | IBString warningText; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /shared/ScannerSubscription.h: -------------------------------------------------------------------------------- 1 | #ifndef scanner_def 2 | #define scanner_def 3 | 4 | #include 5 | #include 6 | 7 | #include "IBString.h" 8 | 9 | #define UNSET_DOUBLE DBL_MAX 10 | #define UNSET_INTEGER INT_MAX 11 | #define NO_ROW_NUMBER_SPECIFIED -1; 12 | 13 | struct ScannerSubscription { 14 | ScannerSubscription() { 15 | numberOfRows = NO_ROW_NUMBER_SPECIFIED; 16 | abovePrice = DBL_MAX; 17 | belowPrice = DBL_MAX; 18 | aboveVolume = INT_MAX; 19 | marketCapAbove = DBL_MAX; 20 | marketCapBelow = DBL_MAX; 21 | couponRateAbove = DBL_MAX; 22 | couponRateBelow = DBL_MAX; 23 | excludeConvertible = 0; 24 | averageOptionVolumeAbove = 0; 25 | } 26 | int numberOfRows; 27 | IBString instrument; 28 | IBString locationCode; 29 | IBString scanCode; 30 | double abovePrice; 31 | double belowPrice; 32 | int aboveVolume; 33 | double marketCapAbove; 34 | double marketCapBelow; 35 | IBString moodyRatingAbove; 36 | IBString moodyRatingBelow; 37 | IBString spRatingAbove; 38 | IBString spRatingBelow; 39 | IBString maturityDateAbove; 40 | IBString maturityDateBelow; 41 | double couponRateAbove; 42 | double couponRateBelow; 43 | int excludeConvertible; 44 | int averageOptionVolumeAbove; 45 | IBString scannerSettingPairs; 46 | IBString stockTypeFilter; 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /shared/StdAfx.h: -------------------------------------------------------------------------------- 1 | #ifndef DLLEXP 2 | #define DLLEXP __declspec( dllexport ) 3 | #endif 4 | 5 | #ifdef _MSC_VER 6 | 7 | #define assert ASSERT 8 | #define snprintf _snprintf 9 | 10 | #include 11 | 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /shared/TwsSocketClientErrors.h: -------------------------------------------------------------------------------- 1 | #ifndef tswsocketclienterrors_def 2 | #define tswsocketclienterrors_def 3 | 4 | static const int NO_VALID_ID = -1; 5 | static const int NO_VALID_ERROR_CODE = 0; 6 | static const int SYSTEM_ERROR = 600; 7 | 8 | class CodeMsgPair { 9 | public: 10 | CodeMsgPair(int code, IBString msg) : m_errorCode(code), m_errorMsg(msg) { 11 | } 12 | private: 13 | int m_errorCode; 14 | IBString m_errorMsg; 15 | public: 16 | int code() const { return m_errorCode; } 17 | const IBString& msg() const { return m_errorMsg; } 18 | }; 19 | 20 | static const CodeMsgPair ALREADY_CONNECTED(501, "Already connected."); 21 | static const CodeMsgPair CONNECT_FAIL(502, "Couldn't connect to TWS. Confirm that \"Enable ActiveX and Socket Clients\" is enabled on the TWS \"Configure->API\" menu."); 22 | static const CodeMsgPair UPDATE_TWS(503, "The TWS is out of date and must be upgraded."); 23 | static const CodeMsgPair NOT_CONNECTED(504, "Not connected"); 24 | static const CodeMsgPair UNKNOWN_ID(505, "Fatal Error: Unknown message id."); 25 | static const CodeMsgPair ZERO_BYTE_READ(506, "Unexplained zero bytes read."); 26 | static const CodeMsgPair NULL_STRING_READ(507, "Null string read when expecting integer"); 27 | static const CodeMsgPair NO_BYTES_READ(508, "Error: no bytes read or no null terminator found"); 28 | static const CodeMsgPair SOCKET_EXCEPTION(509, "Exception caught while reading socket - "); 29 | static const CodeMsgPair FAIL_CREATE_SOCK(520, "Failed to create socket"); 30 | static const CodeMsgPair FAIL_CONNECT_TWS(521, "Couldn't connect to TWS."); 31 | static const CodeMsgPair FAIL_SEND_FA_REQUEST(522, "FA Information Request Sending Error - "); 32 | static const CodeMsgPair FAIL_SEND_FA_REPLACE(523, "FA Information Replace Sending Error - "); 33 | static const CodeMsgPair FAIL_SEND_REQSCANNER(524, "Request Scanner Subscription Sending Error - "); 34 | static const CodeMsgPair FAIL_SEND_CANSCANNER(525, "Cancel Scanner Subscription Sending Error - "); 35 | static const CodeMsgPair FAIL_SEND_REQSCANNERPARAMETERS(526, "Request Scanner Parameter Sending Error - "); 36 | static const CodeMsgPair FAIL_SEND_REQHISTDATA(527, "Request Historical Data Sending Error - "); 37 | static const CodeMsgPair FAIL_SEND_CANHISTDATA(528, "Cancel Historical Data Sending Error - "); 38 | static const CodeMsgPair FAIL_SEND_REQRTBARS(529, "Request Real-time Bar Data Sending Error - "); 39 | static const CodeMsgPair FAIL_SEND_CANRTBARS(530, "Cancel Real-time Bar Data Sending Error - "); 40 | static const CodeMsgPair FAIL_SEND_REQCURRTIME(531, "Request Current Time Sending Error - "); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /shared/shared_ptr.h: -------------------------------------------------------------------------------- 1 | #ifndef shared_ptr_h_INCLUDED 2 | #define shared_ptr_h_INCLUDED 3 | 4 | // 5 | // Implements a subset of shared_prt found at www.boost.org. 6 | // Uses a singly linked circular list instead of a reference counter. 7 | // Avoids extra heap allocation needed to get a shared reference counter, 8 | // but sizeof(shared_ptr) == sizeof(void*) * 3 compared to sizeof(void*) * 2 9 | // 10 | // See "Handles and Exception Safety, Part 4: Tracking References without Counters" 11 | // by Andrew Koenig and Barbara E. Moo, Feb. 2003 C++ Users Journal 12 | // 13 | namespace shared_ptr_defs { 14 | 15 | class Use { 16 | public: 17 | 18 | Use() { forward_ = this; back_ = this; } 19 | ~Use() { remove(); } 20 | 21 | Use(const Use& u) { insert(u); } 22 | Use& operator=(const Use& u) 23 | { 24 | if (this != &u) { 25 | remove(); 26 | insert(u); 27 | } 28 | return *this; 29 | } 30 | bool only() const { return this == this->forward_; } 31 | private: 32 | mutable const Use *forward_; 33 | mutable const Use *back_; 34 | 35 | void insert(const Use& u) const { 36 | this->back_ = &u; 37 | this->forward_ = u.forward_; 38 | u.forward_->back_ = this; 39 | u.forward_ = this; 40 | } 41 | 42 | void remove() const { 43 | this->forward_->back_ = this->back_; 44 | this->back_->forward_ = this->forward_; 45 | } 46 | }; 47 | 48 | } // end of namespace shared_ptr_defs 49 | 50 | template class shared_ptr { 51 | public: 52 | 53 | typedef shared_ptr_defs::Use Use; 54 | 55 | template friend class shared_ptr; 56 | 57 | explicit shared_ptr(X* ptr = 0) : ptr_(ptr) {} 58 | 59 | ~shared_ptr() { if (use_.only()) delete ptr_; } 60 | 61 | template 62 | shared_ptr(const shared_ptr& other) 63 | : ptr_(other.ptr_), 64 | use_(other.use_) 65 | {} 66 | 67 | shared_ptr& operator=(const shared_ptr& other) { 68 | if ( &use_ == &other.use_ ) { return *this; } 69 | if ( use_.only() ) { delete ptr_; } 70 | use_ = other.use_; 71 | ptr_ = other.ptr_; 72 | return *this; 73 | } 74 | 75 | X& operator*() const { return *ptr_; } 76 | X* operator->() const { return ptr_; } 77 | // added these Alexy Shelest 78 | /* 79 | X& operator<< (bool val) const { return *ptr_; } 80 | X& operator<< (short val) const { return *ptr_; } 81 | X& operator<< (unsigned short val) const { return *ptr_; } 82 | X& operator<< (int val) const { return *ptr_; } 83 | X& operator<< (unsigned int val) const { return *ptr_; } 84 | X& operator<< (long val) const { return *ptr_; } 85 | X& operator<< (unsigned long val) const { return *ptr_; } 86 | X& operator<< (float val) const { return *ptr_; } 87 | X& operator<< (double val) const { return *ptr_; } 88 | X& operator<< (long double val) const { return *ptr_; } 89 | X& operator<< (const void* val) const { return *ptr_; } 90 | X& operator<<(const char* val) const { return *ptr_; } 91 | 92 | X& operator !() const { return *ptr_; } 93 | */ 94 | // end Alexy Shelest 95 | 96 | X* get() const { return ptr_; } 97 | bool only() const { return use_.only(); } 98 | 99 | void reset(X* ptr = 0) { 100 | if ( use_.only() ) { delete ptr_; } 101 | ptr_ = ptr; 102 | use_ = Use(); 103 | } 104 | 105 | private: 106 | 107 | X *ptr_; 108 | Use use_; 109 | }; 110 | 111 | #endif /* shared_ptr_h_INCLUDED */ 112 | -------------------------------------------------------------------------------- /src/BreakoutTrader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "BreakoutTrader.h" 3 | 4 | #include "EPosixClientSocket.h" 5 | #include "EPosixClientSocketPlatform.h" 6 | 7 | #include "Contract.h" 8 | #include "Order.h" 9 | 10 | #include 11 | 12 | using namespace std; 13 | 14 | const int PING_DEADLINE = 2; // seconds 15 | const int SLEEP_BETWEEN_PINGS = 30; // seconds 16 | // const 1 of type double to avoid casting for division operation (i.e. double/int=double, int/int=int) 17 | const double one = 1; 18 | 19 | /////////////////////////////////////////////////////////// 20 | // member funcs 21 | BreakoutTrader::BreakoutTrader(std::string symbol, std::string type, std::string exch, std::string ccy, std::string time, std::string isdbg) 22 | : m_pClient(new EPosixClientSocket(this)) 23 | , m_state(ST_CONNECT) 24 | , m_sleepDeadline(0) 25 | , m_orderId(0) 26 | , m_tickId(0) 27 | ,m_curName("") 28 | ,m_pFout(new ofstream) 29 | ,m_pLogger(new ofstream) 30 | ,m_totalBidVol(0) 31 | ,m_numbBidTicks(0) 32 | ,m_numbAskTicks(0) 33 | ,m_totalAskVol(0) 34 | ,m_totalVol(0) 35 | ,m_numbTicks(0) 36 | { 37 | m_pLogger->open("logs/rolling_log.log", ios::app); 38 | if (!*(m_pLogger)) 39 | { 40 | throw "Cannot open rolling.log\n"; 41 | } 42 | m_curName = rollLog(); 43 | m_symbol = symbol; 44 | m_secType = type; 45 | m_exchange = exch; 46 | m_currency = ccy; 47 | m_timePeriod = atoi(time.c_str()); 48 | m_isDbg = atoi(isdbg.c_str()); 49 | 50 | } 51 | 52 | BreakoutTrader::~BreakoutTrader() 53 | { 54 | m_pFout->close(); 55 | m_pLogger->close(); 56 | } 57 | 58 | string BreakoutTrader::rollLog() 59 | { 60 | time_t now = ::time(NULL); 61 | struct tm * timeinfo = localtime ( &now); 62 | 63 | ostringstream ostr; 64 | ostr <<"logs/"<tm_year<<"_"<tm_mon<<"_"<tm_mday; 65 | string tmp = ostr.str(); 66 | 67 | const char *fName; 68 | fName = tmp.c_str(); 69 | 70 | if (tmp != m_curName) 71 | { 72 | // close old file 73 | if (m_pFout->is_open()) m_pFout->close(); 74 | // open new 75 | m_pFout->open(fName, ios::app); 76 | if (!*(m_pFout)) 77 | { 78 | time_t now = ::time(NULL); 79 | *m_pLogger<eConnect( host, port, clientId); 101 | 102 | if (bRes) 103 | { 104 | *m_pLogger<eDisconnect(); 116 | 117 | time_t now = ::time(NULL); 118 | *m_pLogger<isConnected(); 124 | } 125 | 126 | void BreakoutTrader::processMessages() 127 | { 128 | fd_set readSet, writeSet, errorSet; 129 | 130 | struct timeval tval; 131 | tval.tv_usec = 0; 132 | tval.tv_sec = 0; 133 | 134 | time_t now = time(NULL); 135 | 136 | switch (m_state) 137 | { 138 | case ST_REQ_DATA: 139 | reqData(); 140 | break; 141 | case ST_REQ_DATA_ACK: 142 | // can't run for more than 24 hours without VPN 143 | // m_curName = rollLog(); 144 | if ((now - m_PeriodStarted) > m_timePeriod) 145 | { 146 | closeTimePeriod(); 147 | } 148 | break; 149 | case ST_PING: 150 | reqCurrentTime(); 151 | break; 152 | case ST_PING_ACK: 153 | if( m_sleepDeadline < now) 154 | { 155 | disconnect(); 156 | return; 157 | } 158 | break; 159 | case ST_IDLE: 160 | if( m_sleepDeadline < now) 161 | { 162 | m_state = ST_PING; 163 | return; 164 | } 165 | break; 166 | } 167 | 168 | if( m_sleepDeadline > 0) 169 | { 170 | // initialize timeout with m_sleepDeadline - now 171 | tval.tv_sec = m_sleepDeadline - now; 172 | } 173 | 174 | if( m_pClient->fd() >= 0 ) 175 | { 176 | 177 | FD_ZERO( &readSet); 178 | errorSet = writeSet = readSet; 179 | 180 | FD_SET( m_pClient->fd(), &readSet); 181 | 182 | if( !m_pClient->isOutBufferEmpty()) 183 | FD_SET( m_pClient->fd(), &writeSet); 184 | 185 | FD_CLR( m_pClient->fd(), &errorSet); 186 | 187 | int ret = select( m_pClient->fd() + 1, &readSet, &writeSet, &errorSet, &tval); 188 | 189 | if( ret == 0) { // timeout 190 | return; 191 | } 192 | 193 | if( ret < 0) { // error 194 | disconnect(); 195 | return; 196 | } 197 | 198 | if( m_pClient->fd() < 0) 199 | return; 200 | 201 | if( FD_ISSET( m_pClient->fd(), &errorSet)) { 202 | // error on socket 203 | m_pClient->onError(); 204 | } 205 | 206 | if( m_pClient->fd() < 0) 207 | return; 208 | 209 | if( FD_ISSET( m_pClient->fd(), &writeSet)) { 210 | // socket is ready for writing 211 | m_pClient->onSend(); 212 | } 213 | 214 | if( m_pClient->fd() < 0) 215 | return; 216 | 217 | if( FD_ISSET( m_pClient->fd(), &readSet)) { 218 | // socket is ready for reading 219 | m_pClient->onReceive(); 220 | } 221 | } 222 | } 223 | 224 | ////////////////////////////////////////////////////////////////// 225 | // methods 226 | void BreakoutTrader::reqCurrentTime() 227 | { 228 | time_t now = ::time(NULL); 229 | *m_pLogger<reqCurrentTime(); 237 | } 238 | 239 | void BreakoutTrader::reqData() 240 | { 241 | Contract contract; 242 | contract.symbol = m_symbol; 243 | contract.secType = m_secType; 244 | contract.exchange = m_exchange; 245 | contract.currency = m_currency; 246 | 247 | IBString ticks = "100,101,104,105,106,107,165,221,225,233,236,258,293,294,295,318"; 248 | //IBString whatToShow = "TRADES"; 249 | 250 | time_t now = ::time(NULL); 251 | *m_pLogger<reqMktData(m_tickId, contract, ticks, false); 255 | //m_pClient->reqMktDepth(m_tickId, contract, 50); 256 | //m_pClient->reqRealTimeBars(m_tickId, contract, 5, whatToShow, true); 257 | m_tickId++; 258 | } 259 | 260 | void BreakoutTrader::closeTimePeriod() 261 | { 262 | // roll 263 | // keep 264 | Sum sumFunc; 265 | sumFunc = for_each(m_closePriceLogs.begin(),m_closePriceLogs.end(),Sum()); 266 | double sum = sumFunc.GetSum(); 267 | SqrSum sumSqFunc; 268 | sumSqFunc = for_each(m_closePriceLogs.begin(),m_closePriceLogs.end(),SqrSum()); 269 | double sqSum = sumSqFunc.GetSum(); 270 | // delete 271 | Sum sumAskFunc; 272 | sumAskFunc = for_each(m_closeAskPriceLogs.begin(),m_closeAskPriceLogs.end(),Sum()); 273 | double askSum = sumAskFunc.GetSum(); 274 | SqrSum sumSqAskFunc; 275 | sumSqAskFunc = for_each(m_closeAskPriceLogs.begin(),m_closeAskPriceLogs.end(),SqrSum()); 276 | double askSqSum = sumSqAskFunc.GetSum(); 277 | 278 | Sum sumBidFunc; 279 | sumBidFunc = for_each(m_closeBidPriceLogs.begin(),m_closeBidPriceLogs.end(),Sum()); 280 | double bidSum = sumBidFunc.GetSum(); 281 | SqrSum sumSqBidFunc; 282 | sumSqBidFunc = for_each(m_closeBidPriceLogs.begin(),m_closeBidPriceLogs.end(),SqrSum()); 283 | double bidSqSum = sumSqBidFunc.GetSum(); 284 | // delete 285 | if (m_isDbg) 286 | { 287 | time_t now = ::time(NULL); 288 | *m_pLogger<tm_mday<<","<tm_hour<<","<tm_min<<","<tm_sec<<"," 314 | < 1) 382 | { 383 | m_prevPrice = m_lastPrice; 384 | m_lastPrice = price; 385 | m_closePriceLogs.push_back(log(m_lastPrice/m_prevPrice)); 386 | } 387 | else 388 | { 389 | m_lastPrice = price; 390 | } 391 | //if (m_isDbg) 392 | //{ 393 | // time_t now = ::time(NULL); 394 | // *m_pLogger< 1) 404 | { 405 | m_prevAskPrice = m_lastAskPrice; 406 | m_lastAskPrice = price; 407 | m_closeAskPriceLogs.push_back(log(m_lastAskPrice/m_prevAskPrice)); 408 | } 409 | else 410 | { 411 | m_lastAskPrice = price; 412 | } 413 | //if (m_isDbg) 414 | //{ 415 | // time_t now = ::time(NULL); 416 | // *m_pLogger< 1) 425 | { 426 | m_prevBidPrice = m_lastBidPrice; 427 | m_lastBidPrice = price; 428 | m_closeBidPriceLogs.push_back(log(m_lastBidPrice/m_prevBidPrice)); 429 | } 430 | else 431 | { 432 | m_lastBidPrice = price; 433 | } 434 | //if (m_isDbg) 435 | //{ 436 | // time_t now = ::time(NULL); 437 | // *m_pLogger< 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | class EPosixClientSocket; 19 | 20 | enum State 21 | { 22 | ST_CONNECT, 23 | ST_REQ_DATA, 24 | ST_REQ_DATA_ACK, 25 | ST_PING, 26 | ST_PING_ACK, 27 | ST_IDLE 28 | }; 29 | // sum functor 30 | template 31 | class Sum 32 | { 33 | T m_Sum; 34 | public: 35 | Sum() 36 | { 37 | m_Sum = 0; 38 | } 39 | T GetSum() const 40 | { 41 | return m_Sum; 42 | } 43 | 44 | void operator() (const T& el) 45 | { 46 | m_Sum += el; 47 | } 48 | }; 49 | // sum of squares functor 50 | template 51 | class SqrSum 52 | { 53 | T m_Sum; 54 | public: 55 | SqrSum() 56 | { 57 | m_Sum = 0; 58 | } 59 | T GetSum() const 60 | { 61 | return m_Sum; 62 | } 63 | void operator() (const T& el) 64 | { 65 | m_Sum += (el*el); 66 | } 67 | }; 68 | 69 | class BreakoutTrader : public EWrapper 70 | { 71 | public: 72 | 73 | BreakoutTrader(std::string symbol, std::string type, std::string exch, std::string ccy, std::string time, std::string isdbg); 74 | ~BreakoutTrader(); 75 | 76 | void processMessages(); 77 | 78 | bool connect(const char * host, unsigned int port, int clientId = 0); 79 | void disconnect() const; 80 | bool isConnected() const; 81 | 82 | private: 83 | string rollLog(); 84 | void reqCurrentTime(); 85 | void reqData(); 86 | void closeTimePeriod(); 87 | 88 | public: 89 | // events 90 | void tickPrice(TickerId tickerId, TickType field, double price, int canAutoExecute); 91 | void tickSize(TickerId tickerId, TickType field, int size); 92 | void tickOptionComputation( TickerId tickerId, TickType tickType, double impliedVol, double delta, 93 | double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice); 94 | void tickGeneric(TickerId tickerId, TickType tickType, double value); 95 | void tickString(TickerId tickerId, TickType tickType, const IBString& value); 96 | void tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const IBString& formattedBasisPoints, 97 | double totalDividends, int holdDays, const IBString& futureExpiry, double dividendImpact, double dividendsToExpiry); 98 | void orderStatus(OrderId orderId, const IBString &status, int filled, 99 | int remaining, double avgFillPrice, int permId, int parentId, 100 | double lastFillPrice, int clientId, const IBString& whyHeld); 101 | void openOrder(OrderId orderId, const Contract&, const Order&, const OrderState&); 102 | void openOrderEnd(); 103 | void winError(const IBString &str, int lastError); 104 | void connectionClosed(); 105 | void updateAccountValue(const IBString& key, const IBString& val, 106 | const IBString& currency, const IBString& accountName); 107 | void updatePortfolio(const Contract& contract, int position, 108 | double marketPrice, double marketValue, double averageCost, 109 | double unrealizedPNL, double realizedPNL, const IBString& accountName); 110 | void updateAccountTime(const IBString& timeStamp); 111 | void accountDownloadEnd(const IBString& accountName); 112 | void nextValidId(OrderId orderId); 113 | void contractDetails(int reqId, const ContractDetails& contractDetails); 114 | void bondContractDetails(int reqId, const ContractDetails& contractDetails); 115 | void contractDetailsEnd(int reqId); 116 | void execDetails(int reqId, const Contract& contract, const Execution& execution); 117 | void execDetailsEnd(int reqId); 118 | void error(const int id, const int errorCode, const IBString errorString); 119 | void updateMktDepth(TickerId id, int position, int operation, int side, 120 | double price, int size); 121 | void updateMktDepthL2(TickerId id, int position, IBString marketMaker, int operation, 122 | int side, double price, int size); 123 | void updateNewsBulletin(int msgId, int msgType, const IBString& newsMessage, const IBString& originExch); 124 | void managedAccounts(const IBString& accountsList); 125 | void receiveFA(faDataType pFaDataType, const IBString& cxml); 126 | void historicalData(TickerId reqId, const IBString& date, double open, double high, 127 | double low, double close, int volume, int barCount, double WAP, int hasGaps); 128 | void scannerParameters(const IBString &xml); 129 | void scannerData(int reqId, int rank, const ContractDetails &contractDetails, 130 | const IBString &distance, const IBString &benchmark, const IBString &projection, 131 | const IBString &legsStr); 132 | void scannerDataEnd(int reqId); 133 | void realtimeBar(TickerId reqId, long time, double open, double high, double low, double close, 134 | long volume, double wap, int count); 135 | void currentTime(long time); 136 | void fundamentalData(TickerId reqId, const IBString& data); 137 | void deltaNeutralValidation(int reqId, const UnderComp& underComp); 138 | void tickSnapshotEnd(int reqId); 139 | void marketDataType(TickerId reqId, int marketDataType); 140 | 141 | private: 142 | 143 | boost::shared_ptr m_pClient; 144 | State m_state; 145 | time_t m_sleepDeadline; 146 | int m_timePeriod; 147 | time_t m_PeriodStarted; 148 | 149 | OrderId m_orderId; 150 | OrderId m_tickId; 151 | 152 | string m_symbol; 153 | string m_secType; 154 | string m_exchange; 155 | string m_currency; 156 | 157 | string m_curName; 158 | boost::shared_ptr m_pFout; 159 | boost::shared_ptr m_pLogger; 160 | 161 | bool m_isDbg; 162 | // delete 163 | double m_lastBidPrice; 164 | double m_prevBidPrice; 165 | double m_lastAskPrice; 166 | double m_prevAskPrice; 167 | unsigned int m_totalBidVol; 168 | int m_numbBidTicks; 169 | int m_numbAskTicks; 170 | unsigned int m_totalAskVol; 171 | double m_AskStDiv; 172 | double m_BidStDiv; 173 | vector m_closeAskPriceLogs; 174 | vector m_closeBidPriceLogs; 175 | // keep 176 | double m_lastPrice; 177 | double m_prevPrice; 178 | unsigned int m_totalVol; 179 | int m_numbTicks; 180 | double m_StDiv; 181 | vector m_closePriceLogs; 182 | // 183 | }; 184 | 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "BreakoutTrader.h" 3 | 4 | using namespace std; 5 | const unsigned MAX_ATTEMPTS = 50; 6 | const unsigned SLEEP_TIME = 10; 7 | 8 | // usage: symbol, type, exchange, currency, time period (number of seconds) 9 | // "EUR" "CASH" "IDEALPRO" "USD" 300 1 10 | int main(int argc, char** argv) 11 | { 12 | try 13 | { 14 | cout<<"Start of BreakoutTrader with "<= MAX_ATTEMPTS) { 45 | break; 46 | } 47 | 48 | cout<<"Sleeping before next attempt for "< 2 | #include "UnitTest.h" 3 | 4 | #include "EPosixClientSocket.h" 5 | #include "EPosixClientSocketPlatform.h" 6 | 7 | #include "Contract.h" 8 | #include "Order.h" 9 | 10 | using namespace std; 11 | 12 | const int PING_DEADLINE = 2; // seconds 13 | const int SLEEP_BETWEEN_PINGS = 30; // seconds 14 | 15 | /////////////////////////////////////////////////////////// 16 | // member funcs 17 | UnitTest::UnitTest() 18 | : m_pClient(new EPosixClientSocket(this)) 19 | , m_state(ST_CONNECT) 20 | , m_sleepDeadline(0) 21 | , m_buySignal(0) 22 | { 23 | } 24 | 25 | UnitTest::~UnitTest() 26 | { 27 | } 28 | 29 | bool UnitTest::connect(const char *host, unsigned int port, int clientId) 30 | { 31 | // trying to connect 32 | cout<<"Connecting to %s:%d clientId:%d\n"<< (!( host && *host) ? "127.0.0.1" : host)<< port<eConnect( host, port, clientId); 35 | 36 | if (bRes) { 37 | cout<<"Connected to %s:%d clientId:%d\n"<<(!( host && *host) ? "127.0.0.1" : host)<eDisconnect(); 48 | 49 | cout<<"Disconnected\n"<isConnected(); 55 | } 56 | 57 | 58 | ////////////////////////////////////////////////////////////////// 59 | // methods 60 | void UnitTest::processMessages() 61 | { 62 | fd_set readSet, writeSet, errorSet; 63 | 64 | struct timeval tval; 65 | tval.tv_usec = 0; 66 | tval.tv_sec = 0; 67 | 68 | time_t now = time(NULL); 69 | 70 | switch (m_state) { 71 | case ST_REQ_DATA: 72 | requestData(); 73 | break; 74 | case ST_REQ_DATA_ACK: 75 | break; 76 | case ST_PLACEORDER: 77 | placeOrder(); 78 | break; 79 | case ST_PLACEORDER_ACK: 80 | break; 81 | case ST_PLACETAIL: 82 | placeTail(); 83 | break; 84 | case ST_PLACETAIL_ACK: 85 | break; 86 | case ST_CANCELORDER: 87 | cancelOrder(); 88 | break; 89 | case ST_CANCELORDER_ACK: 90 | break; 91 | case ST_PING: 92 | reqCurrentTime(); 93 | break; 94 | case ST_PING_ACK: 95 | if( m_sleepDeadline < now) { 96 | disconnect(); 97 | return; 98 | } 99 | break; 100 | case ST_IDLE: 101 | if( m_sleepDeadline < now) { 102 | m_state = ST_PING; 103 | return; 104 | } 105 | break; 106 | } 107 | 108 | if( m_sleepDeadline > 0) { 109 | // initialize timeout with m_sleepDeadline - now 110 | tval.tv_sec = m_sleepDeadline - now; 111 | } 112 | 113 | if( m_pClient->fd() >= 0 ) { 114 | 115 | FD_ZERO( &readSet); 116 | errorSet = writeSet = readSet; 117 | 118 | FD_SET( m_pClient->fd(), &readSet); 119 | 120 | if( !m_pClient->isOutBufferEmpty()) 121 | FD_SET( m_pClient->fd(), &writeSet); 122 | 123 | FD_CLR( m_pClient->fd(), &errorSet); 124 | 125 | int ret = select( m_pClient->fd() + 1, &readSet, &writeSet, &errorSet, &tval); 126 | 127 | if( ret == 0) { // timeout 128 | return; 129 | } 130 | 131 | if( ret < 0) { // error 132 | disconnect(); 133 | return; 134 | } 135 | 136 | if( m_pClient->fd() < 0) 137 | return; 138 | 139 | if( FD_ISSET( m_pClient->fd(), &errorSet)) { 140 | // error on socket 141 | m_pClient->onError(); 142 | } 143 | 144 | if( m_pClient->fd() < 0) 145 | return; 146 | 147 | if( FD_ISSET( m_pClient->fd(), &writeSet)) { 148 | // socket is ready for writing 149 | m_pClient->onSend(); 150 | } 151 | 152 | if( m_pClient->fd() < 0) 153 | return; 154 | 155 | if( FD_ISSET( m_pClient->fd(), &readSet)) { 156 | // socket is ready for reading 157 | m_pClient->onReceive(); 158 | } 159 | } 160 | } 161 | 162 | 163 | void UnitTest::requestData() 164 | { 165 | Contract contract; 166 | contract.symbol = "EUR"; 167 | contract.secType = "CASH"; 168 | contract.exchange = "IDEALPRO"; 169 | contract.currency = "USD"; 170 | 171 | IBString ticks = "100,101,104,105,106,107,165,221,225,233,236,258,293,294,295,318"; 172 | 173 | cout<<"Request FX market data"<reqMktData(m_tickId, contract, ticks, false); 177 | 178 | m_tickId++; 179 | } 180 | void UnitTest::placeTail() 181 | { 182 | 183 | Contract contract; 184 | Order order; 185 | 186 | contract.symbol = "EUR"; 187 | contract.secType = "CASH"; 188 | contract.exchange = "IDEALPRO"; 189 | contract.currency = "USD"; 190 | 191 | order.action = "SELL"; 192 | order.totalQuantity = 20000; 193 | order.orderType = "MKT"; 194 | 195 | cout<<"Placing Tail Order"<placeOrder( m_orderId, contract, order); 200 | 201 | m_orderId++; 202 | } 203 | 204 | void UnitTest::reqCurrentTime() 205 | { 206 | cout<<"Requesting Current Time\n"<reqCurrentTime(); 214 | } 215 | 216 | void UnitTest::placeOrder() 217 | { 218 | Contract contract; 219 | Order order; 220 | 221 | contract.symbol = "EUR"; 222 | contract.secType = "CASH"; 223 | contract.exchange = "IDEALPRO"; 224 | contract.currency = "USD"; 225 | 226 | order.action = "BUY"; 227 | order.totalQuantity = 20000; 228 | order.orderType = "LMT"; 229 | order.lmtPrice = m_lastPrice; 230 | 231 | cout<<"Placing Order"<placeOrder( m_orderId, contract, order); 236 | 237 | m_orderId++; 238 | } 239 | 240 | void UnitTest::cancelOrder() 241 | { 242 | cout<<"Cancelling Order %ld\n"<cancelOrder( m_orderId); 247 | } 248 | 249 | /////////////////////////////////////////////////////////////////// 250 | // events 251 | void UnitTest::orderStatus( OrderId orderId, const IBString &status, int filled, 252 | int remaining, double avgFillPrice, int permId, int parentId, 253 | double lastFillPrice, int clientId, const IBString& whyHeld) 254 | 255 | { 256 | /* 257 | if( orderId == m_orderId) { 258 | if( m_state == ST_PLACEORDER_ACK && (status == "PreSubmitted" || status == "Submitted")) 259 | m_state = ST_CANCELORDER; 260 | 261 | if( m_state == ST_CANCELORDER_ACK && status == "Cancelled") 262 | m_state = ST_PING; 263 | 264 | cout<<"Order: id=%ld, status=%s\n"< 1 ? argv[1] : ""; 375 | unsigned int port = 7496; 376 | int clientId = 0; 377 | 378 | cout<<"Start of POSIX Socket Client Test\n"< 7 | 8 | class EPosixClientSocket; 9 | enum State { 10 | ST_CONNECT, 11 | ST_PLACETAIL, 12 | ST_PLACETAIL_ACK, 13 | ST_PLACEORDER, 14 | ST_PLACEORDER_ACK, 15 | ST_CANCELORDER, 16 | ST_CANCELORDER_ACK, 17 | ST_PING, 18 | ST_PING_ACK, 19 | ST_IDLE, 20 | ST_REQ_DATA, 21 | ST_REQ_DATA_ACK 22 | }; 23 | 24 | class UnitTest : public EWrapper 25 | { 26 | public: 27 | 28 | UnitTest(); 29 | ~UnitTest(); 30 | 31 | bool connect(const char * host, unsigned int port, int clientId = 0); 32 | void disconnect() const; 33 | bool isConnected() const; 34 | void reqCurrentTime(); 35 | void placeOrder(); 36 | void cancelOrder(); 37 | void requestData(); 38 | void placeTail(); 39 | void processMessages(); 40 | 41 | // events 42 | void tickPrice(TickerId tickerId, TickType field, double price, int canAutoExecute); 43 | void tickSize(TickerId tickerId, TickType field, int size); 44 | void tickOptionComputation( TickerId tickerId, TickType tickType, double impliedVol, double delta, 45 | double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice); 46 | void tickGeneric(TickerId tickerId, TickType tickType, double value); 47 | void tickString(TickerId tickerId, TickType tickType, const IBString& value); 48 | void tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const IBString& formattedBasisPoints, 49 | double totalDividends, int holdDays, const IBString& futureExpiry, double dividendImpact, double dividendsToExpiry); 50 | void orderStatus(OrderId orderId, const IBString &status, int filled, 51 | int remaining, double avgFillPrice, int permId, int parentId, 52 | double lastFillPrice, int clientId, const IBString& whyHeld); 53 | void openOrder(OrderId orderId, const Contract&, const Order&, const OrderState&); 54 | void openOrderEnd(); 55 | void winError(const IBString &str, int lastError); 56 | void connectionClosed(); 57 | void updateAccountValue(const IBString& key, const IBString& val, 58 | const IBString& currency, const IBString& accountName); 59 | void updatePortfolio(const Contract& contract, int position, 60 | double marketPrice, double marketValue, double averageCost, 61 | double unrealizedPNL, double realizedPNL, const IBString& accountName); 62 | void updateAccountTime(const IBString& timeStamp); 63 | void accountDownloadEnd(const IBString& accountName); 64 | void nextValidId(OrderId orderId); 65 | void contractDetails(int reqId, const ContractDetails& contractDetails); 66 | void bondContractDetails(int reqId, const ContractDetails& contractDetails); 67 | void contractDetailsEnd(int reqId); 68 | void execDetails(int reqId, const Contract& contract, const Execution& execution); 69 | void execDetailsEnd(int reqId); 70 | void error(const int id, const int errorCode, const IBString errorString); 71 | void updateMktDepth(TickerId id, int position, int operation, int side, 72 | double price, int size); 73 | void updateMktDepthL2(TickerId id, int position, IBString marketMaker, int operation, 74 | int side, double price, int size); 75 | void updateNewsBulletin(int msgId, int msgType, const IBString& newsMessage, const IBString& originExch); 76 | void managedAccounts(const IBString& accountsList); 77 | void receiveFA(faDataType pFaDataType, const IBString& cxml); 78 | void historicalData(TickerId reqId, const IBString& date, double open, double high, 79 | double low, double close, int volume, int barCount, double WAP, int hasGaps); 80 | void scannerParameters(const IBString &xml); 81 | void scannerData(int reqId, int rank, const ContractDetails &contractDetails, 82 | const IBString &distance, const IBString &benchmark, const IBString &projection, 83 | const IBString &legsStr); 84 | void scannerDataEnd(int reqId); 85 | void realtimeBar(TickerId reqId, long time, double open, double high, double low, double close, 86 | long volume, double wap, int count); 87 | void currentTime(long time); 88 | void fundamentalData(TickerId reqId, const IBString& data); 89 | void deltaNeutralValidation(int reqId, const UnderComp& underComp); 90 | void tickSnapshotEnd(int reqId); 91 | void marketDataType(TickerId reqId, int marketDataType); 92 | 93 | private: 94 | 95 | std::auto_ptr m_pClient; 96 | State m_state; 97 | time_t m_sleepDeadline; 98 | int m_buySignal; 99 | double m_lastPrice; 100 | OrderId m_orderId; 101 | OrderId m_tickId; 102 | OrderId m_pendingOrder; 103 | }; 104 | 105 | #endif 106 | 107 | --------------------------------------------------------------------------------