修改vn.ib下的IB API到最新的9.72版本

This commit is contained in:
chenxy123 2016-11-12 00:42:37 +08:00
parent 8e658868b2
commit 745e716728
164 changed files with 10613 additions and 520 deletions

85
vn.ib/CMakeLists.txt Normal file
View File

@ -0,0 +1,85 @@
cmake_minimum_required(VERSION 2.8)
project(vn_ib_api)
# 使
set(CMAKE_BUILD_TYPE "Release")
if (CMAKE_COMPILER_IS_GNUC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++11")
endif ()
#
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
# 使64
option(USE_64BITS "comiple 64bits" ON)
if (USE_64BITS)
add_definitions(-DUSE_64BITS)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
endif()
# C++ API
if (WIN32)
set(IBAPI_PATH ibapi)
elseif (UNIX)
message("Under unix: " ${CMAKE_SIZEOF_VOID_P})
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
set(IBAPI_PATH ibapi)
endif()
endif()
include_directories(${IBAPI_PATH})
#set(IBAPI_LIBRARY )
#find_library(IBAPI_LIBRARY
# NAMES thostmduserapi
# PATHS ${IBAPI_PATH})
#find_library(IBAPI_TD_LIBRARY
# NAMES thosttraderapi
# PATHS ${IBAPI_PATH})
#
set (vnib )
option(BUILD_IB "build ib" ON)
if (BUILD_IB)
add_definitions(-DBUILD_IB)
set(IB_PATH vnib/vnib)
include_directories(IB_PATH)
set(VN_IB_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/vnib/vnib/vnib.cpp)
add_library(vnib SHARED ${VN_IB_SOURCE})
endif()
# Python
set(PYTHON_LIBRARY )
if (WIN32)
set(PYTHON_INCLUDE_PATH C:/Python27/include)
find_library(PYTHON_LIBRARY
NAMES python27
PATHS C:/Python27/libs)
include_directories(${PYTHON_INCLUDE_PATH})
else()
set(PYTHON_INCLUDE_PATH /usr/include/python2.7/)
find_library(PYTHON_LIBRARY
NAMES python2.7
PATHS /usr/lib/x86_64-linux-gnu)
include_directories(${PYTHON_INCLUDE_PATH})
endif()
# boostanaconda
if (WIN32)
set(Boost_USE_STATIC_LIBS ON) #boost
endif()
set(Boost_USE_MULTITHREADED ON)
find_package(Boost 1.55.0 COMPONENTS python thread date_time system chrono REQUIRED) # boost否者message(${Boost_LIBRARIES})
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
endif()
# solib
set_target_properties(vnib PROPERTIES PREFIX "")
# .so
target_link_libraries(vnib ${Boost_LIBRARIES} ${PYTHON_LIBRARY} ${IBAPI_LIBRARY})

View File

@ -14,8 +14,13 @@
4. vn.ib基于较新的IB官方API9.72 beta开发IbPy则是采用了较老的API9.70 stable 4. vn.ib基于较新的IB官方API9.72 beta开发IbPy则是采用了较老的API9.70 stable
### 对原生接口的修改部分
shared_ptr.h和SoftDollerTier.h中加入了对象比较函数的代码用于实现其对应vector的自动Python封装。
### API版本 ### API版本
版本IB API for Windows beta 9.72 版本IB API for Windows beta 9.72.18
日期2016-09-14
链接:[http://interactivebrokers.github.io/](http://interactivebrokers.github.io/) 链接:[http://interactivebrokers.github.io/](http://interactivebrokers.github.io/)

13
vn.ib/build.sh Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
# Written by Suzhengchun on 20160213
set -e
BUILDDIR=build
rm -rf $BUILDDIR
if [ ! -f $BUILDDIR ]; then
mkdir -p $BUILDDIR
fi
pushd $BUILDDIR
cmake ..
make VERBOSE=1 -j 1
popd

View File

@ -1,224 +0,0 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef eclient_h__INCLUDED
#define eclient_h__INCLUDED
#include <memory>
#include <string>
#include <vector>
#include <iosfwd>
#include "CommonDefs.h"
#include "TagValue.h"
struct Contract;
struct Order;
struct ExecutionFilter;
struct ScannerSubscription;
struct ETransport;
class EWrapper;
typedef std::vector<char> BytesVec;
class TWSAPIDLLEXP EClient
{
public:
explicit EClient(EWrapper *ptr, ETransport *pTransport);
~EClient();
virtual void eDisconnect() = 0;
int clientId() const { return m_clientId; }
const std::string& optionalCapabilities() const;
void setOptionalCapabilities(const std::string& optCapts);
void setConnectOptions(const std::string& connectOptions);
void disableUseV100Plus();
bool usingV100Plus();
protected:
void eConnectBase();
void eDisconnectBase();
public:
enum ConnState {
CS_DISCONNECTED,
CS_CONNECTING,
CS_CONNECTED,
CS_REDIRECT
};
// connection state
ConnState connState() const;
bool isConnected() const;
const std::string& host() const { return m_host; }
unsigned port() const { return m_port; }
public:
// access to protected variables
EWrapper * getWrapper() const;
protected:
void setClientId( int clientId);
void setExtraAuth( bool extraAuth);
void setHost( const std::string& host);
void setPort( unsigned port);
public:
bool isInBufferEmpty() const;
// override virtual funcs from EClient
int serverVersion();
std::string TwsConnectionTime();
void reqMktData(TickerId id, const Contract& contract,
const std::string& genericTicks, bool snapshot, const TagValueListSPtr& mktDataOptions);
void cancelMktData(TickerId id);
void placeOrder(OrderId id, const Contract& contract, const Order& order);
void cancelOrder(OrderId id) ;
void reqOpenOrders();
void reqAccountUpdates(bool subscribe, const std::string& acctCode);
void reqExecutions(int reqId, const ExecutionFilter& filter);
void reqIds(int numIds);
void reqContractDetails(int reqId, const Contract& contract);
void reqMktDepth(TickerId tickerId, const Contract& contract, int numRows, const TagValueListSPtr& mktDepthOptions);
void cancelMktDepth(TickerId tickerId);
void reqNewsBulletins(bool allMsgs);
void cancelNewsBulletins();
void setServerLogLevel(int level);
void reqAutoOpenOrders(bool bAutoBind);
void reqAllOpenOrders();
void reqManagedAccts();
void requestFA(faDataType pFaDataType);
void replaceFA(faDataType pFaDataType, const std::string& cxml);
void reqHistoricalData( TickerId id, const Contract& contract,
const std::string& endDateTime, const std::string& durationStr,
const std::string& barSizeSetting, const std::string& whatToShow,
int useRTH, int formatDate, const TagValueListSPtr& chartOptions);
void exerciseOptions(TickerId tickerId, const Contract& contract,
int exerciseAction, int exerciseQuantity,
const std::string& account, int override);
void cancelHistoricalData(TickerId tickerId );
void reqRealTimeBars(TickerId id, const Contract& contract, int barSize,
const std::string& whatToShow, bool useRTH, const TagValueListSPtr& realTimeBarsOptions);
void cancelRealTimeBars(TickerId tickerId );
void cancelScannerSubscription(int tickerId);
void reqScannerParameters();
void reqScannerSubscription(int tickerId, const ScannerSubscription& subscription, const TagValueListSPtr& scannerSubscriptionOptions);
void reqCurrentTime();
void reqFundamentalData(TickerId reqId, const Contract&, const std::string& reportType);
void cancelFundamentalData(TickerId reqId);
void calculateImpliedVolatility(TickerId reqId, const Contract& contract, double optionPrice, double underPrice);
void calculateOptionPrice(TickerId reqId, const Contract& contract, double volatility, double underPrice);
void cancelCalculateImpliedVolatility(TickerId reqId);
void cancelCalculateOptionPrice(TickerId reqId);
void reqGlobalCancel();
void reqMarketDataType(int marketDataType);
void reqPositions();
void cancelPositions();
void reqAccountSummary( int reqId, const std::string& groupName, const std::string& tags);
void cancelAccountSummary( int reqId);
void verifyRequest( const std::string& apiName, const std::string& apiVersion);
void verifyMessage( const std::string& apiData);
void verifyAndAuthRequest( const std::string& apiName, const std::string& apiVersion, const std::string& opaqueIsvKey);
void verifyAndAuthMessage( const std::string& apiData, const std::string& xyzResponse);
void queryDisplayGroups( int reqId);
void subscribeToGroupEvents( int reqId, int groupId);
void updateDisplayGroup( int reqId, const std::string& contractInfo);
void unsubscribeFromGroupEvents( int reqId);
void reqPositionsMulti( int reqId, const std::string& account, const std::string& modelCode);
void cancelPositionsMulti( int reqId);
void reqAccountUpdatessMulti( int reqId, const std::string& account, const std::string& modelCode, bool ledgerAndNLV);
void cancelAccountUpdatesMulti( int reqId);
void reqSecDefOptParams(int reqId, const std::string& underlyingSymbol, const std::string& futFopExchange, const std::string& underlyingSecType, int underlyingConId);
private:
virtual int receive(char* buf, size_t sz) = 0;
protected:
virtual void prepareBufferImpl(std::ostream&) const = 0;
virtual void prepareBuffer(std::ostream&) const = 0;
virtual bool closeAndSend(std::string msg, unsigned offset = 0) = 0;
virtual int bufferedSend(const std::string& msg);
protected:
int bufferedRead();
// try to process connection request ack
private:
// try to process single msg
int processMsgImpl(const char*& ptr, const char* endPtr);
int processMsg(const char*& ptr, const char* endPtr);
typedef int (EClient::*messageHandler)(const char*& ptr, const char* endPtr);
int processOnePrefixedMsg(const char*& ptr, const char* endPtr, messageHandler);
public:
void startApi();
// encoders
template<class T> static void EncodeField(std::ostream&, T);
// "max" encoders
static void EncodeFieldMax(std::ostream& os, int);
static void EncodeFieldMax(std::ostream& os, double);
// socket state
private:
virtual bool isSocketOK() const = 0;
protected:
bool isConnecting() const;
int sendConnectRequest();
bool extraAuth();
protected:
EWrapper *m_pEWrapper;
std::auto_ptr<ETransport> m_transport;
private:
BytesVec m_inBuffer;
std::string m_host;
int m_port;
int m_clientId;
ConnState m_connState;
bool m_extraAuth;
protected:
int m_serverVersion;
std::string m_TwsTime;
private:
std::string m_optionalCapabilities;
std::string m_connectOptions;
protected:
bool m_useV100Plus;
};
template<> void EClient::EncodeField<bool>(std::ostream& os, bool);
template<> void EClient::EncodeField<double>(std::ostream& os, double);
#define ENCODE_FIELD(x) EClient::EncodeField(msg, x);
#define ENCODE_FIELD_MAX(x) EClient::EncodeFieldMax(msg, x);
#endif

Binary file not shown.

View File

@ -72,5 +72,6 @@ void DefaultEWrapper::accountUpdateMulti( int reqId, const std::string& account,
void DefaultEWrapper::accountUpdateMultiEnd( int reqId) { } void DefaultEWrapper::accountUpdateMultiEnd( int reqId) { }
void DefaultEWrapper::securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes) { } void DefaultEWrapper::securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes) { }
void DefaultEWrapper::securityDefinitionOptionalParameterEnd(int reqId) { } void DefaultEWrapper::securityDefinitionOptionalParameterEnd(int reqId) { }
void DefaultEWrapper::softDollarTiers(int reqId, const std::vector<SoftDollarTier> &tiers) { }

View File

@ -76,5 +76,6 @@ public:
virtual void accountUpdateMultiEnd( int reqId); virtual void accountUpdateMultiEnd( int reqId);
virtual void securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes); virtual void securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes);
virtual void securityDefinitionOptionalParameterEnd(int reqId); virtual void securityDefinitionOptionalParameterEnd(int reqId);
virtual void softDollarTiers(int reqId, const std::vector<SoftDollarTier> &tiers);
}; };

View File

@ -27,157 +27,7 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
///////////////////////////////////////////////////////////////////////////////// using namespace ibapi::client_constants;
// SOCKET CLIENT VERSION CHANGE LOG : Incremented when the format of incomming
// server responses change
/////////////////////////////////////////////////////////////////////////////////
// constants
// 6 = Added parentId to orderStatus
// 7 = The new execDetails event returned for an order filled status and reqExecDetails
// Also added market depth support.
// 8 = Added 'lastFillPrice' to orderStatus and 'permId' to execDetails
// 9 = Added 'avgCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event
// 10 = Added 'serverId' to the 'open order' & 'order status' events.
// We send back all the API open orders upon connection.
// Added new methods reqAllOpenOrders, reqAutoOpenOrders()
// Added FA support - reqExecution has filter.
// - reqAccountUpdates takes acct code.
// 11 = Added permId to openOrder event.
// 12 = Added IgnoreRth, hidden, and discretionaryAmt
// 13 = Added GoodAfterTime
// 14 = always send size on bid/ask/last tick
// 15 = send allocation string with open order
// 16 = can receive account name in account and portfolio updates, and fa params in openOrder
// 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data
// 18 = can receive good till date field in open order messages, and send backfill requests
// 19 = can receive new extended order attributes in OPEN_ORDER
// 20 = expects TWS time string on connection after server version >= 20, and parentId in open order
// 21 = can receive bond contract details.
// 22 = can receive price magnifier in contract details
// 23 = support for scanner
// 24 = can receive volatility order parameters in open order messages
// 25 = can receive HMDS query start and end times
// 26 = can receive option vols in option market data messages
// 27 = can receive delta neutral order type and delta neutral aux price
// 28 = can receive option model computation ticks
// 29 = can receive trail stop limit price in open order and can place them: API 8.91
// 30 = can receive extended bond contract def, new ticks, and trade count in bars
// 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders
// ; can receive RT bars
// 32 = can receive TickType.LAST_TIMESTAMP
// 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages
// 34 = can receive whatIf orders / order state
// 35 = can receive contId field for Contract objects
// 36 = can receive outsideRth field for Order objects
// 37 = can receive clearingAccount and clearingIntent for Order objects
// 38 = can receive multipier and primaryExchange in portfolio updates
// ; can receive cumQty and avgPrice in execution
// ; can receive fundamental data
// ; can receive underComp for Contract objects
// ; can receive reqId and end marker in contractDetails/bondContractDetails
// ; can receive ScaleInitComponentSize and ScaleSubsComponentSize for Order objects
// 39 = can receive underConId in contractDetails
// 40 = can receive algoStrategy/algoParams in openOrder
// 41 = can receive end marker for openOrder
// ; can receive end marker for account download
// ; can receive end marker for executions download
// 42 = can receive deltaNeutralValidation
// 43 = can receive longName(companyName)
// ; can receive listingExchange
// ; can receive RTVolume tick
// 44 = can receive end market for ticker snapshot
// 45 = can receive notHeld field in openOrder
// 46 = can receive contractMonth, industry, category, subcategory fields in contractDetails
// ; can receive timeZoneId, tradingHours, liquidHours fields in contractDetails
// 47 = can receive gamma, vega, theta, undPrice fields in TICK_OPTION_COMPUTATION
// 48 = can receive exemptCode in openOrder
// 49 = can receive hedgeType and hedgeParam in openOrder
// 50 = can receive optOutSmartRouting field in openOrder
// 51 = can receive smartComboRoutingParams in openOrder
// 52 = can receive deltaNeutralConId, deltaNeutralSettlingFirm, deltaNeutralClearingAccount and deltaNeutralClearingIntent in openOrder
// 53 = can receive orderRef in execution
// 54 = can receive scale order fields (PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset,
// InitPosition, InitFillQty and RandomPercent) in openOrder
// 55 = can receive orderComboLegs (price) in openOrder
// 56 = can receive trailingPercent in openOrder
// 57 = can receive commissionReport message
// 58 = can receive CUSIP/ISIN/etc. in contractDescription/bondContractDescription
// 59 = can receive evRule, evMultiplier in contractDescription/bondContractDescription/executionDetails
// can receive multiplier in executionDetails
// 60 = can receive deltaNeutralOpenClose, deltaNeutralShortSale, deltaNeutralShortSaleSlot
// and deltaNeutralDesignatedLocation in openOrder
// can receive position, positionEnd, accountSummary and accountSummaryEnd
// 61 = can receive multiplier in openOrder
// can receive tradingClass in openOrder, updatePortfolio, execDetails and position
// 62 = can receive avgCost in position message
// 63 = can receive verifyMessageAPI, verifyCompleted, displayGroupList and displayGroupUpdated messages
// 64 = can receive solicited attrib in openOrder message
// 65 = can receive verifyAndAuthMessageAPI and verifyAndAuthCompleted messages
// 66 = can receive randomize size and randomize price order fields
const int CLIENT_VERSION = 66;
// outgoing msg id's
const int REQ_MKT_DATA = 1;
const int CANCEL_MKT_DATA = 2;
const int PLACE_ORDER = 3;
const int CANCEL_ORDER = 4;
const int REQ_OPEN_ORDERS = 5;
const int REQ_ACCT_DATA = 6;
const int REQ_EXECUTIONS = 7;
const int REQ_IDS = 8;
const int REQ_CONTRACT_DATA = 9;
const int REQ_MKT_DEPTH = 10;
const int CANCEL_MKT_DEPTH = 11;
const int REQ_NEWS_BULLETINS = 12;
const int CANCEL_NEWS_BULLETINS = 13;
const int SET_SERVER_LOGLEVEL = 14;
const int REQ_AUTO_OPEN_ORDERS = 15;
const int REQ_ALL_OPEN_ORDERS = 16;
const int REQ_MANAGED_ACCTS = 17;
const int REQ_FA = 18;
const int REPLACE_FA = 19;
const int REQ_HISTORICAL_DATA = 20;
const int EXERCISE_OPTIONS = 21;
const int REQ_SCANNER_SUBSCRIPTION = 22;
const int CANCEL_SCANNER_SUBSCRIPTION = 23;
const int REQ_SCANNER_PARAMETERS = 24;
const int CANCEL_HISTORICAL_DATA = 25;
const int REQ_CURRENT_TIME = 49;
const int REQ_REAL_TIME_BARS = 50;
const int CANCEL_REAL_TIME_BARS = 51;
const int REQ_FUNDAMENTAL_DATA = 52;
const int CANCEL_FUNDAMENTAL_DATA = 53;
const int REQ_CALC_IMPLIED_VOLAT = 54;
const int REQ_CALC_OPTION_PRICE = 55;
const int CANCEL_CALC_IMPLIED_VOLAT = 56;
const int CANCEL_CALC_OPTION_PRICE = 57;
const int REQ_GLOBAL_CANCEL = 58;
const int REQ_MARKET_DATA_TYPE = 59;
const int REQ_POSITIONS = 61;
const int REQ_ACCOUNT_SUMMARY = 62;
const int CANCEL_ACCOUNT_SUMMARY = 63;
const int CANCEL_POSITIONS = 64;
const int VERIFY_REQUEST = 65;
const int VERIFY_MESSAGE = 66;
const int QUERY_DISPLAY_GROUPS = 67;
const int SUBSCRIBE_TO_GROUP_EVENTS = 68;
const int UPDATE_DISPLAY_GROUP = 69;
const int UNSUBSCRIBE_FROM_GROUP_EVENTS = 70;
const int START_API = 71;
const int VERIFY_AND_AUTH_REQUEST = 72;
const int VERIFY_AND_AUTH_MESSAGE = 73;
const int REQ_POSITIONS_MULTI = 74;
const int CANCEL_POSITIONS_MULTI = 75;
const int REQ_ACCOUNT_UPDATES_MULTI = 76;
const int CANCEL_ACCOUNT_UPDATES_MULTI = 77;
const int REQ_SEC_DEF_OPT_PARAMS = 78;
// TWS New Bulletins constants
const int NEWS_MSG = 1; // standard IB news bulleting message
const int EXCHANGE_AVAIL_MSG = 2; // control message specifing that an exchange is available for trading
const int EXCHANGE_UNAVAIL_MSG = 3; // control message specifing that an exchange is unavailable for trading
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// encoders // encoders
@ -1507,6 +1357,17 @@ void EClient::placeOrder( OrderId id, const Contract& contract, const Order& ord
} }
} }
if (m_serverVersion < MIN_SERVER_VER_SOFT_DOLLAR_TIER)
{
if (!order.softDollarTier.name().empty() || !order.softDollarTier.val().empty())
{
m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
" It does not support soft dollar tier");
return;
}
}
std::stringstream msg; std::stringstream msg;
prepareBuffer( msg); prepareBuffer( msg);
@ -1896,6 +1757,11 @@ void EClient::placeOrder( OrderId id, const Contract& contract, const Order& ord
ENCODE_FIELD( order.extOperator); ENCODE_FIELD( order.extOperator);
} }
if (m_serverVersion >= MIN_SERVER_VER_SOFT_DOLLAR_TIER) {
ENCODE_FIELD(order.softDollarTier.name());
ENCODE_FIELD(order.softDollarTier.val());
}
closeAndSend( msg.str()); closeAndSend( msg.str());
} }
@ -2820,6 +2686,23 @@ void EClient::reqSecDefOptParams(int reqId, const std::string& underlyingSymbol,
closeAndSend(msg.str()); closeAndSend(msg.str());
} }
void EClient::reqSoftDollarTiers(int reqId)
{
if( !isConnected()) {
m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
return;
}
std::stringstream msg;
prepareBuffer(msg);
ENCODE_FIELD(REQ_SOFT_DOLLAR_TIERS);
ENCODE_FIELD(reqId);
closeAndSend(msg.str());
}
int EClient::processMsgImpl(const char*& beginPtr, const char* endPtr) int EClient::processMsgImpl(const char*& beginPtr, const char* endPtr)
{ {
EDecoder decoder(serverVersion(), m_pEWrapper); EDecoder decoder(serverVersion(), m_pEWrapper);

View File

@ -0,0 +1,384 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef eclient_h__INCLUDED
#define eclient_h__INCLUDED
#include <memory>
#include <string>
#include <vector>
#include <iosfwd>
#include "CommonDefs.h"
#include "TagValue.h"
namespace ibapi {
namespace client_constants {
/////////////////////////////////////////////////////////////////////////////////
// SOCKET CLIENT VERSION CHANGE LOG : Incremented when the format of incomming
// server responses change
/////////////////////////////////////////////////////////////////////////////////
// constants
// 6 = Added parentId to orderStatus
// 7 = The new execDetails event returned for an order filled status and reqExecDetails
// Also added market depth support.
// 8 = Added 'lastFillPrice' to orderStatus and 'permId' to execDetails
// 9 = Added 'avgCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event
// 10 = Added 'serverId' to the 'open order' & 'order status' events.
// We send back all the API open orders upon connection.
// Added new methods reqAllOpenOrders, reqAutoOpenOrders()
// Added FA support - reqExecution has filter.
// - reqAccountUpdates takes acct code.
// 11 = Added permId to openOrder event.
// 12 = Added IgnoreRth, hidden, and discretionaryAmt
// 13 = Added GoodAfterTime
// 14 = always send size on bid/ask/last tick
// 15 = send allocation string with open order
// 16 = can receive account name in account and portfolio updates, and fa params in openOrder
// 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data
// 18 = can receive good till date field in open order messages, and send backfill requests
// 19 = can receive new extended order attributes in OPEN_ORDER
// 20 = expects TWS time string on connection after server version >= 20, and parentId in open order
// 21 = can receive bond contract details.
// 22 = can receive price magnifier in contract details
// 23 = support for scanner
// 24 = can receive volatility order parameters in open order messages
// 25 = can receive HMDS query start and end times
// 26 = can receive option vols in option market data messages
// 27 = can receive delta neutral order type and delta neutral aux price
// 28 = can receive option model computation ticks
// 29 = can receive trail stop limit price in open order and can place them: API 8.91
// 30 = can receive extended bond contract def, new ticks, and trade count in bars
// 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders
// ; can receive RT bars
// 32 = can receive TickType.LAST_TIMESTAMP
// 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages
// 34 = can receive whatIf orders / order state
// 35 = can receive contId field for Contract objects
// 36 = can receive outsideRth field for Order objects
// 37 = can receive clearingAccount and clearingIntent for Order objects
// 38 = can receive multipier and primaryExchange in portfolio updates
// ; can receive cumQty and avgPrice in execution
// ; can receive fundamental data
// ; can receive underComp for Contract objects
// ; can receive reqId and end marker in contractDetails/bondContractDetails
// ; can receive ScaleInitComponentSize and ScaleSubsComponentSize for Order objects
// 39 = can receive underConId in contractDetails
// 40 = can receive algoStrategy/algoParams in openOrder
// 41 = can receive end marker for openOrder
// ; can receive end marker for account download
// ; can receive end marker for executions download
// 42 = can receive deltaNeutralValidation
// 43 = can receive longName(companyName)
// ; can receive listingExchange
// ; can receive RTVolume tick
// 44 = can receive end market for ticker snapshot
// 45 = can receive notHeld field in openOrder
// 46 = can receive contractMonth, industry, category, subcategory fields in contractDetails
// ; can receive timeZoneId, tradingHours, liquidHours fields in contractDetails
// 47 = can receive gamma, vega, theta, undPrice fields in TICK_OPTION_COMPUTATION
// 48 = can receive exemptCode in openOrder
// 49 = can receive hedgeType and hedgeParam in openOrder
// 50 = can receive optOutSmartRouting field in openOrder
// 51 = can receive smartComboRoutingParams in openOrder
// 52 = can receive deltaNeutralConId, deltaNeutralSettlingFirm, deltaNeutralClearingAccount and deltaNeutralClearingIntent in openOrder
// 53 = can receive orderRef in execution
// 54 = can receive scale order fields (PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset,
// InitPosition, InitFillQty and RandomPercent) in openOrder
// 55 = can receive orderComboLegs (price) in openOrder
// 56 = can receive trailingPercent in openOrder
// 57 = can receive commissionReport message
// 58 = can receive CUSIP/ISIN/etc. in contractDescription/bondContractDescription
// 59 = can receive evRule, evMultiplier in contractDescription/bondContractDescription/executionDetails
// can receive multiplier in executionDetails
// 60 = can receive deltaNeutralOpenClose, deltaNeutralShortSale, deltaNeutralShortSaleSlot
// and deltaNeutralDesignatedLocation in openOrder
// can receive position, positionEnd, accountSummary and accountSummaryEnd
// 61 = can receive multiplier in openOrder
// can receive tradingClass in openOrder, updatePortfolio, execDetails and position
// 62 = can receive avgCost in position message
// 63 = can receive verifyMessageAPI, verifyCompleted, displayGroupList and displayGroupUpdated messages
// 64 = can receive solicited attrib in openOrder message
// 65 = can receive verifyAndAuthMessageAPI and verifyAndAuthCompleted messages
// 66 = can receive randomize size and randomize price order fields
const int CLIENT_VERSION = 66;
// outgoing msg id's
const int REQ_MKT_DATA = 1;
const int CANCEL_MKT_DATA = 2;
const int PLACE_ORDER = 3;
const int CANCEL_ORDER = 4;
const int REQ_OPEN_ORDERS = 5;
const int REQ_ACCT_DATA = 6;
const int REQ_EXECUTIONS = 7;
const int REQ_IDS = 8;
const int REQ_CONTRACT_DATA = 9;
const int REQ_MKT_DEPTH = 10;
const int CANCEL_MKT_DEPTH = 11;
const int REQ_NEWS_BULLETINS = 12;
const int CANCEL_NEWS_BULLETINS = 13;
const int SET_SERVER_LOGLEVEL = 14;
const int REQ_AUTO_OPEN_ORDERS = 15;
const int REQ_ALL_OPEN_ORDERS = 16;
const int REQ_MANAGED_ACCTS = 17;
const int REQ_FA = 18;
const int REPLACE_FA = 19;
const int REQ_HISTORICAL_DATA = 20;
const int EXERCISE_OPTIONS = 21;
const int REQ_SCANNER_SUBSCRIPTION = 22;
const int CANCEL_SCANNER_SUBSCRIPTION = 23;
const int REQ_SCANNER_PARAMETERS = 24;
const int CANCEL_HISTORICAL_DATA = 25;
const int REQ_CURRENT_TIME = 49;
const int REQ_REAL_TIME_BARS = 50;
const int CANCEL_REAL_TIME_BARS = 51;
const int REQ_FUNDAMENTAL_DATA = 52;
const int CANCEL_FUNDAMENTAL_DATA = 53;
const int REQ_CALC_IMPLIED_VOLAT = 54;
const int REQ_CALC_OPTION_PRICE = 55;
const int CANCEL_CALC_IMPLIED_VOLAT = 56;
const int CANCEL_CALC_OPTION_PRICE = 57;
const int REQ_GLOBAL_CANCEL = 58;
const int REQ_MARKET_DATA_TYPE = 59;
const int REQ_POSITIONS = 61;
const int REQ_ACCOUNT_SUMMARY = 62;
const int CANCEL_ACCOUNT_SUMMARY = 63;
const int CANCEL_POSITIONS = 64;
const int VERIFY_REQUEST = 65;
const int VERIFY_MESSAGE = 66;
const int QUERY_DISPLAY_GROUPS = 67;
const int SUBSCRIBE_TO_GROUP_EVENTS = 68;
const int UPDATE_DISPLAY_GROUP = 69;
const int UNSUBSCRIBE_FROM_GROUP_EVENTS = 70;
const int START_API = 71;
const int VERIFY_AND_AUTH_REQUEST = 72;
const int VERIFY_AND_AUTH_MESSAGE = 73;
const int REQ_POSITIONS_MULTI = 74;
const int CANCEL_POSITIONS_MULTI = 75;
const int REQ_ACCOUNT_UPDATES_MULTI = 76;
const int CANCEL_ACCOUNT_UPDATES_MULTI = 77;
const int REQ_SEC_DEF_OPT_PARAMS = 78;
const int REQ_SOFT_DOLLAR_TIERS = 79;
// TWS New Bulletins constants
const int NEWS_MSG = 1; // standard IB news bulleting message
const int EXCHANGE_AVAIL_MSG = 2; // control message specifing that an exchange is available for trading
const int EXCHANGE_UNAVAIL_MSG = 3; // control message specifing that an exchange is unavailable for trading
} // namespace client_constants
} // namespace ibapi
struct Contract;
struct Order;
struct ExecutionFilter;
struct ScannerSubscription;
struct ETransport;
class EWrapper;
typedef std::vector<char> BytesVec;
class TWSAPIDLLEXP EClient
{
public:
explicit EClient(EWrapper *ptr, ETransport *pTransport);
~EClient();
virtual void eDisconnect() = 0;
int clientId() const { return m_clientId; }
const std::string& optionalCapabilities() const;
void setOptionalCapabilities(const std::string& optCapts);
void setConnectOptions(const std::string& connectOptions);
void disableUseV100Plus();
bool usingV100Plus();
protected:
void eConnectBase();
void eDisconnectBase();
public:
enum ConnState {
CS_DISCONNECTED,
CS_CONNECTING,
CS_CONNECTED,
CS_REDIRECT
};
// connection state
ConnState connState() const;
bool isConnected() const;
const std::string& host() const { return m_host; }
unsigned port() const { return m_port; }
public:
// access to protected variables
EWrapper * getWrapper() const;
protected:
void setClientId( int clientId);
void setExtraAuth( bool extraAuth);
void setHost( const std::string& host);
void setPort( unsigned port);
public:
bool isInBufferEmpty() const;
// override virtual funcs from EClient
int serverVersion();
std::string TwsConnectionTime();
void reqMktData(TickerId id, const Contract& contract,
const std::string& genericTicks, bool snapshot, const TagValueListSPtr& mktDataOptions);
void cancelMktData(TickerId id);
void placeOrder(OrderId id, const Contract& contract, const Order& order);
void cancelOrder(OrderId id) ;
void reqOpenOrders();
void reqAccountUpdates(bool subscribe, const std::string& acctCode);
void reqExecutions(int reqId, const ExecutionFilter& filter);
void reqIds(int numIds);
void reqContractDetails(int reqId, const Contract& contract);
void reqMktDepth(TickerId tickerId, const Contract& contract, int numRows, const TagValueListSPtr& mktDepthOptions);
void cancelMktDepth(TickerId tickerId);
void reqNewsBulletins(bool allMsgs);
void cancelNewsBulletins();
void setServerLogLevel(int level);
void reqAutoOpenOrders(bool bAutoBind);
void reqAllOpenOrders();
void reqManagedAccts();
void requestFA(faDataType pFaDataType);
void replaceFA(faDataType pFaDataType, const std::string& cxml);
void reqHistoricalData( TickerId id, const Contract& contract,
const std::string& endDateTime, const std::string& durationStr,
const std::string& barSizeSetting, const std::string& whatToShow,
int useRTH, int formatDate, const TagValueListSPtr& chartOptions);
void exerciseOptions(TickerId tickerId, const Contract& contract,
int exerciseAction, int exerciseQuantity,
const std::string& account, int override);
void cancelHistoricalData(TickerId tickerId );
void reqRealTimeBars(TickerId id, const Contract& contract, int barSize,
const std::string& whatToShow, bool useRTH, const TagValueListSPtr& realTimeBarsOptions);
void cancelRealTimeBars(TickerId tickerId );
void cancelScannerSubscription(int tickerId);
void reqScannerParameters();
void reqScannerSubscription(int tickerId, const ScannerSubscription& subscription, const TagValueListSPtr& scannerSubscriptionOptions);
void reqCurrentTime();
void reqFundamentalData(TickerId reqId, const Contract&, const std::string& reportType);
void cancelFundamentalData(TickerId reqId);
void calculateImpliedVolatility(TickerId reqId, const Contract& contract, double optionPrice, double underPrice);
void calculateOptionPrice(TickerId reqId, const Contract& contract, double volatility, double underPrice);
void cancelCalculateImpliedVolatility(TickerId reqId);
void cancelCalculateOptionPrice(TickerId reqId);
void reqGlobalCancel();
void reqMarketDataType(int marketDataType);
void reqPositions();
void cancelPositions();
void reqAccountSummary( int reqId, const std::string& groupName, const std::string& tags);
void cancelAccountSummary( int reqId);
void verifyRequest( const std::string& apiName, const std::string& apiVersion);
void verifyMessage( const std::string& apiData);
void verifyAndAuthRequest( const std::string& apiName, const std::string& apiVersion, const std::string& opaqueIsvKey);
void verifyAndAuthMessage( const std::string& apiData, const std::string& xyzResponse);
void queryDisplayGroups( int reqId);
void subscribeToGroupEvents( int reqId, int groupId);
void updateDisplayGroup( int reqId, const std::string& contractInfo);
void unsubscribeFromGroupEvents( int reqId);
void reqPositionsMulti( int reqId, const std::string& account, const std::string& modelCode);
void cancelPositionsMulti( int reqId);
void reqAccountUpdatessMulti( int reqId, const std::string& account, const std::string& modelCode, bool ledgerAndNLV);
void cancelAccountUpdatesMulti( int reqId);
void reqSecDefOptParams(int reqId, const std::string& underlyingSymbol, const std::string& futFopExchange, const std::string& underlyingSecType, int underlyingConId);
void reqSoftDollarTiers(int reqId);
private:
virtual int receive(char* buf, size_t sz) = 0;
protected:
virtual void prepareBufferImpl(std::ostream&) const = 0;
virtual void prepareBuffer(std::ostream&) const = 0;
virtual bool closeAndSend(std::string msg, unsigned offset = 0) = 0;
virtual int bufferedSend(const std::string& msg);
protected:
int bufferedRead();
// try to process connection request ack
private:
// try to process single msg
int processMsgImpl(const char*& ptr, const char* endPtr);
int processMsg(const char*& ptr, const char* endPtr);
typedef int (EClient::*messageHandler)(const char*& ptr, const char* endPtr);
int processOnePrefixedMsg(const char*& ptr, const char* endPtr, messageHandler);
public:
void startApi();
// encoders
template<class T> static void EncodeField(std::ostream&, T);
// "max" encoders
static void EncodeFieldMax(std::ostream& os, int);
static void EncodeFieldMax(std::ostream& os, double);
// socket state
private:
virtual bool isSocketOK() const = 0;
protected:
bool isConnecting() const;
int sendConnectRequest();
bool extraAuth();
protected:
EWrapper *m_pEWrapper;
std::auto_ptr<ETransport> m_transport;
private:
BytesVec m_inBuffer;
std::string m_host;
int m_port;
int m_clientId;
ConnState m_connState;
bool m_extraAuth;
protected:
int m_serverVersion;
std::string m_TwsTime;
private:
std::string m_optionalCapabilities;
std::string m_connectOptions;
protected:
bool m_useV100Plus;
};
template<> void EClient::EncodeField<bool>(std::ostream& os, bool);
template<> void EClient::EncodeField<double>(std::ostream& os, double);
#define ENCODE_FIELD(x) EClient::EncodeField(msg, x);
#define ENCODE_FIELD_MAX(x) EClient::EncodeFieldMax(msg, x);
#endif

View File

@ -642,6 +642,16 @@ const char* EDecoder::processOpenOrderMsg(const char* ptr, const char* endPtr) {
DECODE_FIELD(order.adjustableTrailingUnit); DECODE_FIELD(order.adjustableTrailingUnit);
} }
if (m_serverVersion >= MIN_SERVER_VER_SOFT_DOLLAR_TIER) {
std::string name, value, displayName;
DECODE_FIELD(name);
DECODE_FIELD(value);
DECODE_FIELD(displayName);
order.softDollarTier = SoftDollarTier(name, value, displayName);
}
m_pEWrapper->openOrder( (OrderId)order.orderId, contract, order, orderState); m_pEWrapper->openOrder( (OrderId)order.orderId, contract, order, orderState);
return ptr; return ptr;
@ -1585,7 +1595,7 @@ const char* EDecoder::processAccountUpdateMultiEndMsg(const char* ptr, const cha
return ptr; return ptr;
} }
const char* EDecoder::processSecurityDefinitionOptionalParameter(const char* ptr, const char* endPtr) { const char* EDecoder::processSecurityDefinitionOptionalParameterMsg(const char* ptr, const char* endPtr) {
int reqId; int reqId;
std::string exchange; std::string exchange;
int underlyingConId; int underlyingConId;
@ -1625,7 +1635,7 @@ const char* EDecoder::processSecurityDefinitionOptionalParameter(const char* ptr
return ptr; return ptr;
} }
const char* EDecoder::processSecurityDefinitionOptionalParameterEnd(const char* ptr, const char* endPtr) { const char* EDecoder::processSecurityDefinitionOptionalParameterEndMsg(const char* ptr, const char* endPtr) {
int reqId; int reqId;
DECODE_FIELD(reqId); DECODE_FIELD(reqId);
@ -1635,6 +1645,31 @@ const char* EDecoder::processSecurityDefinitionOptionalParameterEnd(const char*
return ptr; return ptr;
} }
const char* EDecoder::processSoftDollarTiersMsg(const char* ptr, const char* endPtr)
{
int reqId;
int nTiers;
DECODE_FIELD(reqId);
DECODE_FIELD(nTiers);
std::vector<SoftDollarTier> tiers(nTiers);
for (int i = 0; i < nTiers; i++) {
std::string name, value, dislplayName;
DECODE_FIELD(name);
DECODE_FIELD(value);
DECODE_FIELD(dislplayName);
tiers[i] = SoftDollarTier(name, value, value);
}
m_pEWrapper->softDollarTiers(reqId, tiers);
return ptr;
}
int EDecoder::processConnectAck(const char*& beginPtr, const char* endPtr) int EDecoder::processConnectAck(const char*& beginPtr, const char* endPtr)
{ {
@ -1910,11 +1945,15 @@ int EDecoder::parseAndProcessMsg(const char*& beginPtr, const char* endPtr) {
break; break;
case SECURITY_DEFINITION_OPTION_PARAMETER: case SECURITY_DEFINITION_OPTION_PARAMETER:
ptr = processSecurityDefinitionOptionalParameter(ptr, endPtr); ptr = processSecurityDefinitionOptionalParameterMsg(ptr, endPtr);
break; break;
case SECURITY_DEFINITION_OPTION_PARAMETER_END: case SECURITY_DEFINITION_OPTION_PARAMETER_END:
ptr = processSecurityDefinitionOptionalParameterEnd(ptr, endPtr); ptr = processSecurityDefinitionOptionalParameterEndMsg(ptr, endPtr);
break;
case SOFT_DOLLAR_TIERS:
ptr = processSoftDollarTiersMsg(ptr, endPtr);
break; break;
default: default:

View File

@ -55,12 +55,13 @@ const int MIN_SERVER_VER_PEGGED_TO_BENCHMARK = 102;
const int MIN_SERVER_VER_MODELS_SUPPORT = 103; const int MIN_SERVER_VER_MODELS_SUPPORT = 103;
const int MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ = 104; const int MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ = 104;
const int MIN_SERVER_VER_EXT_OPERATOR = 105; const int MIN_SERVER_VER_EXT_OPERATOR = 105;
const int MIN_SERVER_VER_SOFT_DOLLAR_TIER = 106;
/* 100+ messaging */ /* 100+ messaging */
// 100 = enhanced handshake, msg length prefixes // 100 = enhanced handshake, msg length prefixes
const int MIN_CLIENT_VER = 100; const int MIN_CLIENT_VER = 100;
const int MAX_CLIENT_VER = MIN_SERVER_VER_EXT_OPERATOR; const int MAX_CLIENT_VER = MIN_SERVER_VER_SOFT_DOLLAR_TIER;
// incoming msg id's // incoming msg id's
@ -115,6 +116,7 @@ const int ACCOUNT_UPDATE_MULTI = 73;
const int ACCOUNT_UPDATE_MULTI_END = 74; const int ACCOUNT_UPDATE_MULTI_END = 74;
const int SECURITY_DEFINITION_OPTION_PARAMETER = 75; const int SECURITY_DEFINITION_OPTION_PARAMETER = 75;
const int SECURITY_DEFINITION_OPTION_PARAMETER_END = 76; const int SECURITY_DEFINITION_OPTION_PARAMETER_END = 76;
const int SOFT_DOLLAR_TIERS = 77;
const int HEADER_LEN = 4; // 4 bytes for msg length const int HEADER_LEN = 4; // 4 bytes for msg length
const int MAX_MSG_LEN = 0xFFFFFF; // 16Mb - 1byte const int MAX_MSG_LEN = 0xFFFFFF; // 16Mb - 1byte
@ -213,8 +215,9 @@ class TWSAPIDLLEXP EDecoder
const char* processPositionMultiEndMsg(const char* ptr, const char* endPtr); const char* processPositionMultiEndMsg(const char* ptr, const char* endPtr);
const char* processAccountUpdateMultiMsg(const char* ptr, const char* endPtr); const char* processAccountUpdateMultiMsg(const char* ptr, const char* endPtr);
const char* processAccountUpdateMultiEndMsg(const char* ptr, const char* endPtr); const char* processAccountUpdateMultiEndMsg(const char* ptr, const char* endPtr);
const char* processSecurityDefinitionOptionalParameter(const char* ptr, const char* endPtr); const char* processSecurityDefinitionOptionalParameterMsg(const char* ptr, const char* endPtr);
const char* processSecurityDefinitionOptionalParameterEnd(const char* ptr, const char* endPtr); const char* processSecurityDefinitionOptionalParameterEndMsg(const char* ptr, const char* endPtr);
const char* processSoftDollarTiersMsg(const char* ptr, const char* endPtr);
int processConnectAck(const char*& beginPtr, const char* endPtr); int processConnectAck(const char*& beginPtr, const char* endPtr);

View File

@ -178,13 +178,20 @@ void EReader::onReceive() {
} }
bool EReader::bufferedRead(char *buf, int size) { bool EReader::bufferedRead(char *buf, int size) {
while (m_buf.size() < size) while (size > 0) {
if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK()) while (m_buf.size() < size && m_buf.size() < m_nMaxBufSize)
return false; if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
return false;
std::copy(m_buf.begin(), m_buf.begin() + size, buf); int nBytes = min(m_nMaxBufSize, size);
std::copy(m_buf.begin() + size, m_buf.end(), m_buf.begin());
m_buf.resize(m_buf.size() - size); std::copy(m_buf.begin(), m_buf.begin() + nBytes, buf);
std::copy(m_buf.begin() + nBytes, m_buf.end(), m_buf.begin());
m_buf.resize(m_buf.size() - nBytes);
size -= nBytes;
buf += nBytes;
}
return true; return true;
} }

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include "EReaderSignal.h" #include "EReaderSignal.h"
#include "StdAfx.h" #include "StdAfx.h"
#include <stdexcept>
#if !defined(INFINITE) #if !defined(INFINITE)
#define INFINITE ((unsigned long)-1) #define INFINITE ((unsigned long)-1)

View File

@ -6,6 +6,7 @@
#define ewrapper_def #define ewrapper_def
#include "CommonDefs.h" #include "CommonDefs.h"
#include "SoftDollarTier.h"
#include <string> #include <string>
#include <set> #include <set>
@ -78,6 +79,9 @@ enum TickType { BID_SIZE, BID, ASK, ASK_SIZE, LAST, LAST_SIZE,
DELAYED_VOLUME, DELAYED_VOLUME,
DELAYED_CLOSE, DELAYED_CLOSE,
DELAYED_OPEN, DELAYED_OPEN,
RT_TRD_VOLUME,
CREDITMAN_MARK_PRICE,
CREDITMAN_SLOW_MARK_PRICE,
NOT_SET }; NOT_SET };
inline bool isPrice( TickType tickType) { inline bool isPrice( TickType tickType) {
@ -165,6 +169,7 @@ public:
virtual void accountUpdateMultiEnd( int reqId) = 0; virtual void accountUpdateMultiEnd( int reqId) = 0;
virtual void securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes) = 0; virtual void securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes) = 0;
virtual void securityDefinitionOptionalParameterEnd(int reqId) = 0; virtual void securityDefinitionOptionalParameterEnd(int reqId) = 0;
virtual void softDollarTiers(int reqId, const std::vector<SoftDollarTier> &tiers) = 0;
}; };

View File

@ -7,6 +7,7 @@
#include "TagValue.h" #include "TagValue.h"
#include "OrderCondition.h" #include "OrderCondition.h"
#include "SoftDollarTier.h"
#include <float.h> #include <float.h>
#include <limits.h> #include <limits.h>
@ -42,7 +43,8 @@ typedef ibapi::shared_ptr<OrderComboLeg> OrderComboLegSPtr;
struct Order struct Order
{ {
Order() Order() :
softDollarTier("", "", "")
{ {
// order identifier // order identifier
orderId = 0; orderId = 0;
@ -307,6 +309,8 @@ struct Order
// ext operator // ext operator
std::string extOperator; std::string extOperator;
SoftDollarTier softDollarTier;
public: public:
// Helpers // Helpers

View File

@ -0,0 +1,22 @@
#include "StdAfx.h"
#include "SoftDollarTier.h"
SoftDollarTier::SoftDollarTier(const std::string& name, const std::string& val, const std::string& displayName) :
m_name(name), m_val(val), m_displayName(displayName)
{
}
std::string SoftDollarTier::name() const
{
return m_name;
}
std::string SoftDollarTier::val() const
{
return m_val;
}
std::string SoftDollarTier::displayName() const
{
return m_displayName;
}

View File

@ -0,0 +1,14 @@
#pragma once
class TWSAPIDLLEXP SoftDollarTier
{
std::string m_name, m_val, m_displayName;
public:
SoftDollarTier(const std::string& name = "", const std::string& val = "", const std::string& displayName = "");
std::string name() const;
std::string val() const;
std::string displayName() const;
};

View File

@ -0,0 +1,106 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef shared_ptr_h_INCLUDED
#define shared_ptr_h_INCLUDED
//
// Implements a subset of shared_prt found at www.boost.org.
// Uses a singly linked circular list instead of a reference counter.
// Avoids extra heap allocation needed to get a shared reference counter,
// but sizeof(shared_ptr) == sizeof(void*) * 3 compared to sizeof(void*) * 2
//
// See "Handles and Exception Safety, Part 4: Tracking References without Counters"
// by Andrew Koenig and Barbara E. Moo, Feb. 2003 C++ Users Journal
//
namespace ibapi {
namespace shared_ptr_defs {
class Use {
public:
Use() { forward_ = this; back_ = this; }
~Use() { remove(); }
Use(const Use& u) { insert(u); }
Use& operator=(const Use& u)
{
if (this != &u) {
remove();
insert(u);
}
return *this;
}
bool only() const { return this == this->forward_; }
private:
mutable const Use *forward_;
mutable const Use *back_;
void insert(const Use& u) const {
this->back_ = &u;
this->forward_ = u.forward_;
u.forward_->back_ = this;
u.forward_ = this;
}
void remove() const {
this->forward_->back_ = this->back_;
this->back_->forward_ = this->forward_;
}
};
} // end of namespace shared_ptr_defs
template<typename X> class shared_ptr {
public:
typedef shared_ptr_defs::Use Use;
template<typename Y> friend class shared_ptr;
explicit shared_ptr(X* ptr = 0) : ptr_(ptr) {}
~shared_ptr() { if (use_.only()) delete ptr_; }
template<typename Y>
shared_ptr(const shared_ptr<Y>& other)
: ptr_(other.ptr_),
use_(other.use_)
{}
shared_ptr& operator=(const shared_ptr& other) {
if ( &use_ == &other.use_ ) { return *this; }
if ( use_.only() ) { delete ptr_; }
use_ = other.use_;
ptr_ = other.ptr_;
return *this;
}
X& operator*() const { return *ptr_; }
X* operator->() const { return ptr_; }
X* get() const { return ptr_; }
bool only() const { return use_.only(); }
void reset(X* ptr = 0) {
if ( use_.only() ) { delete ptr_; }
ptr_ = ptr;
use_ = Use();
}
private:
X *ptr_;
Use use_;
};
} //end of namespace ibapi
#else
//#include <memory>
//using std::shared_ptr;
#endif /* shared_ptr_h_INCLUDED */

View File

@ -0,0 +1,27 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef commissionreport_def
#define commissionreport_def
struct CommissionReport
{
CommissionReport()
{
commission = 0;
realizedPNL = 0;
yield = 0;
yieldRedemptionDate = 0;
}
// commission report fields
std::string execId;
double commission;
std::string currency;
double realizedPNL;
double yield;
int yieldRedemptionDate; // YYYYMMDD format
};
#endif // commissionreport_def

View File

@ -0,0 +1,33 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef common_defs_h_INCLUDED
#define common_defs_h_INCLUDED
typedef long TickerId;
typedef long OrderId;
enum faDataType { GROUPS=1, PROFILES, ALIASES } ;
inline const char* faDataTypeStr ( faDataType pFaDataType )
{
switch (pFaDataType) {
case GROUPS:
return "GROUPS";
case PROFILES:
return "PROFILES";
case ALIASES:
return "ALIASES";
}
return 0 ;
}
enum MarketDataType {
REALTIME = 1,
FROZEN = 2,
DELAYED = 3,
DELAYED_FROZEN = 4
};
#endif /* common_defs_h_INCLUDED */

View File

@ -0,0 +1,187 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef contract_def
#define contract_def
#include "TagValue.h"
/*
SAME_POS = open/close leg value is same as combo
OPEN_POS = open
CLOSE_POS = close
UNKNOWN_POS = unknown
*/
enum LegOpenClose { SAME_POS, OPEN_POS, CLOSE_POS, UNKNOWN_POS };
struct ComboLeg
{
ComboLeg()
: conId(0)
, ratio(0)
, openClose(0)
, shortSaleSlot(0)
, exemptCode(-1)
{
}
long conId;
long ratio;
std::string action; //BUY/SELL/SSHORT
std::string exchange;
long openClose; // LegOpenClose enum values
// for stock legs when doing short sale
long shortSaleSlot; // 1 = clearing broker, 2 = third party
std::string designatedLocation;
int exemptCode;
bool operator==( const ComboLeg& other) const
{
return (conId == other.conId &&
ratio == other.ratio &&
openClose == other.openClose &&
shortSaleSlot == other.shortSaleSlot &&
exemptCode == other.exemptCode &&
action == other.action &&
exchange == other.exchange &&
designatedLocation == other.designatedLocation);
}
};
struct UnderComp
{
UnderComp()
: conId(0)
, delta(0)
, price(0)
{}
long conId;
double delta;
double price;
};
typedef ibapi::shared_ptr<ComboLeg> ComboLegSPtr;
struct Contract
{
Contract()
: conId(0)
, strike(0)
, includeExpired(false)
, comboLegs(NULL)
, underComp(NULL)
{
}
long conId;
std::string symbol;
std::string secType;
std::string lastTradeDateOrContractMonth;
double strike;
std::string right;
std::string multiplier;
std::string exchange;
std::string primaryExchange; // pick an actual (ie non-aggregate) exchange that the contract trades on. DO NOT SET TO SMART.
std::string currency;
std::string localSymbol;
std::string tradingClass;
bool includeExpired;
std::string secIdType; // CUSIP;SEDOL;ISIN;RIC
std::string secId;
// COMBOS
std::string comboLegsDescrip; // received in open order 14 and up for all combos
// combo legs
typedef std::vector<ComboLegSPtr> ComboLegList;
typedef ibapi::shared_ptr<ComboLegList> ComboLegListSPtr;
ComboLegListSPtr comboLegs;
// delta neutral
UnderComp* underComp;
public:
// Helpers
static void CloneComboLegs(ComboLegListSPtr& dst, const ComboLegListSPtr& src);
};
struct ContractDetails
{
ContractDetails()
: minTick(0)
, priceMagnifier(0)
, underConId(0)
, evMultiplier(0)
, callable(false)
, putable(false)
, coupon(0)
, convertible(false)
, nextOptionPartial(false)
{
}
Contract summary;
std::string marketName;
double minTick;
std::string orderTypes;
std::string validExchanges;
long priceMagnifier;
int underConId;
std::string longName;
std::string contractMonth;
std::string industry;
std::string category;
std::string subcategory;
std::string timeZoneId;
std::string tradingHours;
std::string liquidHours;
std::string evRule;
double evMultiplier;
TagValueListSPtr secIdList;
// BOND values
std::string cusip;
std::string ratings;
std::string descAppend;
std::string bondType;
std::string couponType;
bool callable;
bool putable;
double coupon;
bool convertible;
std::string maturity;
std::string issueDate;
std::string nextOptionDate;
std::string nextOptionType;
bool nextOptionPartial;
std::string notes;
};
inline void
Contract::CloneComboLegs(ComboLegListSPtr& dst, const ComboLegListSPtr& src)
{
if (!src.get())
return;
dst->reserve(src->size());
ComboLegList::const_iterator iter = src->begin();
const ComboLegList::const_iterator iterEnd = src->end();
for (; iter != iterEnd; ++iter) {
const ComboLeg* leg = iter->get();
if (!leg)
continue;
dst->push_back(ComboLegSPtr(new ComboLeg(*leg)));
}
}
#endif

View File

@ -0,0 +1,43 @@
#include "StdAfx.h"
#include "ContractCondition.h"
#include "EDecoder.h"
#include "EClient.h"
std::string ContractCondition::toString() {
std::string strContract = conId() + "";
return type() + " of " + strContract + OperatorCondition::toString();
}
const char* ContractCondition::readExternal(const char* ptr, const char* endPtr) {
if (!(ptr = OperatorCondition::readExternal(ptr, endPtr)))
return 0;
DECODE_FIELD(m_conId);
DECODE_FIELD(m_exchange);
return ptr;
}
void ContractCondition::writeExternal(std::ostream & msg) const {
OperatorCondition::writeExternal(msg);
ENCODE_FIELD(m_conId);
ENCODE_FIELD(m_exchange);
}
int ContractCondition::conId() {
return m_conId;
}
void ContractCondition::conId(int conId) {
m_conId = conId;
}
std::string ContractCondition::exchange() {
return m_exchange;
}
void ContractCondition::exchange(const std::string & exchange) {
m_exchange = exchange;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "OperatorCondition.h"
class TWSAPIDLLEXP ContractCondition : public OperatorCondition {
int m_conId;
std::string m_exchange;
public:
virtual std::string toString();
virtual const char* readExternal(const char* ptr, const char* endPtr);
virtual void writeExternal(std::ostream &out) const;
int conId();
void conId(int conId);
std::string exchange();
void exchange(const std::string &exchange);
};

View File

@ -0,0 +1,77 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#include "StdAfx.h"
#include "DefaultEWrapper.h"
void DefaultEWrapper::tickPrice( TickerId tickerId, TickType field, double price, int canAutoExecute) { }
void DefaultEWrapper::tickSize( TickerId tickerId, TickType field, int size) { }
void DefaultEWrapper::tickOptionComputation( TickerId tickerId, TickType tickType, double impliedVol, double delta,
double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) { }
void DefaultEWrapper::tickGeneric(TickerId tickerId, TickType tickType, double value) { }
void DefaultEWrapper::tickString(TickerId tickerId, TickType tickType, const std::string& value) { }
void DefaultEWrapper::tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const std::string& formattedBasisPoints,
double totalDividends, int holdDays, const std::string& futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate) { }
void DefaultEWrapper::orderStatus( OrderId orderId, const std::string& status, double filled,
double remaining, double avgFillPrice, int permId, int parentId,
double lastFillPrice, int clientId, const std::string& whyHeld) { }
void DefaultEWrapper::openOrder( OrderId orderId, const Contract&, const Order&, const OrderState&) { }
void DefaultEWrapper::openOrderEnd() { }
void DefaultEWrapper::winError( const std::string& str, int lastError) { }
void DefaultEWrapper::connectionClosed() { }
void DefaultEWrapper::updateAccountValue(const std::string& key, const std::string& val,
const std::string& currency, const std::string& accountName) { }
void DefaultEWrapper::updatePortfolio( const Contract& contract, double position,
double marketPrice, double marketValue, double averageCost,
double unrealizedPNL, double realizedPNL, const std::string& accountName) { }
void DefaultEWrapper::updateAccountTime(const std::string& timeStamp) { }
void DefaultEWrapper::accountDownloadEnd(const std::string& accountName) { }
void DefaultEWrapper::nextValidId( OrderId orderId) { }
void DefaultEWrapper::contractDetails( int reqId, const ContractDetails& contractDetails) { }
void DefaultEWrapper::bondContractDetails( int reqId, const ContractDetails& contractDetails) { }
void DefaultEWrapper::contractDetailsEnd( int reqId) { }
void DefaultEWrapper::execDetails( int reqId, const Contract& contract, const Execution& execution) { }
void DefaultEWrapper::execDetailsEnd( int reqId) { }
void DefaultEWrapper::error(const int id, const int errorCode, const std::string errorString) { }
void DefaultEWrapper::updateMktDepth(TickerId id, int position, int operation, int side,
double price, int size) { }
void DefaultEWrapper::updateMktDepthL2(TickerId id, int position, std::string marketMaker, int operation,
int side, double price, int size) { }
void DefaultEWrapper::updateNewsBulletin(int msgId, int msgType, const std::string& newsMessage, const std::string& originExch) { }
void DefaultEWrapper::managedAccounts( const std::string& accountsList) { }
void DefaultEWrapper::receiveFA(faDataType pFaDataType, const std::string& cxml) { }
void DefaultEWrapper::historicalData(TickerId reqId, const std::string& date, double open, double high,
double low, double close, int volume, int barCount, double WAP, int hasGaps) { }
void DefaultEWrapper::scannerParameters(const std::string& xml) { }
void DefaultEWrapper::scannerData(int reqId, int rank, const ContractDetails& contractDetails,
const std::string& distance, const std::string& benchmark, const std::string& projection,
const std::string& legsStr) { }
void DefaultEWrapper::scannerDataEnd(int reqId) { }
void DefaultEWrapper::realtimeBar(TickerId reqId, long time, double open, double high, double low, double close,
long volume, double wap, int count) { }
void DefaultEWrapper::currentTime(long time) { }
void DefaultEWrapper::fundamentalData(TickerId reqId, const std::string& data) { }
void DefaultEWrapper::deltaNeutralValidation(int reqId, const UnderComp& underComp) { }
void DefaultEWrapper::tickSnapshotEnd( int reqId) { }
void DefaultEWrapper::marketDataType( TickerId reqId, int marketDataType) { }
void DefaultEWrapper::commissionReport( const CommissionReport& commissionReport) { }
void DefaultEWrapper::position( const std::string& account, const Contract& contract, double position, double avgCost) { }
void DefaultEWrapper::positionEnd() { }
void DefaultEWrapper::accountSummary( int reqId, const std::string& account, const std::string& tag, const std::string& value, const std::string& curency) { }
void DefaultEWrapper::accountSummaryEnd( int reqId) { }
void DefaultEWrapper::verifyMessageAPI( const std::string& apiData) { }
void DefaultEWrapper::verifyCompleted( bool isSuccessful, const std::string& errorText) { }
void DefaultEWrapper::displayGroupList( int reqId, const std::string& groups) { }
void DefaultEWrapper::displayGroupUpdated( int reqId, const std::string& contractInfo) { }
void DefaultEWrapper::verifyAndAuthMessageAPI( const std::string& apiData, const std::string& xyzChallange) { }
void DefaultEWrapper::verifyAndAuthCompleted( bool isSuccessful, const std::string& errorText) { }
void DefaultEWrapper::connectAck() { }
void DefaultEWrapper::positionMulti( int reqId, const std::string& account,const std::string& modelCode, const Contract& contract, double pos, double avgCost) { }
void DefaultEWrapper::positionMultiEnd( int reqId) { }
void DefaultEWrapper::accountUpdateMulti( int reqId, const std::string& account, const std::string& modelCode, const std::string& key, const std::string& value, const std::string& currency) { }
void DefaultEWrapper::accountUpdateMultiEnd( int reqId) { }
void DefaultEWrapper::securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes) { }
void DefaultEWrapper::securityDefinitionOptionalParameterEnd(int reqId) { }
void DefaultEWrapper::softDollarTiers(int reqId, const std::vector<SoftDollarTier> &tiers) { }

View File

@ -0,0 +1,81 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#include "EWrapper.h"
class TWSAPIDLLEXP DefaultEWrapper :
public EWrapper
{
public:
virtual void tickPrice( TickerId tickerId, TickType field, double price, int canAutoExecute);
virtual void tickSize( TickerId tickerId, TickType field, int size);
virtual void tickOptionComputation( TickerId tickerId, TickType tickType, double impliedVol, double delta,
double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice);
virtual void tickGeneric(TickerId tickerId, TickType tickType, double value);
virtual void tickString(TickerId tickerId, TickType tickType, const std::string& value);
virtual void tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const std::string& formattedBasisPoints,
double totalDividends, int holdDays, const std::string& futureLastTradeDate, double dividendImpact, double dividendsToLastTradeDate);
virtual void orderStatus( OrderId orderId, const std::string& status, double filled,
double remaining, double avgFillPrice, int permId, int parentId,
double lastFillPrice, int clientId, const std::string& whyHeld);
virtual void openOrder( OrderId orderId, const Contract&, const Order&, const OrderState&);
virtual void openOrderEnd();
virtual void winError( const std::string& str, int lastError);
virtual void connectionClosed();
virtual void updateAccountValue(const std::string& key, const std::string& val,
const std::string& currency, const std::string& accountName);
virtual void updatePortfolio( const Contract& contract, double position,
double marketPrice, double marketValue, double averageCost,
double unrealizedPNL, double realizedPNL, const std::string& accountName);
virtual void updateAccountTime(const std::string& timeStamp);
virtual void accountDownloadEnd(const std::string& accountName);
virtual void nextValidId( OrderId orderId);
virtual void contractDetails( int reqId, const ContractDetails& contractDetails);
virtual void bondContractDetails( int reqId, const ContractDetails& contractDetails);
virtual void contractDetailsEnd( int reqId);
virtual void execDetails( int reqId, const Contract& contract, const Execution& execution);
virtual void execDetailsEnd( int reqId);
virtual void error(const int id, const int errorCode, const std::string errorString);
virtual void updateMktDepth(TickerId id, int position, int operation, int side,
double price, int size);
virtual void updateMktDepthL2(TickerId id, int position, std::string marketMaker, int operation,
int side, double price, int size);
virtual void updateNewsBulletin(int msgId, int msgType, const std::string& newsMessage, const std::string& originExch);
virtual void managedAccounts( const std::string& accountsList);
virtual void receiveFA(faDataType pFaDataType, const std::string& cxml);
virtual void historicalData(TickerId reqId, const std::string& date, double open, double high,
double low, double close, int volume, int barCount, double WAP, int hasGaps);
virtual void scannerParameters(const std::string& xml);
virtual void scannerData(int reqId, int rank, const ContractDetails& contractDetails,
const std::string& distance, const std::string& benchmark, const std::string& projection,
const std::string& legsStr);
virtual void scannerDataEnd(int reqId);
virtual void realtimeBar(TickerId reqId, long time, double open, double high, double low, double close,
long volume, double wap, int count);
virtual void currentTime(long time);
virtual void fundamentalData(TickerId reqId, const std::string& data);
virtual void deltaNeutralValidation(int reqId, const UnderComp& underComp);
virtual void tickSnapshotEnd( int reqId);
virtual void marketDataType( TickerId reqId, int marketDataType);
virtual void commissionReport( const CommissionReport& commissionReport);
virtual void position( const std::string& account, const Contract& contract, double position, double avgCost);
virtual void positionEnd();
virtual void accountSummary( int reqId, const std::string& account, const std::string& tag, const std::string& value, const std::string& curency);
virtual void accountSummaryEnd( int reqId);
virtual void verifyMessageAPI( const std::string& apiData);
virtual void verifyCompleted( bool isSuccessful, const std::string& errorText);
virtual void displayGroupList( int reqId, const std::string& groups);
virtual void displayGroupUpdated( int reqId, const std::string& contractInfo);
virtual void verifyAndAuthMessageAPI( const std::string& apiData, const std::string& xyzChallange);
virtual void verifyAndAuthCompleted( bool isSuccessful, const std::string& errorText);
virtual void connectAck();
virtual void positionMulti( int reqId, const std::string& account,const std::string& modelCode, const Contract& contract, double pos, double avgCost);
virtual void positionMultiEnd( int reqId);
virtual void accountUpdateMulti( int reqId, const std::string& account, const std::string& modelCode, const std::string& key, const std::string& value, const std::string& currency);
virtual void accountUpdateMultiEnd( int reqId);
virtual void securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass, const std::string& multiplier, std::set<std::string> expirations, std::set<double> strikes);
virtual void securityDefinitionOptionalParameterEnd(int reqId);
virtual void softDollarTiers(int reqId, const std::vector<SoftDollarTier> &tiers);
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,384 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef eclient_h__INCLUDED
#define eclient_h__INCLUDED
#include <memory>
#include <string>
#include <vector>
#include <iosfwd>
#include "CommonDefs.h"
#include "TagValue.h"
namespace ibapi {
namespace client_constants {
/////////////////////////////////////////////////////////////////////////////////
// SOCKET CLIENT VERSION CHANGE LOG : Incremented when the format of incomming
// server responses change
/////////////////////////////////////////////////////////////////////////////////
// constants
// 6 = Added parentId to orderStatus
// 7 = The new execDetails event returned for an order filled status and reqExecDetails
// Also added market depth support.
// 8 = Added 'lastFillPrice' to orderStatus and 'permId' to execDetails
// 9 = Added 'avgCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event
// 10 = Added 'serverId' to the 'open order' & 'order status' events.
// We send back all the API open orders upon connection.
// Added new methods reqAllOpenOrders, reqAutoOpenOrders()
// Added FA support - reqExecution has filter.
// - reqAccountUpdates takes acct code.
// 11 = Added permId to openOrder event.
// 12 = Added IgnoreRth, hidden, and discretionaryAmt
// 13 = Added GoodAfterTime
// 14 = always send size on bid/ask/last tick
// 15 = send allocation string with open order
// 16 = can receive account name in account and portfolio updates, and fa params in openOrder
// 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data
// 18 = can receive good till date field in open order messages, and send backfill requests
// 19 = can receive new extended order attributes in OPEN_ORDER
// 20 = expects TWS time string on connection after server version >= 20, and parentId in open order
// 21 = can receive bond contract details.
// 22 = can receive price magnifier in contract details
// 23 = support for scanner
// 24 = can receive volatility order parameters in open order messages
// 25 = can receive HMDS query start and end times
// 26 = can receive option vols in option market data messages
// 27 = can receive delta neutral order type and delta neutral aux price
// 28 = can receive option model computation ticks
// 29 = can receive trail stop limit price in open order and can place them: API 8.91
// 30 = can receive extended bond contract def, new ticks, and trade count in bars
// 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders
// ; can receive RT bars
// 32 = can receive TickType.LAST_TIMESTAMP
// 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages
// 34 = can receive whatIf orders / order state
// 35 = can receive contId field for Contract objects
// 36 = can receive outsideRth field for Order objects
// 37 = can receive clearingAccount and clearingIntent for Order objects
// 38 = can receive multipier and primaryExchange in portfolio updates
// ; can receive cumQty and avgPrice in execution
// ; can receive fundamental data
// ; can receive underComp for Contract objects
// ; can receive reqId and end marker in contractDetails/bondContractDetails
// ; can receive ScaleInitComponentSize and ScaleSubsComponentSize for Order objects
// 39 = can receive underConId in contractDetails
// 40 = can receive algoStrategy/algoParams in openOrder
// 41 = can receive end marker for openOrder
// ; can receive end marker for account download
// ; can receive end marker for executions download
// 42 = can receive deltaNeutralValidation
// 43 = can receive longName(companyName)
// ; can receive listingExchange
// ; can receive RTVolume tick
// 44 = can receive end market for ticker snapshot
// 45 = can receive notHeld field in openOrder
// 46 = can receive contractMonth, industry, category, subcategory fields in contractDetails
// ; can receive timeZoneId, tradingHours, liquidHours fields in contractDetails
// 47 = can receive gamma, vega, theta, undPrice fields in TICK_OPTION_COMPUTATION
// 48 = can receive exemptCode in openOrder
// 49 = can receive hedgeType and hedgeParam in openOrder
// 50 = can receive optOutSmartRouting field in openOrder
// 51 = can receive smartComboRoutingParams in openOrder
// 52 = can receive deltaNeutralConId, deltaNeutralSettlingFirm, deltaNeutralClearingAccount and deltaNeutralClearingIntent in openOrder
// 53 = can receive orderRef in execution
// 54 = can receive scale order fields (PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset,
// InitPosition, InitFillQty and RandomPercent) in openOrder
// 55 = can receive orderComboLegs (price) in openOrder
// 56 = can receive trailingPercent in openOrder
// 57 = can receive commissionReport message
// 58 = can receive CUSIP/ISIN/etc. in contractDescription/bondContractDescription
// 59 = can receive evRule, evMultiplier in contractDescription/bondContractDescription/executionDetails
// can receive multiplier in executionDetails
// 60 = can receive deltaNeutralOpenClose, deltaNeutralShortSale, deltaNeutralShortSaleSlot
// and deltaNeutralDesignatedLocation in openOrder
// can receive position, positionEnd, accountSummary and accountSummaryEnd
// 61 = can receive multiplier in openOrder
// can receive tradingClass in openOrder, updatePortfolio, execDetails and position
// 62 = can receive avgCost in position message
// 63 = can receive verifyMessageAPI, verifyCompleted, displayGroupList and displayGroupUpdated messages
// 64 = can receive solicited attrib in openOrder message
// 65 = can receive verifyAndAuthMessageAPI and verifyAndAuthCompleted messages
// 66 = can receive randomize size and randomize price order fields
const int CLIENT_VERSION = 66;
// outgoing msg id's
const int REQ_MKT_DATA = 1;
const int CANCEL_MKT_DATA = 2;
const int PLACE_ORDER = 3;
const int CANCEL_ORDER = 4;
const int REQ_OPEN_ORDERS = 5;
const int REQ_ACCT_DATA = 6;
const int REQ_EXECUTIONS = 7;
const int REQ_IDS = 8;
const int REQ_CONTRACT_DATA = 9;
const int REQ_MKT_DEPTH = 10;
const int CANCEL_MKT_DEPTH = 11;
const int REQ_NEWS_BULLETINS = 12;
const int CANCEL_NEWS_BULLETINS = 13;
const int SET_SERVER_LOGLEVEL = 14;
const int REQ_AUTO_OPEN_ORDERS = 15;
const int REQ_ALL_OPEN_ORDERS = 16;
const int REQ_MANAGED_ACCTS = 17;
const int REQ_FA = 18;
const int REPLACE_FA = 19;
const int REQ_HISTORICAL_DATA = 20;
const int EXERCISE_OPTIONS = 21;
const int REQ_SCANNER_SUBSCRIPTION = 22;
const int CANCEL_SCANNER_SUBSCRIPTION = 23;
const int REQ_SCANNER_PARAMETERS = 24;
const int CANCEL_HISTORICAL_DATA = 25;
const int REQ_CURRENT_TIME = 49;
const int REQ_REAL_TIME_BARS = 50;
const int CANCEL_REAL_TIME_BARS = 51;
const int REQ_FUNDAMENTAL_DATA = 52;
const int CANCEL_FUNDAMENTAL_DATA = 53;
const int REQ_CALC_IMPLIED_VOLAT = 54;
const int REQ_CALC_OPTION_PRICE = 55;
const int CANCEL_CALC_IMPLIED_VOLAT = 56;
const int CANCEL_CALC_OPTION_PRICE = 57;
const int REQ_GLOBAL_CANCEL = 58;
const int REQ_MARKET_DATA_TYPE = 59;
const int REQ_POSITIONS = 61;
const int REQ_ACCOUNT_SUMMARY = 62;
const int CANCEL_ACCOUNT_SUMMARY = 63;
const int CANCEL_POSITIONS = 64;
const int VERIFY_REQUEST = 65;
const int VERIFY_MESSAGE = 66;
const int QUERY_DISPLAY_GROUPS = 67;
const int SUBSCRIBE_TO_GROUP_EVENTS = 68;
const int UPDATE_DISPLAY_GROUP = 69;
const int UNSUBSCRIBE_FROM_GROUP_EVENTS = 70;
const int START_API = 71;
const int VERIFY_AND_AUTH_REQUEST = 72;
const int VERIFY_AND_AUTH_MESSAGE = 73;
const int REQ_POSITIONS_MULTI = 74;
const int CANCEL_POSITIONS_MULTI = 75;
const int REQ_ACCOUNT_UPDATES_MULTI = 76;
const int CANCEL_ACCOUNT_UPDATES_MULTI = 77;
const int REQ_SEC_DEF_OPT_PARAMS = 78;
const int REQ_SOFT_DOLLAR_TIERS = 79;
// TWS New Bulletins constants
const int NEWS_MSG = 1; // standard IB news bulleting message
const int EXCHANGE_AVAIL_MSG = 2; // control message specifing that an exchange is available for trading
const int EXCHANGE_UNAVAIL_MSG = 3; // control message specifing that an exchange is unavailable for trading
} // namespace client_constants
} // namespace ibapi
struct Contract;
struct Order;
struct ExecutionFilter;
struct ScannerSubscription;
struct ETransport;
class EWrapper;
typedef std::vector<char> BytesVec;
class TWSAPIDLLEXP EClient
{
public:
explicit EClient(EWrapper *ptr, ETransport *pTransport);
~EClient();
virtual void eDisconnect() = 0;
int clientId() const { return m_clientId; }
const std::string& optionalCapabilities() const;
void setOptionalCapabilities(const std::string& optCapts);
void setConnectOptions(const std::string& connectOptions);
void disableUseV100Plus();
bool usingV100Plus();
protected:
void eConnectBase();
void eDisconnectBase();
public:
enum ConnState {
CS_DISCONNECTED,
CS_CONNECTING,
CS_CONNECTED,
CS_REDIRECT
};
// connection state
ConnState connState() const;
bool isConnected() const;
const std::string& host() const { return m_host; }
unsigned port() const { return m_port; }
public:
// access to protected variables
EWrapper * getWrapper() const;
protected:
void setClientId( int clientId);
void setExtraAuth( bool extraAuth);
void setHost( const std::string& host);
void setPort( unsigned port);
public:
bool isInBufferEmpty() const;
// override virtual funcs from EClient
int serverVersion();
std::string TwsConnectionTime();
void reqMktData(TickerId id, const Contract& contract,
const std::string& genericTicks, bool snapshot, const TagValueListSPtr& mktDataOptions);
void cancelMktData(TickerId id);
void placeOrder(OrderId id, const Contract& contract, const Order& order);
void cancelOrder(OrderId id) ;
void reqOpenOrders();
void reqAccountUpdates(bool subscribe, const std::string& acctCode);
void reqExecutions(int reqId, const ExecutionFilter& filter);
void reqIds(int numIds);
void reqContractDetails(int reqId, const Contract& contract);
void reqMktDepth(TickerId tickerId, const Contract& contract, int numRows, const TagValueListSPtr& mktDepthOptions);
void cancelMktDepth(TickerId tickerId);
void reqNewsBulletins(bool allMsgs);
void cancelNewsBulletins();
void setServerLogLevel(int level);
void reqAutoOpenOrders(bool bAutoBind);
void reqAllOpenOrders();
void reqManagedAccts();
void requestFA(faDataType pFaDataType);
void replaceFA(faDataType pFaDataType, const std::string& cxml);
void reqHistoricalData( TickerId id, const Contract& contract,
const std::string& endDateTime, const std::string& durationStr,
const std::string& barSizeSetting, const std::string& whatToShow,
int useRTH, int formatDate, const TagValueListSPtr& chartOptions);
void exerciseOptions(TickerId tickerId, const Contract& contract,
int exerciseAction, int exerciseQuantity,
const std::string& account, int override);
void cancelHistoricalData(TickerId tickerId );
void reqRealTimeBars(TickerId id, const Contract& contract, int barSize,
const std::string& whatToShow, bool useRTH, const TagValueListSPtr& realTimeBarsOptions);
void cancelRealTimeBars(TickerId tickerId );
void cancelScannerSubscription(int tickerId);
void reqScannerParameters();
void reqScannerSubscription(int tickerId, const ScannerSubscription& subscription, const TagValueListSPtr& scannerSubscriptionOptions);
void reqCurrentTime();
void reqFundamentalData(TickerId reqId, const Contract&, const std::string& reportType);
void cancelFundamentalData(TickerId reqId);
void calculateImpliedVolatility(TickerId reqId, const Contract& contract, double optionPrice, double underPrice);
void calculateOptionPrice(TickerId reqId, const Contract& contract, double volatility, double underPrice);
void cancelCalculateImpliedVolatility(TickerId reqId);
void cancelCalculateOptionPrice(TickerId reqId);
void reqGlobalCancel();
void reqMarketDataType(int marketDataType);
void reqPositions();
void cancelPositions();
void reqAccountSummary( int reqId, const std::string& groupName, const std::string& tags);
void cancelAccountSummary( int reqId);
void verifyRequest( const std::string& apiName, const std::string& apiVersion);
void verifyMessage( const std::string& apiData);
void verifyAndAuthRequest( const std::string& apiName, const std::string& apiVersion, const std::string& opaqueIsvKey);
void verifyAndAuthMessage( const std::string& apiData, const std::string& xyzResponse);
void queryDisplayGroups( int reqId);
void subscribeToGroupEvents( int reqId, int groupId);
void updateDisplayGroup( int reqId, const std::string& contractInfo);
void unsubscribeFromGroupEvents( int reqId);
void reqPositionsMulti( int reqId, const std::string& account, const std::string& modelCode);
void cancelPositionsMulti( int reqId);
void reqAccountUpdatessMulti( int reqId, const std::string& account, const std::string& modelCode, bool ledgerAndNLV);
void cancelAccountUpdatesMulti( int reqId);
void reqSecDefOptParams(int reqId, const std::string& underlyingSymbol, const std::string& futFopExchange, const std::string& underlyingSecType, int underlyingConId);
void reqSoftDollarTiers(int reqId);
private:
virtual int receive(char* buf, size_t sz) = 0;
protected:
virtual void prepareBufferImpl(std::ostream&) const = 0;
virtual void prepareBuffer(std::ostream&) const = 0;
virtual bool closeAndSend(std::string msg, unsigned offset = 0) = 0;
virtual int bufferedSend(const std::string& msg);
protected:
int bufferedRead();
// try to process connection request ack
private:
// try to process single msg
int processMsgImpl(const char*& ptr, const char* endPtr);
int processMsg(const char*& ptr, const char* endPtr);
typedef int (EClient::*messageHandler)(const char*& ptr, const char* endPtr);
int processOnePrefixedMsg(const char*& ptr, const char* endPtr, messageHandler);
public:
void startApi();
// encoders
template<class T> static void EncodeField(std::ostream&, T);
// "max" encoders
static void EncodeFieldMax(std::ostream& os, int);
static void EncodeFieldMax(std::ostream& os, double);
// socket state
private:
virtual bool isSocketOK() const = 0;
protected:
bool isConnecting() const;
int sendConnectRequest();
bool extraAuth();
protected:
EWrapper *m_pEWrapper;
std::auto_ptr<ETransport> m_transport;
private:
BytesVec m_inBuffer;
std::string m_host;
int m_port;
int m_clientId;
ConnState m_connState;
bool m_extraAuth;
protected:
int m_serverVersion;
std::string m_TwsTime;
private:
std::string m_optionalCapabilities;
std::string m_connectOptions;
protected:
bool m_useV100Plus;
};
template<> void EClient::EncodeField<bool>(std::ostream& os, bool);
template<> void EClient::EncodeField<double>(std::ostream& os, double);
#define ENCODE_FIELD(x) EClient::EncodeField(msg, x);
#define ENCODE_FIELD_MAX(x) EClient::EncodeFieldMax(msg, x);
#endif

View File

@ -0,0 +1,10 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
struct EClientMsgSink
{
virtual void serverVersion(int version, const char *time) = 0;
virtual void redirect(const char *host, int port) = 0;
};

View File

@ -0,0 +1,332 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#include "StdAfx.h"
#include "EPosixClientSocketPlatform.h"
#include "EClientSocket.h"
#include "TwsSocketClientErrors.h"
#include "EWrapper.h"
#include "EDecoder.h"
#include "EReaderSignal.h"
#include "EReader.h"
#include "EMessage.h"
#include <string.h>
#include <assert.h>
#include <ostream>
const int MIN_SERVER_VER_SUPPORTED = 38; //all supported server versions are defined in EDecoder.h
///////////////////////////////////////////////////////////
// member funcs
EClientSocket::EClientSocket(EWrapper *ptr, EReaderSignal *pSignal) : EClient( ptr, new ESocket())
{
m_fd = SocketsInit() ? -1 : -2;
m_allowRedirect = false;
m_asyncEConnect = false;
m_pSignal = pSignal;
}
EClientSocket::~EClientSocket()
{
if( m_fd != -2)
SocketsDestroy();
}
bool EClientSocket::asyncEConnect() const {
return m_asyncEConnect;
}
void EClientSocket::asyncEConnect(bool val) {
m_asyncEConnect = val;
}
bool EClientSocket::eConnect( const char *host, unsigned int port, int clientId, bool extraAuth)
{
if( m_fd == -2) {
getWrapper()->error( NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg());
return false;
}
// reset errno
errno = 0;
// already connected?
if( m_fd >= 0) {
errno = EISCONN;
getWrapper()->error( NO_VALID_ID, ALREADY_CONNECTED.code(), ALREADY_CONNECTED.msg());
return false;
}
// normalize host
m_hostNorm = (host && *host) ? host : "127.0.0.1";
// initialize host and port
setHost( m_hostNorm);
setPort( port);
// try to connect to specified host and port
ConnState resState = CS_DISCONNECTED;
return eConnectImpl( clientId, extraAuth, &resState);
}
ESocket *EClientSocket::getTransport() {
assert(dynamic_cast<ESocket*>(m_transport.get()) != 0);
return static_cast<ESocket*>(m_transport.get());
}
bool EClientSocket::eConnectImpl(int clientId, bool extraAuth, ConnState* stateOutPt)
{
// resolve host
struct hostent* hostEnt = gethostbyname( host().c_str());
if ( !hostEnt) {
getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg());
return false;
}
// create socket
m_fd = socket(AF_INET, SOCK_STREAM, 0);
// cannot create socket
if( m_fd < 0) {
getWrapper()->error( NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg());
return false;
}
// starting to connect to server
struct sockaddr_in sa;
memset( &sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons( port());
sa.sin_addr.s_addr = ((in_addr*)hostEnt->h_addr)->s_addr;
// try to connect
if( (connect( m_fd, (struct sockaddr *) &sa, sizeof( sa))) < 0) {
// error connecting
SocketClose( m_fd);
m_fd = -1;
getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg());
return false;
}
getTransport()->fd(m_fd);
// set client id
setClientId( clientId);
setExtraAuth( extraAuth);
int res = sendConnectRequest();
if (res < 0 && !handleSocketError())
return false;
if( !isConnected()) {
if( connState() != CS_DISCONNECTED) {
assert( connState() == CS_REDIRECT);
if( stateOutPt) {
*stateOutPt = connState();
}
eDisconnect();
}
return false;
}
// set socket to non-blocking state
if ( !SetSocketNonBlocking(m_fd)) {
// error setting socket to non-blocking
eDisconnect();
getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg());
return false;
}
assert( connState() == CS_CONNECTED);
if( stateOutPt) {
*stateOutPt = connState();
}
if (!m_asyncEConnect) {
EReader reader(this, m_pSignal);
reader.putMessageToQueue();
while (m_pSignal && !m_serverVersion && isSocketOK()) {
reader.checkClient();
m_pSignal->waitForSignal();
reader.processMsgs();
}
}
// successfully connected
return isSocketOK();
}
void EClientSocket::encodeMsgLen(std::string& msg, unsigned offset) const
{
assert( !msg.empty());
assert( m_useV100Plus);
assert( sizeof(unsigned) == HEADER_LEN);
assert( msg.size() > offset + HEADER_LEN);
unsigned len = msg.size() - HEADER_LEN - offset;
if( len > MAX_MSG_LEN) {
m_pEWrapper->error( NO_VALID_ID, BAD_LENGTH.code(), BAD_LENGTH.msg());
return;
}
unsigned netlen = htonl( len);
memcpy( &msg[offset], &netlen, HEADER_LEN);
}
bool EClientSocket::closeAndSend(std::string msg, unsigned offset)
{
assert( !msg.empty());
if( m_useV100Plus) {
encodeMsgLen( msg, offset);
}
if (bufferedSend(msg) == -1)
return handleSocketError();
return true;
}
void EClientSocket::prepareBufferImpl(std::ostream& buf) const
{
assert( m_useV100Plus);
assert( sizeof(unsigned) == HEADER_LEN);
char header[HEADER_LEN] = { 0 };
buf.write( header, sizeof(header));
}
void EClientSocket::prepareBuffer(std::ostream& buf) const
{
if( !m_useV100Plus)
return;
prepareBufferImpl( buf);
}
void EClientSocket::eDisconnect()
{
if ( m_fd >= 0 )
// close socket
SocketClose( m_fd);
m_fd = -1;
eDisconnectBase();
}
bool EClientSocket::isSocketOK() const
{
return ( m_fd >= 0);
}
int EClientSocket::fd() const
{
return m_fd;
}
int EClientSocket::receive(char* buf, size_t sz)
{
if( sz <= 0)
return 0;
int nResult = ::recv( m_fd, buf, sz, 0);
if( nResult == -1 && !handleSocketError()) {
return -1;
}
if( nResult == 0) {
onClose();
}
if( nResult <= 0) {
return 0;
}
return nResult;
}
void EClientSocket::serverVersion(int version, const char *time) {
m_serverVersion = version;
m_TwsTime = time;
if( usingV100Plus() ? (m_serverVersion < MIN_CLIENT_VER || m_serverVersion > MAX_CLIENT_VER) : m_serverVersion < MIN_SERVER_VER_SUPPORTED ) {
getWrapper()->error( NO_VALID_ID, UNSUPPORTED_VERSION.code(), UNSUPPORTED_VERSION.msg());
eDisconnect();
}
if (!m_asyncEConnect)
startApi();
}
void EClientSocket::redirect(const char *host, int port) {
// handle redirect
if( (m_hostNorm != this->host() || port != this->port())) {
if (!m_allowRedirect) {
getWrapper()->error(NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg());
return;
}
eDisconnect();
eConnectImpl( clientId(), extraAuth(), 0);
}
}
bool EClientSocket::handleSocketError()
{
// no error
if( errno == 0)
return true;
// Socket is already connected
if( errno == EISCONN) {
return true;
}
if( errno == EWOULDBLOCK)
return false;
if( errno == ECONNREFUSED) {
getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg());
}
else {
getWrapper()->error( NO_VALID_ID, SOCKET_EXCEPTION.code(),
SOCKET_EXCEPTION.msg() + strerror(errno));
}
// reset errno
errno = 0;
eDisconnect();
return false;
}
///////////////////////////////////////////////////////////
// callbacks from socket
void EClientSocket::onSend()
{
if( !handleSocketError())
return;
getTransport()->sendBufferedData();
}
void EClientSocket::onClose()
{
if( !handleSocketError())
return;
eDisconnect();
getWrapper()->connectionClosed();
}
void EClientSocket::onError()
{
handleSocketError();
}

View File

@ -0,0 +1,70 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef eposixclientsocket_def
#define eposixclientsocket_def
#include "EClient.h"
#include "EClientMsgSink.h"
#include "ESocket.h"
class EWrapper;
class EReaderSignal;
class TWSAPIDLLEXP EClientSocket : public EClient, public EClientMsgSink
{
protected:
virtual void prepareBufferImpl(std::ostream&) const;
virtual void prepareBuffer(std::ostream&) const;
virtual bool closeAndSend(std::string msg, unsigned offset = 0);
public:
explicit EClientSocket(EWrapper *ptr, EReaderSignal *pSignal = 0);
~EClientSocket();
bool eConnect( const char *host, unsigned int port, int clientId = 0, bool extraAuth = false);
// override virtual funcs from EClient
void eDisconnect();
bool isSocketOK() const;
int fd() const;
bool asyncEConnect() const;
void asyncEConnect(bool val);
ESocket *getTransport();
private:
bool eConnectImpl(int clientId, bool extraAuth, ConnState* stateOutPt);
private:
void encodeMsgLen(std::string& msg, unsigned offset) const;
public:
bool handleSocketError();
int receive( char* buf, size_t sz);
public:
// callback from socket
void onSend();
void onError();
private:
void onClose();
private:
int m_fd;
bool m_allowRedirect;
const char* m_hostNorm;
bool m_asyncEConnect;
EReaderSignal *m_pSignal;
//EClientMsgSink implementation
public:
void serverVersion(int version, const char *time);
void redirect(const char *host, int port);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#include "Contract.h"
//const int MIN_SERVER_VER_REAL_TIME_BARS = 34;
//const int MIN_SERVER_VER_SCALE_ORDERS = 35;
//const int MIN_SERVER_VER_SNAPSHOT_MKT_DATA = 35;
//const int MIN_SERVER_VER_SSHORT_COMBO_LEGS = 35;
//const int MIN_SERVER_VER_WHAT_IF_ORDERS = 36;
//const int MIN_SERVER_VER_CONTRACT_CONID = 37;
const int MIN_SERVER_VER_PTA_ORDERS = 39;
const int MIN_SERVER_VER_FUNDAMENTAL_DATA = 40;
const int MIN_SERVER_VER_UNDER_COMP = 40;
const int MIN_SERVER_VER_CONTRACT_DATA_CHAIN = 40;
const int MIN_SERVER_VER_SCALE_ORDERS2 = 40;
const int MIN_SERVER_VER_ALGO_ORDERS = 41;
const int MIN_SERVER_VER_EXECUTION_DATA_CHAIN = 42;
const int MIN_SERVER_VER_NOT_HELD = 44;
const int MIN_SERVER_VER_SEC_ID_TYPE = 45;
const int MIN_SERVER_VER_PLACE_ORDER_CONID = 46;
const int MIN_SERVER_VER_REQ_MKT_DATA_CONID = 47;
const int MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT = 49;
const int MIN_SERVER_VER_REQ_CALC_OPTION_PRICE = 50;
const int MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT = 50;
const int MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE = 50;
const int MIN_SERVER_VER_SSHORTX_OLD = 51;
const int MIN_SERVER_VER_SSHORTX = 52;
const int MIN_SERVER_VER_REQ_GLOBAL_CANCEL = 53;
const int MIN_SERVER_VER_HEDGE_ORDERS = 54;
const int MIN_SERVER_VER_REQ_MARKET_DATA_TYPE = 55;
const int MIN_SERVER_VER_OPT_OUT_SMART_ROUTING = 56;
const int MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS = 57;
const int MIN_SERVER_VER_DELTA_NEUTRAL_CONID = 58;
const int MIN_SERVER_VER_SCALE_ORDERS3 = 60;
const int MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE = 61;
const int MIN_SERVER_VER_TRAILING_PERCENT = 62;
const int MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE = 66;
const int MIN_SERVER_VER_POSITIONS = 67;
const int MIN_SERVER_VER_ACCOUNT_SUMMARY = 67;
const int MIN_SERVER_VER_TRADING_CLASS = 68;
const int MIN_SERVER_VER_SCALE_TABLE = 69;
const int MIN_SERVER_VER_LINKING = 70;
const int MIN_SERVER_VER_ALGO_ID = 71;
const int MIN_SERVER_VER_OPTIONAL_CAPABILITIES = 72;
const int MIN_SERVER_VER_ORDER_SOLICITED = 73;
const int MIN_SERVER_VER_LINKING_AUTH = 74;
const int MIN_SERVER_VER_PRIMARYEXCH = 75;
const int MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE = 76;
const int MIN_SERVER_VER_FRACTIONAL_POSITIONS = 101;
const int MIN_SERVER_VER_PEGGED_TO_BENCHMARK = 102;
const int MIN_SERVER_VER_MODELS_SUPPORT = 103;
const int MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ = 104;
const int MIN_SERVER_VER_EXT_OPERATOR = 105;
const int MIN_SERVER_VER_SOFT_DOLLAR_TIER = 106;
/* 100+ messaging */
// 100 = enhanced handshake, msg length prefixes
const int MIN_CLIENT_VER = 100;
const int MAX_CLIENT_VER = MIN_SERVER_VER_SOFT_DOLLAR_TIER;
// incoming msg id's
const int TICK_PRICE = 1;
const int TICK_SIZE = 2;
const int ORDER_STATUS = 3;
const int ERR_MSG = 4;
const int OPEN_ORDER = 5;
const int ACCT_VALUE = 6;
const int PORTFOLIO_VALUE = 7;
const int ACCT_UPDATE_TIME = 8;
const int NEXT_VALID_ID = 9;
const int CONTRACT_DATA = 10;
const int EXECUTION_DATA = 11;
const int MARKET_DEPTH = 12;
const int MARKET_DEPTH_L2 = 13;
const int NEWS_BULLETINS = 14;
const int MANAGED_ACCTS = 15;
const int RECEIVE_FA = 16;
const int HISTORICAL_DATA = 17;
const int BOND_CONTRACT_DATA = 18;
const int SCANNER_PARAMETERS = 19;
const int SCANNER_DATA = 20;
const int TICK_OPTION_COMPUTATION = 21;
const int TICK_GENERIC = 45;
const int TICK_STRING = 46;
const int TICK_EFP = 47;
const int CURRENT_TIME = 49;
const int REAL_TIME_BARS = 50;
const int FUNDAMENTAL_DATA = 51;
const int CONTRACT_DATA_END = 52;
const int OPEN_ORDER_END = 53;
const int ACCT_DOWNLOAD_END = 54;
const int EXECUTION_DATA_END = 55;
const int DELTA_NEUTRAL_VALIDATION = 56;
const int TICK_SNAPSHOT_END = 57;
const int MARKET_DATA_TYPE = 58;
const int COMMISSION_REPORT = 59;
const int POSITION_DATA = 61;
const int POSITION_END = 62;
const int ACCOUNT_SUMMARY = 63;
const int ACCOUNT_SUMMARY_END = 64;
const int VERIFY_MESSAGE_API = 65;
const int VERIFY_COMPLETED = 66;
const int DISPLAY_GROUP_LIST = 67;
const int DISPLAY_GROUP_UPDATED = 68;
const int VERIFY_AND_AUTH_MESSAGE_API = 69;
const int VERIFY_AND_AUTH_COMPLETED = 70;
const int POSITION_MULTI = 71;
const int POSITION_MULTI_END = 72;
const int ACCOUNT_UPDATE_MULTI = 73;
const int ACCOUNT_UPDATE_MULTI_END = 74;
const int SECURITY_DEFINITION_OPTION_PARAMETER = 75;
const int SECURITY_DEFINITION_OPTION_PARAMETER_END = 76;
const int SOFT_DOLLAR_TIERS = 77;
const int HEADER_LEN = 4; // 4 bytes for msg length
const int MAX_MSG_LEN = 0xFFFFFF; // 16Mb - 1byte
const char API_SIGN[4] = { 'A', 'P', 'I', '\0' }; // "API"
// helper structures
namespace {
struct BarData {
std::string date;
double open;
double high;
double low;
double close;
int volume;
double average;
std::string hasGaps;
int barCount;
};
struct ScanData {
ContractDetails contract;
int rank;
std::string distance;
std::string benchmark;
std::string projection;
std::string legsStr;
};
} // end of anonymous namespace
///////////////////////////////////////////////////////////
// utility funcs
static std::string errMsg(std::exception e) {
// return the error associated with this exception
return std::string(e.what());
}
class EWrapper;
class EClient;
struct EClientMsgSink;
class TWSAPIDLLEXP EDecoder
{
EWrapper *m_pEWrapper;
int m_serverVersion;
EClientMsgSink *m_pClientMsgSink;
const char* processTickPriceMsg(const char* ptr, const char* endPtr);
const char* processTickSizeMsg(const char* ptr, const char* endPtr);
const char* processTickOptionComputationMsg(const char* ptr, const char* endPtr);
const char* processTickGenericMsg(const char* ptr, const char* endPtr);
const char* processTickStringMsg(const char* ptr, const char* endPtr);
const char* processTickEfpMsg(const char* ptr, const char* endPtr);
const char* processOrderStatusMsg(const char* ptr, const char* endPtr);
const char* processErrMsgMsg(const char* ptr, const char* endPtr);
const char* processOpenOrderMsg(const char* ptr, const char* endPtr);
const char* processAcctValueMsg(const char* ptr, const char* endPtr);
const char* processPortfolioValueMsg(const char* ptr, const char* endPtr);
const char* processAcctUpdateTimeMsg(const char* ptr, const char* endPtr);
const char* processNextValidIdMsg(const char* ptr, const char* endPtr);
const char* processContractDataMsg(const char* ptr, const char* endPtr);
const char* processBondContractDataMsg(const char* ptr, const char* endPtr);
const char* processExecutionDataMsg(const char* ptr, const char* endPtr);
const char* processMarketDepthMsg(const char* ptr, const char* endPtr);
const char* processMarketDepthL2Msg(const char* ptr, const char* endPtr);
const char* processNewsBulletinsMsg(const char* ptr, const char* endPtr);
const char* processManagedAcctsMsg(const char* ptr, const char* endPtr);
const char* processReceiveFaMsg(const char* ptr, const char* endPtr);
const char* processHistoricalDataMsg(const char* ptr, const char* endPtr);
const char* processScannerDataMsg(const char* ptr, const char* endPtr);
const char* processScannerParametersMsg(const char* ptr, const char* endPtr);
const char* processCurrentTimeMsg(const char* ptr, const char* endPtr);
const char* processRealTimeBarsMsg(const char* ptr, const char* endPtr);
const char* processFundamentalDataMsg(const char* ptr, const char* endPtr);
const char* processContractDataEndMsg(const char* ptr, const char* endPtr);
const char* processOpenOrderEndMsg(const char* ptr, const char* endPtr);
const char* processAcctDownloadEndMsg(const char* ptr, const char* endPtr);
const char* processExecutionDataEndMsg(const char* ptr, const char* endPtr);
const char* processDeltaNeutralValidationMsg(const char* ptr, const char* endPtr);
const char* processTickSnapshotEndMsg(const char* ptr, const char* endPtr);
const char* processMarketDataTypeMsg(const char* ptr, const char* endPtr);
const char* processCommissionReportMsg(const char* ptr, const char* endPtr);
const char* processPositionDataMsg(const char* ptr, const char* endPtr);
const char* processPositionEndMsg(const char* ptr, const char* endPtr);
const char* processAccountSummaryMsg(const char* ptr, const char* endPtr);
const char* processAccountSummaryEndMsg(const char* ptr, const char* endPtr);
const char* processVerifyMessageApiMsg(const char* ptr, const char* endPtr);
const char* processVerifyCompletedMsg(const char* ptr, const char* endPtr);
const char* processDisplayGroupListMsg(const char* ptr, const char* endPtr);
const char* processDisplayGroupUpdatedMsg(const char* ptr, const char* endPtr);
const char* processVerifyAndAuthMessageApiMsg(const char* ptr, const char* endPtr);
const char* processVerifyAndAuthCompletedMsg(const char* ptr, const char* endPtr);
const char* processPositionMultiMsg(const char* ptr, const char* endPtr);
const char* processPositionMultiEndMsg(const char* ptr, const char* endPtr);
const char* processAccountUpdateMultiMsg(const char* ptr, const char* endPtr);
const char* processAccountUpdateMultiEndMsg(const char* ptr, const char* endPtr);
const char* processSecurityDefinitionOptionalParameterMsg(const char* ptr, const char* endPtr);
const char* processSecurityDefinitionOptionalParameterEndMsg(const char* ptr, const char* endPtr);
const char* processSoftDollarTiersMsg(const char* ptr, const char* endPtr);
int processConnectAck(const char*& beginPtr, const char* endPtr);
public:
static bool CheckOffset(const char* ptr, const char* endPtr);
static const char* FindFieldEnd(const char* ptr, const char* endPtr);
// decoders
static bool DecodeField(bool&, const char*& ptr, const char* endPtr);
static bool DecodeField(int&, const char*& ptr, const char* endPtr);
static bool DecodeField(long&, const char*& ptr, const char* endPtr);
static bool DecodeField(double&, const char*& ptr, const char* endPtr);
static bool DecodeField(std::string&, const char*& ptr, const char* endPtr);
static bool DecodeFieldMax(int&, const char*& ptr, const char* endPtr);
static bool DecodeFieldMax(long&, const char*& ptr, const char* endPtr);
static bool DecodeFieldMax(double&, const char*& ptr, const char* endPtr);
EDecoder(int serverVersion, EWrapper *callback, EClientMsgSink *clientMsgSink = 0);
int parseAndProcessMsg(const char*& beginPtr, const char* endPtr);
};
#define DECODE_FIELD(x) if (!EDecoder::DecodeField(x, ptr, endPtr)) return 0;
#define DECODE_FIELD_MAX(x) if (!EDecoder::DecodeFieldMax(x, ptr, endPtr)) return 0;

View File

@ -0,0 +1,20 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#include "StdAfx.h"
#include "EMessage.h"
EMessage::EMessage(const std::vector<char> &data) {
this->data = data;
}
const char* EMessage::begin(void) const
{
return data.data();
}
const char* EMessage::end(void) const
{
return data.data() + data.size();
}

View File

@ -0,0 +1,13 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
class TWSAPIDLLEXP EMessage
{
std::vector<char> data;
public:
EMessage(const std::vector<char> &data);
const char* begin(void) const;
const char* end(void) const;
};

View File

@ -0,0 +1,59 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#include "StdAfx.h"
#include "EMutex.h"
EMutex::EMutex()
{
#if defined(IB_POSIX)
pthread_mutex_init(&cs, NULL);
#elif defined(IB_WIN32)
InitializeCriticalSection(&cs);
#else
# error "Not implemented on this platform"
#endif
}
EMutex::~EMutex(void)
{
Leave();
#if defined(IB_POSIX)
pthread_mutex_destroy(&cs);
#elif defined(IB_WIN32)
DeleteCriticalSection(&cs);
#else
# error "Not implemented on this platform"
#endif
}
bool EMutex::TryEnter()
{
#if defined(IB_POSIX)
return pthread_mutex_trylock(&cs) == 0;
#elif defined(IB_WIN32)
return TryEnterCriticalSection(&cs);
#else
# error "Not implemented on this platform"
#endif
}
void EMutex::Enter() {
#if defined(IB_POSIX)
pthread_mutex_lock(&cs);
#elif defined(IB_WIN32)
EnterCriticalSection(&cs);
#else
# error "Not implemented on this platform"
#endif
}
void EMutex::Leave() {
#if defined(IB_POSIX)
pthread_mutex_unlock(&cs);
#elif defined(IB_WIN32)
LeaveCriticalSection(&cs);
#else
# error "Not implemented on this platform"
#endif
}

View File

@ -0,0 +1,25 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#include "StdAfx.h"
class TWSAPIDLLEXP EMutex
{
#if defined(IB_POSIX)
pthread_mutex_t cs;
#elif defined(IB_WIN32)
CRITICAL_SECTION cs;
#else
# error "Not implemented on this platform"
#endif
public:
EMutex();
~EMutex();
bool TryEnter();
void Enter();
void Leave();
};

View File

@ -0,0 +1,65 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#ifndef eposixclientsocketcommon_def
#define eposixclientsocketcommon_def
#ifdef _WIN32
// Windows
// includes
#include <WinSock2.h>
#include <time.h>
// defines
#if _MSC_VER < 1700
#define EISCONN WSAEISCONN
#define EWOULDBLOCK WSAEWOULDBLOCK
#define ECONNREFUSED WSAECONNREFUSED
#else
#pragma comment(lib, "ws2_32.lib")
#endif
// helpers
inline bool SocketsInit( void) {
WSADATA data;
return ( !WSAStartup( MAKEWORD(2, 2), &data));
};
inline bool SocketsDestroy() { return ( !WSACleanup()); };
inline int SocketClose(int sockfd) { return closesocket( sockfd); };
inline bool SetSocketNonBlocking(int sockfd) {
unsigned long mode = 1;
return ( ioctlsocket( sockfd, FIONBIO, &mode) == 0);
};
#else
// LINUX
// includes
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/fcntl.h>
#include <unistd.h>
// helpers
inline bool SocketsInit() { return true; };
inline bool SocketsDestroy() { return true; };
inline int SocketClose(int sockfd) { return close( sockfd); };
inline bool SetSocketNonBlocking(int sockfd) {
// get socket flags
int flags = fcntl(sockfd, F_GETFL);
if (flags == -1)
return false;
// set non-blocking mode
return ( fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == 0);
};
#endif
#endif

View File

@ -0,0 +1,290 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#include "StdAfx.h"
#include "shared_ptr.h"
#include "Contract.h"
#include "EDecoder.h"
#include "EMutex.h"
#include "EReader.h"
#include "EClientSocket.h"
#include "EPosixClientSocketPlatform.h"
#include "EReaderSignal.h"
#include "EMessage.h"
#include "DefaultEWrapper.h"
#define IN_BUF_SIZE_DEFAULT 8192
static DefaultEWrapper defaultWrapper;
EReader::EReader(EClientSocket *clientSocket, EReaderSignal *signal)
: processMsgsDecoder_(clientSocket->EClient::serverVersion(), clientSocket->getWrapper(), clientSocket) {
m_isAlive = true;
m_pClientSocket = clientSocket;
m_pEReaderSignal = signal;
m_needsWriteSelect = false;
m_nMaxBufSize = IN_BUF_SIZE_DEFAULT;
m_buf.reserve(IN_BUF_SIZE_DEFAULT);
}
EReader::~EReader(void) {
m_isAlive = false;
#if defined(IB_WIN32)
WaitForSingleObject(m_hReadThread, INFINITE);
#endif
}
void EReader::checkClient() {
m_needsWriteSelect = !m_pClientSocket->getTransport()->isOutBufferEmpty();
}
void EReader::start() {
#if defined(IB_POSIX)
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create( &thread, &attr, readToQueueThread, this );
pthread_attr_destroy(&attr);
#elif defined(IB_WIN32)
m_hReadThread = CreateThread(0, 0, readToQueueThread, this, 0, 0);
#else
# error "Not implemented on this platform"
#endif
}
#if defined(IB_POSIX)
void * EReader::readToQueueThread(void * lpParam)
#elif defined(IB_WIN32)
DWORD WINAPI EReader::readToQueueThread(LPVOID lpParam)
#else
# error "Not implemented on this platform"
#endif
{
EReader *pThis = reinterpret_cast<EReader *>(lpParam);
pThis->readToQueue();
return 0;
}
void EReader::readToQueue() {
EMessage *msg = 0;
while (m_isAlive) {
if (m_buf.size() == 0 && !processNonBlockingSelect() && m_pClientSocket->isSocketOK())
continue;
if (!putMessageToQueue())
break;
}
m_pClientSocket->handleSocketError();
m_pEReaderSignal->issueSignal(); //letting client know that socket was closed
}
bool EReader::putMessageToQueue() {
EMessage *msg = 0;
if (m_pClientSocket->isSocketOK())
msg = readSingleMsg();
if (msg == 0)
return false;
m_csMsgQueue.Enter();
m_msgQueue.push_back(ibapi::shared_ptr<EMessage>(msg));
m_csMsgQueue.Leave();
m_pEReaderSignal->issueSignal();
return true;
}
bool EReader::processNonBlockingSelect() {
fd_set readSet, writeSet, errorSet;
struct timeval tval;
tval.tv_usec = 100 * 1000; //100 ms
tval.tv_sec = 0;
if( m_pClientSocket->fd() >= 0 ) {
FD_ZERO( &readSet);
errorSet = writeSet = readSet;
FD_SET( m_pClientSocket->fd(), &readSet);
if (m_needsWriteSelect)
FD_SET( m_pClientSocket->fd(), &writeSet);
FD_SET( m_pClientSocket->fd(), &errorSet);
int ret = select( m_pClientSocket->fd() + 1, &readSet, &writeSet, &errorSet, &tval);
if( ret == 0) { // timeout
return false;
}
if( ret < 0) { // error
m_pClientSocket->eDisconnect();
return false;
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &errorSet)) {
// error on socket
m_pClientSocket->onError();
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &writeSet)) {
// socket is ready for writing
onSend();
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &readSet)) {
// socket is ready for reading
onReceive();
}
return true;
}
return false;
}
void EReader::onSend() {
m_pEReaderSignal->issueSignal();
}
void EReader::onReceive() {
int nOffset = m_buf.size();
m_buf.resize(m_nMaxBufSize);
int nRes = m_pClientSocket->receive(m_buf.data() + nOffset, m_buf.size() - nOffset);
if (nRes <= 0)
return;
m_buf.resize(nRes + nOffset);
}
bool EReader::bufferedRead(char *buf, int size) {
while (size > 0) {
while (m_buf.size() < size && m_buf.size() < m_nMaxBufSize)
if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
return false;
int nBytes = min(m_nMaxBufSize, size);
std::copy(m_buf.begin(), m_buf.begin() + nBytes, buf);
std::copy(m_buf.begin() + nBytes, m_buf.end(), m_buf.begin());
m_buf.resize(m_buf.size() - nBytes);
size -= nBytes;
buf += nBytes;
}
return true;
}
EMessage * EReader::readSingleMsg() {
if (m_pClientSocket->usingV100Plus()) {
int msgSize;
if (!bufferedRead((char *)&msgSize, sizeof(msgSize)))
return 0;
msgSize = htonl(msgSize);
if (msgSize <= 0 || msgSize > MAX_MSG_LEN)
return 0;
std::vector<char> buf = std::vector<char>(msgSize);
if (!bufferedRead(buf.data(), buf.size()))
return 0;
return new EMessage(buf);
}
else {
const char *pBegin = 0;
const char *pEnd = 0;
int msgSize = 0;
while (msgSize == 0)
{
if (m_buf.size() >= m_nMaxBufSize * 3/4)
m_nMaxBufSize *= 2;
if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
return 0;
pBegin = m_buf.data();
pEnd = pBegin + m_buf.size();
msgSize = EDecoder(m_pClientSocket->EClient::serverVersion(), &defaultWrapper).parseAndProcessMsg(pBegin, pEnd);
}
std::vector<char> msgData(msgSize);
if (!bufferedRead(msgData.data(), msgSize))
return 0;
if (m_buf.size() < IN_BUF_SIZE_DEFAULT && m_buf.capacity() > IN_BUF_SIZE_DEFAULT)
{
m_buf.resize(m_nMaxBufSize = IN_BUF_SIZE_DEFAULT);
m_buf.shrink_to_fit();
}
EMessage * msg = new EMessage(msgData);
return msg;
}
}
ibapi::shared_ptr<EMessage> EReader::getMsg(void) {
m_csMsgQueue.Enter();
if (m_msgQueue.size() == 0) {
m_csMsgQueue.Leave();
return ibapi::shared_ptr<EMessage>();
}
ibapi::shared_ptr<EMessage> msg = m_msgQueue.front();
m_msgQueue.pop_front();
m_csMsgQueue.Leave();
return msg;
}
void EReader::processMsgs(void) {
m_pClientSocket->onSend();
checkClient();
ibapi::shared_ptr<EMessage> msg = getMsg();
if (!msg.get())
return;
const char *pBegin = msg->begin();
while (processMsgsDecoder_.parseAndProcessMsg(pBegin, msg->end()) > 0) {
msg = getMsg();
if (!msg.get())
break;
pBegin = msg->begin();
}
}

View File

@ -0,0 +1,58 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#include "StdAfx.h"
#include "EDecoder.h"
#include "EMutex.h"
#include "EReaderOSSignal.h"
class EClientSocket;
class EReaderSignal;
class EMessage;
class TWSAPIDLLEXP EReader
{
EClientSocket *m_pClientSocket;
EReaderSignal *m_pEReaderSignal;
EDecoder processMsgsDecoder_;
std::deque<ibapi::shared_ptr<EMessage>> m_msgQueue;
EMutex m_csMsgQueue;
std::vector<char> m_buf;
bool m_needsWriteSelect;
bool m_isAlive;
#if defined(IB_WIN32)
HANDLE m_hReadThread;
#endif
int m_nMaxBufSize;
void onReceive();
void onSend();
bool bufferedRead(char *buf, int size);
public:
EReader(EClientSocket *clientSocket, EReaderSignal *signal);
~EReader(void);
protected:
bool processNonBlockingSelect();
ibapi::shared_ptr<EMessage> getMsg(void);
void readToQueue();
#if defined(IB_POSIX)
static void * readToQueueThread(void * lpParam);
#elif defined(IB_WIN32)
static DWORD WINAPI readToQueueThread(LPVOID lpParam);
#else
# error "Not implemented on this platform"
#endif
EMessage * readSingleMsg();
public:
void processMsgs(void);
void checkClient();
bool putMessageToQueue();
void start();
};

View File

@ -0,0 +1,73 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#include "StdAfx.h"
#include "EReaderOSSignal.h"
#define MS_IN_SEC 1000
EReaderOSSignal::EReaderOSSignal(unsigned long waitTimeout) throw (std::runtime_error)
{
bool ok = false;
m_waitTimeout = waitTimeout;
#if defined(IB_POSIX)
int rc1 = pthread_mutex_init(&m_mutex, NULL);
int rc2 = pthread_cond_init(&m_evMsgs, NULL);
ok = rc1 == 0 && rc2 == 0;
#elif defined(IB_WIN32)
m_evMsgs = CreateEvent(0, false, false, 0);
ok = (NULL != m_evMsgs);
#else
# error "Not implemented on this platform"
#endif
if (!ok)
throw std::runtime_error("Failed to create event");
}
EReaderOSSignal::~EReaderOSSignal(void)
{
#if defined(IB_POSIX)
pthread_cond_destroy(&m_evMsgs);
pthread_mutex_destroy(&m_mutex);
#elif defined(IB_WIN32)
CloseHandle(m_evMsgs);
#else
# error "Not implemented on this platform"
#endif
}
void EReaderOSSignal::issueSignal() {
#if defined(IB_POSIX)
pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_evMsgs);
pthread_mutex_unlock(&m_mutex);
#elif defined(IB_WIN32)
SetEvent(m_evMsgs);
#else
# error "Not implemented on this platform"
#endif
}
void EReaderOSSignal::waitForSignal() {
#if defined(IB_POSIX)
pthread_mutex_lock(&m_mutex);
if ( m_waitTimeout == INFINITE ) {
pthread_cond_wait(&m_evMsgs, &m_mutex);
}
else {
struct timespec ts;
ts.tv_sec = m_waitTimeout/MS_IN_SEC;
ts.tv_nsec = (m_waitTimeout%MS_IN_SEC)*1000/*us/ms*/*1000/*ns/us*/;
pthread_cond_timedwait(&m_evMsgs, &m_mutex, &ts);
}
pthread_mutex_unlock(&m_mutex);
#elif defined(IB_WIN32)
WaitForSingleObject(m_evMsgs, m_waitTimeout);
#else
# error "Not implemented on this platform"
#endif
}

View File

@ -0,0 +1,33 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#include "EReaderSignal.h"
#include "StdAfx.h"
#include <stdexcept>
#if !defined(INFINITE)
#define INFINITE ((unsigned long)-1)
#endif
class TWSAPIDLLEXP EReaderOSSignal :
public EReaderSignal
{
#if defined(IB_POSIX)
pthread_cond_t m_evMsgs;
pthread_mutex_t m_mutex;
#elif defined(IB_WIN32)
HANDLE m_evMsgs;
#else
# error "Not implemented on this platform"
#endif
unsigned long m_waitTimeout; // in milliseconds
public:
EReaderOSSignal(unsigned long waitTimeout = INFINITE) throw (std::runtime_error);
~EReaderOSSignal(void);
virtual void issueSignal();
virtual void waitForSignal();
};

View File

@ -0,0 +1,10 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
struct EReaderSignal
{
virtual void issueSignal() = 0;
virtual void waitForSignal() = 0;
};

View File

@ -0,0 +1,25 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#include "StdAfx.h"
#if defined(IB_WIN32)
#include "EReaderWMSignal.h"
EReaderWMSignal::EReaderWMSignal(HWND hWnd, int wmUserOffset) {
m_hWnd = hWnd;
m_msg = WM_USER + wmUserOffset;
}
void EReaderWMSignal::issueSignal() {
if (IsWindow(m_hWnd))
PostMessage(m_hWnd, m_msg, 0, 0);
}
void EReaderWMSignal::waitForSignal() {
MSG msg;
if (GetMessage(&msg, 0, m_msg, m_msg))
DispatchMessage(&msg);
}
#endif

View File

@ -0,0 +1,19 @@
/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
#pragma once
#include "ereadersignal.h"
class EReaderWMSignal :
public EReaderSignal
{
HWND m_hWnd;
int m_msg;
public:
EReaderWMSignal(HWND hWnd, int msg);
virtual void issueSignal();
virtual void waitForSignal();
};

View File

@ -0,0 +1,102 @@
#include "StdAfx.h"
#include "EMessage.h"
#include "ESocket.h"
#include <assert.h>
#if defined(IB_POSIX)
#include <sys/socket.h>
#endif
ESocket::ESocket() {
}
void ESocket::fd(int fd) {
m_fd = fd;
}
ESocket::~ESocket(void) {
}
int ESocket::send(EMessage *pMsg) {
return bufferedSend(pMsg->begin(), pMsg->end() - pMsg->begin());
}
int ESocket::bufferedSend(const char* buf, size_t sz)
{
if( sz <= 0)
return 0;
if( !m_outBuffer.empty()) {
m_outBuffer.insert( m_outBuffer.end(), buf, buf + sz);
return sendBufferedData();
}
int nResult = send(buf, sz);
if( nResult < (int)sz) {
int sent = (std::max)( nResult, 0);
m_outBuffer.insert( m_outBuffer.end(), buf + sent, buf + sz);
}
return nResult;
}
int ESocket::sendBufferedData()
{
if( m_outBuffer.empty())
return 0;
int nResult = send( &m_outBuffer[0], m_outBuffer.size());
if( nResult <= 0) {
return nResult;
}
CleanupBuffer( m_outBuffer, nResult);
return nResult;
}
int ESocket::send(const char* buf, size_t sz)
{
if( sz <= 0)
return 0;
int nResult = ::send( m_fd, buf, sz, 0);
if( nResult == -1) {
return -1;
}
if( nResult <= 0) {
return 0;
}
return nResult;
}
static const size_t BufferSizeHighMark = 1 * 1024 * 1024; // 1Mb
void ESocket::CleanupBuffer(std::vector<char>& buffer, int processed)
{
assert( buffer.empty() || processed <= (int)buffer.size());
if( buffer.empty())
return;
if( processed <= 0)
return;
if( (size_t)processed == buffer.size()) {
if( buffer.capacity() >= BufferSizeHighMark) {
std::vector<char>().swap(buffer);
}
else {
buffer.clear();
}
}
else {
buffer.erase( buffer.begin(), buffer.begin() + processed);
}
}
bool ESocket::isOutBufferEmpty() const
{
return m_outBuffer.empty();
}

Some files were not shown because too many files have changed in this diff Show More