Commits

Keli Hu committed 0f50e21

ibapi 9.67 beta

Comments (0)

Files changed (23)

CommissionReport.h

+#ifndef commissionreport_def
+#define commissionreport_def
+
+#include "IBString.h"
+
+struct CommissionReport
+{
+	CommissionReport()
+	{
+		commission = 0;
+		realizedPNL = 0;
+		yield = 0;
+		yieldRedemptionDate = 0;
+	}
+
+	// commission report fields
+	IBString	execId;
+	double		commission;
+	IBString	currency;
+	double		realizedPNL;
+	double		yield;
+	int			yieldRedemptionDate; // YYYYMMDD format
+};
+
+#endif // commissionreport_def
+#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" ;
+			break ;
+		case PROFILES:
+			return "PROFILES" ;
+			break ;
+		case ALIASES:
+			return "ALIASES" ;
+			break ;
+	}
+	return 0 ;
+}
+
+enum MarketDataType { 
+	REALTIME = 1, 
+	FROZEN = 2
+};
+
+#endif /* common_defs_h_INCLUDED */
+#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;
+   IBString action; //BUY/SELL/SSHORT
+
+   IBString exchange;
+   long    openClose; // LegOpenClose enum values
+
+   // for stock legs when doing short sale
+   long    shortSaleSlot; // 1 = clearing broker, 2 = third party
+   IBString designatedLocation;
+   int     exemptCode;
+
+   bool operator==( const ComboLeg &other) const
+   {
+      return (conId == other.conId &&
+         ratio == other.ratio &&
+		 openClose == other.openClose &&
+		 shortSaleSlot == other.shortSaleSlot &&
+		 (Compare(action, other.action) == 0) &&
+		 (Compare(exchange, other.exchange) == 0) &&
+		 (Compare(designatedLocation, other.designatedLocation) == 0) &&
+		 exemptCode == other.exemptCode);
+   }
+};
+
+struct UnderComp
+{
+	UnderComp()
+		: conId(0)
+		, delta(0)
+		, price(0)
+	{}
+
+	long	conId;
+	double	delta;
+	double	price;
+};
+
+typedef shared_ptr<ComboLeg> ComboLegSPtr;
+
+struct Contract
+{
+   Contract()
+      : conId(0)
+	  , strike(0)
+	  , includeExpired(false)
+	  , comboLegs(NULL)
+	  , underComp(NULL)
+   {
+   }
+
+   long    conId;
+   IBString symbol;
+   IBString secType;
+   IBString expiry;
+   double  strike;
+   IBString right;
+   IBString multiplier;
+   IBString exchange;
+   IBString primaryExchange; // pick an actual (ie non-aggregate) exchange that the contract trades on.  DO NOT SET TO SMART.
+   IBString currency;
+   IBString localSymbol;
+   bool includeExpired;
+   IBString secIdType;		// CUSIP;SEDOL;ISIN;RIC
+   IBString secId;
+
+   // COMBOS
+   IBString comboLegsDescrip; // received in open order 14 and up for all combos
+
+	// combo legs
+   typedef std::vector<ComboLegSPtr> ComboLegList;
+   typedef 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)
+	  , callable(false)
+	  , putable(false)
+	  , coupon(0)
+	  , convertible(false)
+	  , nextOptionPartial(false)
+	  , evMultiplier(0)
+		
+   {
+   }
+
+   Contract	summary;
+   IBString	marketName;
+   IBString	tradingClass;
+   double	minTick;
+   IBString	orderTypes;
+   IBString	validExchanges;
+   long		priceMagnifier;
+   int		underConId;
+   IBString	longName;
+   IBString	contractMonth;
+   IBString	industry;
+   IBString	category;
+   IBString	subcategory;
+   IBString	timeZoneId;
+   IBString	tradingHours;
+   IBString	liquidHours;
+   IBString evRule;
+   double   evMultiplier;
+
+   TagValueListSPtr secIdList;
+
+   // BOND values
+   IBString cusip;
+   IBString ratings;
+   IBString descAppend;
+   IBString bondType;
+   IBString couponType;
+   bool callable;
+   bool putable;
+   double coupon;
+   bool convertible;
+   IBString maturity;
+   IBString issueDate;
+   IBString nextOptionDate;
+   IBString nextOptionType;
+   bool nextOptionPartial;
+   IBString 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
+#ifndef eclient_def
+#define eclient_def
+
+#include "CommonDefs.h"
+#include "IBString.h"
+
+struct Contract;
+struct Order;
+struct ExecutionFilter;
+struct ScannerSubscription;
+
+class EClient
+{
+public:
+   virtual ~EClient() {}
+   virtual bool eConnect( const char *host, unsigned int port, int clientId=0) = 0;
+   virtual void eDisconnect() = 0;
+   virtual int serverVersion() = 0;
+   virtual IBString TwsConnectionTime() = 0;
+   virtual void reqMktData( TickerId id, const Contract &contract,
+	   const IBString& genericTicks, bool snapshot) = 0;
+   virtual void cancelMktData( TickerId id) = 0;
+   virtual void placeOrder( OrderId id, const Contract &contract, const Order &order) = 0;
+   virtual void cancelOrder( OrderId id) = 0;
+   virtual void reqOpenOrders() = 0;
+   virtual void reqAccountUpdates(bool subscribe, const IBString& acctCode) = 0;
+   virtual void reqExecutions(int reqId, const ExecutionFilter& filter) = 0;
+   virtual void reqIds( int numIds) = 0;
+   virtual bool checkMessages() = 0;
+   virtual void reqContractDetails( int reqId, const Contract &contract) = 0;
+   virtual void reqMktDepth( TickerId id, const Contract &contract, int numRows) = 0;
+   virtual void cancelMktDepth( TickerId id) = 0;
+   virtual void reqNewsBulletins( bool allMsgs) = 0;
+   virtual void cancelNewsBulletins() = 0;
+   virtual void setServerLogLevel(int level) = 0;
+   virtual void reqAutoOpenOrders(bool bAutoBind) = 0;
+   virtual void reqAllOpenOrders() = 0;
+   virtual void reqManagedAccts() = 0;
+   virtual void requestFA(faDataType pFaDataType) = 0;
+   virtual void replaceFA(faDataType pFaDataType, const IBString& cxml) = 0;
+   virtual void reqHistoricalData( TickerId id, const Contract &contract,
+	   const IBString &endDateTime, const IBString &durationStr, const IBString &barSizeSetting,
+	   const IBString &whatToShow, int useRTH, int formatDate) = 0;
+   virtual void exerciseOptions( TickerId id, const Contract &contract,
+       int exerciseAction, int exerciseQuantity, const IBString &account, int override) = 0;
+   virtual void cancelHistoricalData( TickerId tickerId ) = 0;
+   virtual void reqRealTimeBars( TickerId id, const Contract &contract, int barSize,
+	   const IBString &whatToShow, bool useRTH) = 0;
+   virtual void cancelRealTimeBars( TickerId tickerId) = 0;
+   virtual void cancelScannerSubscription( int tickerId) = 0;
+   virtual void reqScannerParameters() = 0;
+   virtual void reqScannerSubscription( int tickerId, const ScannerSubscription &subscription) = 0;
+   virtual void reqCurrentTime() = 0;
+   virtual void reqFundamentalData( TickerId reqId, const Contract&, const IBString& reportType) = 0;
+   virtual void cancelFundamentalData( TickerId reqId) = 0;
+   virtual void calculateImpliedVolatility( TickerId reqId, const Contract &contract, double optionPrice, double underPrice) = 0;
+   virtual void calculateOptionPrice( TickerId reqId, const Contract &contract, double volatility, double underPrice) = 0;
+   virtual void cancelCalculateImpliedVolatility( TickerId reqId) = 0;
+   virtual void cancelCalculateOptionPrice( TickerId reqId) = 0;
+   virtual void reqGlobalCancel() = 0;
+   virtual void reqMarketDataType( int marketDataType) = 0;
+private:
+};
+
+#endif

EClientSocketBase.cpp

+#include "EClientSocketBaseImpl.h"
+

EClientSocketBase.h

+#ifndef eclientsocketbase_h__INCLUDED
+#define eclientsocketbase_h__INCLUDED
+
+#include "EClient.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class EWrapper;
+
+class EClientSocketBase : public EClient
+{
+public:
+
+	explicit EClientSocketBase(EWrapper *ptr);
+	~EClientSocketBase();
+
+	virtual bool eConnect(const char *host, unsigned int port, int clientId=0) = 0;
+	virtual void eDisconnect() = 0;
+
+	int clientId() const { return m_clientId; }
+
+protected:
+
+	void eConnectBase();
+	void eDisconnectBase();
+
+public:
+
+	// connection state
+	bool isConnected() const;
+
+protected:
+
+	// access to protected variables
+	EWrapper * getWrapper() const;
+	void setClientId( int clientId);
+
+public:
+
+	bool isInBufferEmpty() const;
+	bool isOutBufferEmpty() const;
+
+	// override virtual funcs from EClient
+	int serverVersion();
+	IBString TwsConnectionTime();
+	void reqMktData(TickerId id, const Contract &contract,
+		const IBString &genericTicks, bool snapshot);
+	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 IBString& acctCode);
+	void reqExecutions(int reqId, const ExecutionFilter& filter);
+	void reqIds(int numIds);
+	bool checkMessages();
+	void reqContractDetails(int reqId, const Contract &contract);
+	void reqMktDepth(TickerId tickerId, const Contract &contract, int numRows);
+	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 IBString& cxml);
+	void reqHistoricalData( TickerId id, const Contract &contract,
+		const IBString &endDateTime, const IBString &durationStr,
+		const IBString & barSizeSetting, const IBString &whatToShow,
+		int useRTH, int formatDate);
+	void exerciseOptions(TickerId tickerId, const Contract &contract,
+		int exerciseAction, int exerciseQuantity,
+		const IBString &account, int override);
+	void cancelHistoricalData(TickerId tickerId );
+	void reqRealTimeBars(TickerId id, const Contract &contract, int barSize,
+		const IBString &whatToShow, bool useRTH);
+	void cancelRealTimeBars(TickerId tickerId );
+	void cancelScannerSubscription(int tickerId);
+	void reqScannerParameters();
+	void reqScannerSubscription(int tickerId, const ScannerSubscription &subscription);
+	void reqCurrentTime();
+	void reqFundamentalData(TickerId reqId, const Contract&, const IBString& 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);
+
+private:
+
+	virtual int send(const char* buf, size_t sz) = 0;
+	virtual int receive(char* buf, size_t sz) = 0;
+
+protected:
+
+	int sendBufferedData();
+
+private:
+
+	int bufferedSend(const char* buf, size_t sz);
+	int bufferedSend(const std::string& msg);
+
+	// read and buffer what's available
+	int bufferedRead();
+
+	// try to process connection request ack
+	int processConnectAck(const char*& ptr, const char* endPtr);
+
+	// try to process single msg
+	int processMsg(const char*& ptr, const char* endPtr);
+
+	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(IBString&, 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);
+
+	// 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
+	virtual bool isSocketOK() const = 0;
+
+protected:
+
+	void onConnectBase();
+
+private:
+
+	typedef std::vector<char> BytesVec;
+
+private:
+
+	static void CleanupBuffer(BytesVec&, int processed);
+
+private:
+
+	EWrapper *m_pEWrapper;
+
+	BytesVec m_inBuffer;
+	BytesVec m_outBuffer;
+
+	int m_clientId;
+
+	bool m_connected;
+	int m_serverVersion;
+	IBString m_TwsTime;
+
+};
+
+template<> void EClientSocketBase::EncodeField<bool>(std::ostream& os, bool);
+template<> void EClientSocketBase::EncodeField<double>(std::ostream& os, double);
+
+#endif

EClientSocketBaseImpl.h

+#ifndef eclientsocketbaseimpl_h__INCLUDED
+#define eclientsocketbaseimpl_h__INCLUDED
+
+#include "EClientSocketBase.h"
+
+#include "EWrapper.h"
+#include "TwsSocketClientErrors.h"
+#include "Contract.h"
+#include "Order.h"
+#include "OrderState.h"
+#include "Execution.h"
+#include "ScannerSubscription.h"
+#include "CommissionReport.h"
+
+
+#include <sstream>
+#include <iomanip>
+#include <algorithm>
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+/////////////////////////////////////////////////////////////////////////////////
+// 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
+const int CLIENT_VERSION    = 59;
+const int SERVER_VERSION    = 38;
+
+// 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 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;
+
+// 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;
+
+// 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
+
+///////////////////////////////////////////////////////////
+// helper macroses
+#define DECODE_FIELD(x) if (!DecodeField(x, ptr, endPtr)) return 0;
+#define DECODE_FIELD_MAX(x) if (!DecodeFieldMax(x, ptr, endPtr)) return 0;
+
+#define ENCODE_FIELD(x) EncodeField(msg, x);
+#define ENCODE_FIELD_MAX(x) EncodeFieldMax(msg, x);
+
+///////////////////////////////////////////////////////////
+// helper structures
+namespace {
+
+struct BarData {
+	IBString date;
+	double open;
+	double high;
+	double low;
+	double close;
+	int volume;
+	double average;
+	IBString hasGaps;
+	int barCount;
+};
+
+struct ScanData {
+	ContractDetails contract;
+	int rank;
+	IBString distance;
+	IBString benchmark;
+	IBString projection;
+	IBString legsStr;
+};
+
+} // end of anonymous namespace
+
+///////////////////////////////////////////////////////////
+// encoders
+template<class T>
+void EClientSocketBase::EncodeField(std::ostream& os, T value)
+{
+	os << value << '\0';
+}
+
+template<>
+void EClientSocketBase::EncodeField<bool>(std::ostream& os, bool boolValue)
+{
+	EncodeField<int>(os, boolValue ? 1 : 0);
+}
+
+template<>
+void EClientSocketBase::EncodeField<double>(std::ostream& os, double doubleValue)
+{
+	char str[128];
+
+	snprintf(str, sizeof(str), "%.10g", doubleValue);
+
+	EncodeField<const char*>(os, str);
+}
+
+///////////////////////////////////////////////////////////
+// "max" encoders
+void EClientSocketBase::EncodeFieldMax(std::ostream& os, int intValue)
+{
+	if( intValue == INT_MAX) {
+		EncodeField(os, "");
+		return;
+	}
+	EncodeField(os, intValue);
+}
+
+void EClientSocketBase::EncodeFieldMax(std::ostream& os, double doubleValue)
+{
+	if( doubleValue == DBL_MAX) {
+		EncodeField(os, "");
+		return;
+	}
+	EncodeField(os, doubleValue);
+}
+
+///////////////////////////////////////////////////////////
+// decoders
+bool EClientSocketBase::CheckOffset(const char* ptr, const char* endPtr)
+{
+	assert (ptr && ptr <= endPtr);
+	return (ptr && ptr < endPtr);
+}
+
+const char* EClientSocketBase::FindFieldEnd(const char* ptr, const char* endPtr)
+{
+	return (const char*)memchr(ptr, 0, endPtr - ptr);
+}
+
+bool EClientSocketBase::DecodeField(bool& boolValue, const char*& ptr, const char* endPtr)
+{
+	int intValue;
+	if( !DecodeField(intValue, ptr, endPtr))
+		return false;
+	boolValue = (intValue > 0);
+	return true;
+}
+
+bool EClientSocketBase::DecodeField(int& intValue, const char*& ptr, const char* endPtr)
+{
+	if( !CheckOffset(ptr, endPtr))
+		return false;
+	const char* fieldBeg = ptr;
+	const char* fieldEnd = FindFieldEnd(fieldBeg, endPtr);
+	if( !fieldEnd)
+		return false;
+	intValue = atoi(fieldBeg);
+	ptr = ++fieldEnd;
+	return true;
+}
+
+bool EClientSocketBase::DecodeField(long& longValue, const char*& ptr, const char* endPtr)
+{
+	int intValue;
+	if( !DecodeField(intValue, ptr, endPtr))
+		return false;
+	longValue = intValue;
+	return true;
+}
+
+bool EClientSocketBase::DecodeField(double& doubleValue, const char*& ptr, const char* endPtr)
+{
+	if( !CheckOffset(ptr, endPtr))
+		return false;
+	const char* fieldBeg = ptr;
+	const char* fieldEnd = FindFieldEnd(fieldBeg, endPtr);
+	if( !fieldEnd)
+		return false;
+	doubleValue = atof(fieldBeg);
+	ptr = ++fieldEnd;
+	return true;
+}
+
+bool EClientSocketBase::DecodeField(IBString& stringValue,
+								const char*& ptr, const char* endPtr)
+{
+	if( !CheckOffset(ptr, endPtr))
+		return false;
+	const char* fieldBeg = ptr;
+	const char* fieldEnd = FindFieldEnd(ptr, endPtr);
+	if( !fieldEnd)
+		return false;
+	stringValue = fieldBeg; // better way?
+	ptr = ++fieldEnd;
+	return true;
+}
+
+bool EClientSocketBase::DecodeFieldMax(int& intValue, const char*& ptr, const char* endPtr)
+{
+	IBString stringValue;
+	if( !DecodeField(stringValue, ptr, endPtr))
+		return false;
+	intValue = (IsEmpty(stringValue) ? UNSET_INTEGER : Atoi(stringValue));
+	return true;
+}
+
+bool EClientSocketBase::DecodeFieldMax(long& longValue, const char*& ptr, const char* endPtr)
+{
+	int intValue;
+	if( !DecodeFieldMax(intValue, ptr, endPtr))
+		return false;
+	longValue = intValue;
+	return true;
+}
+
+bool EClientSocketBase::DecodeFieldMax(double& doubleValue, const char*& ptr, const char* endPtr)
+{
+	IBString stringValue;
+	if( !DecodeField(stringValue, ptr, endPtr))
+		return false;
+	doubleValue = (IsEmpty(stringValue) ? UNSET_DOUBLE : Atof(stringValue));
+	return true;
+}
+
+///////////////////////////////////////////////////////////
+// static helpers
+
+static const size_t BufferSizeHighMark = 1 * 1024 * 1024; // 1Mb
+
+void EClientSocketBase::CleanupBuffer(BytesVec& 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) {
+			BytesVec().swap(buffer);
+		}
+		else {
+			buffer.clear();
+		}
+	}
+	else {
+		buffer.erase( buffer.begin(), buffer.begin() + processed);
+	}
+};
+
+///////////////////////////////////////////////////////////
+// utility funcs
+static IBString errMsg(std::exception e) {
+	// return the error associated with this exception
+	return IBString(e.what());
+}
+
+
+#ifdef _MSC_VER
+static IBString errMsg(CException *e) {
+	// return the error associated with this exception
+	char buf[1024];
+	e->GetErrorMessage( buf, sizeof buf);
+	return IBString( buf);
+}
+#endif
+
+///////////////////////////////////////////////////////////
+// member funcs
+EClientSocketBase::EClientSocketBase( EWrapper *ptr)
+	: m_pEWrapper(ptr)
+	, m_clientId(-1)
+	, m_connected(false)
+	, m_serverVersion(0)
+{
+}
+
+EClientSocketBase::~EClientSocketBase()
+{
+}
+
+void EClientSocketBase::eConnectBase()
+{
+}
+
+void EClientSocketBase::eDisconnectBase()
+{
+	Empty(m_TwsTime);
+	m_serverVersion = 0;
+	m_connected = false;
+	m_clientId = -1;
+	m_outBuffer.clear();
+	m_inBuffer.clear();
+}
+
+int EClientSocketBase::serverVersion()
+{
+	return m_serverVersion;
+}
+
+IBString EClientSocketBase::TwsConnectionTime()
+{
+	return m_TwsTime;
+}
+
+void EClientSocketBase::reqMktData(TickerId tickerId, const Contract& contract,
+							   const IBString& genericTicks, bool snapshot)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// not needed anymore validation
+	//if( m_serverVersion < MIN_SERVER_VER_SNAPSHOT_MKT_DATA && snapshot) {
+	//	m_pEWrapper->error( tickerId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support snapshot market data requests.");
+	//	return;
+	//}
+
+	if( m_serverVersion < MIN_SERVER_VER_UNDER_COMP) {
+		if( contract.underComp) {
+			m_pEWrapper->error( tickerId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support delta-neutral orders.");
+			return;
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_REQ_MKT_DATA_CONID) {
+		if( contract.conId > 0) {
+			m_pEWrapper->error( tickerId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support conId parameter.");
+			return;
+		}
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 9;
+
+	// send req mkt data msg
+	ENCODE_FIELD( REQ_MKT_DATA);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	// send contract fields
+	if( m_serverVersion >= MIN_SERVER_VER_REQ_MKT_DATA_CONID) {
+		ENCODE_FIELD( contract.conId);
+	}
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier); // srv v15 and above
+
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.primaryExchange); // srv v14 and above
+	ENCODE_FIELD( contract.currency);
+
+	ENCODE_FIELD( contract.localSymbol); // srv v2 and above
+
+	// Send combo legs for BAG requests (srv v8 and above)
+	if( Compare(contract.secType, "BAG") == 0)
+	{
+		const Contract::ComboLegList* const comboLegs = contract.comboLegs.get();
+		const int comboLegsCount = comboLegs ? comboLegs->size() : 0;
+		ENCODE_FIELD( comboLegsCount);
+		if( comboLegsCount > 0) {
+			for( int i = 0; i < comboLegsCount; ++i) {
+				const ComboLeg* comboLeg = ((*comboLegs)[i]).get();
+				assert( comboLeg);
+				ENCODE_FIELD( comboLeg->conId);
+				ENCODE_FIELD( comboLeg->ratio);
+				ENCODE_FIELD( comboLeg->action);
+				ENCODE_FIELD( comboLeg->exchange);
+			}
+		}
+	}
+
+	if( m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) {
+		if( contract.underComp) {
+			const UnderComp& underComp = *contract.underComp;
+			ENCODE_FIELD( true);
+			ENCODE_FIELD( underComp.conId);
+			ENCODE_FIELD( underComp.delta);
+			ENCODE_FIELD( underComp.price);
+		}
+		else {
+			ENCODE_FIELD( false);
+		}
+	}
+
+	ENCODE_FIELD( genericTicks); // srv v31 and above
+	ENCODE_FIELD( snapshot); // srv v35 and above
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::cancelMktData(TickerId tickerId)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 2;
+
+	// send cancel mkt data msg
+	ENCODE_FIELD( CANCEL_MKT_DATA);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::reqMktDepth( TickerId tickerId, const Contract &contract, int numRows)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	// This feature is only available for versions of TWS >=6
+	//if( m_serverVersion < 6) {
+	//	m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg());
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 3;
+
+	// send req mkt data msg
+	ENCODE_FIELD( REQ_MKT_DEPTH);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	// send contract fields
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier); // srv v15 and above
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol);
+	ENCODE_FIELD( numRows); // srv v19 and above
+
+	bufferedSend( msg.str());
+}
+
+
+void EClientSocketBase::cancelMktDepth( TickerId tickerId)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	// This feature is only available for versions of TWS >=6
+	//if( m_serverVersion < 6) {
+	//	m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg());
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	// send cancel mkt data msg
+	ENCODE_FIELD( CANCEL_MKT_DEPTH);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::reqHistoricalData( TickerId tickerId, const Contract &contract,
+									   const IBString &endDateTime, const IBString &durationStr,
+									   const IBString & barSizeSetting, const IBString &whatToShow,
+									   int useRTH, int formatDate)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < 16) {
+	//	m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg());
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 4;
+
+	ENCODE_FIELD( REQ_HISTORICAL_DATA);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	// send contract fields
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier);
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.primaryExchange);
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol);
+	ENCODE_FIELD( contract.includeExpired); // srv v31 and above
+
+	ENCODE_FIELD( endDateTime); // srv v20 and above
+	ENCODE_FIELD( barSizeSetting); // srv v20 and above
+
+	ENCODE_FIELD( durationStr);
+	ENCODE_FIELD( useRTH);
+	ENCODE_FIELD( whatToShow);
+	ENCODE_FIELD( formatDate); // srv v16 and above
+
+	// Send combo legs for BAG requests
+	if( Compare(contract.secType, "BAG") == 0)
+	{
+		const Contract::ComboLegList* const comboLegs = contract.comboLegs.get();
+		const int comboLegsCount = comboLegs ? comboLegs->size() : 0;
+		ENCODE_FIELD( comboLegsCount);
+		if( comboLegsCount > 0) {
+			for( int i = 0; i < comboLegsCount; ++i) {
+				const ComboLeg* comboLeg = ((*comboLegs)[i]).get();
+				assert( comboLeg);
+				ENCODE_FIELD( comboLeg->conId);
+				ENCODE_FIELD( comboLeg->ratio);
+				ENCODE_FIELD( comboLeg->action);
+				ENCODE_FIELD( comboLeg->exchange);
+			}
+		}
+	}
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::cancelHistoricalData(TickerId tickerId)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < 24) {
+	//	m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support historical data query cancellation.");
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( CANCEL_HISTORICAL_DATA);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::reqRealTimeBars(TickerId tickerId, const Contract &contract,
+									int barSize, const IBString &whatToShow, bool useRTH)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) {
+	//	m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support real time bars.");
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( REQ_REAL_TIME_BARS);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	// send contract fields
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier);
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.primaryExchange);
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol);
+	ENCODE_FIELD( barSize);
+	ENCODE_FIELD( whatToShow);
+	ENCODE_FIELD( useRTH);
+
+	bufferedSend( msg.str());
+}
+
+
+void EClientSocketBase::cancelRealTimeBars(TickerId tickerId)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) {
+	//	m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support realtime bar data query cancellation.");
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( CANCEL_REAL_TIME_BARS);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	bufferedSend( msg.str());
+}
+
+
+void EClientSocketBase::reqScannerParameters()
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < 24) {
+	//	m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support API scanner subscription.");
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( REQ_SCANNER_PARAMETERS);
+	ENCODE_FIELD( VERSION);
+
+	bufferedSend( msg.str());
+}
+
+
+void EClientSocketBase::reqScannerSubscription(int tickerId,
+	const ScannerSubscription& subscription)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < 24) {
+	//	m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support API scanner subscription.");
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 3;
+
+	ENCODE_FIELD( REQ_SCANNER_SUBSCRIPTION);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+	ENCODE_FIELD_MAX( subscription.numberOfRows);
+	ENCODE_FIELD( subscription.instrument);
+	ENCODE_FIELD( subscription.locationCode);
+	ENCODE_FIELD( subscription.scanCode);
+	ENCODE_FIELD_MAX( subscription.abovePrice);
+	ENCODE_FIELD_MAX( subscription.belowPrice);
+	ENCODE_FIELD_MAX( subscription.aboveVolume);
+	ENCODE_FIELD_MAX( subscription.marketCapAbove);
+	ENCODE_FIELD_MAX( subscription.marketCapBelow);
+	ENCODE_FIELD( subscription.moodyRatingAbove);
+	ENCODE_FIELD( subscription.moodyRatingBelow);
+	ENCODE_FIELD( subscription.spRatingAbove);
+	ENCODE_FIELD( subscription.spRatingBelow);
+	ENCODE_FIELD( subscription.maturityDateAbove);
+	ENCODE_FIELD( subscription.maturityDateBelow);
+	ENCODE_FIELD_MAX( subscription.couponRateAbove);
+	ENCODE_FIELD_MAX( subscription.couponRateBelow);
+	ENCODE_FIELD_MAX( subscription.excludeConvertible);
+	ENCODE_FIELD_MAX( subscription.averageOptionVolumeAbove); // srv v25 and above
+	ENCODE_FIELD( subscription.scannerSettingPairs); // srv v25 and above
+	ENCODE_FIELD( subscription.stockTypeFilter); // srv v27 and above
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::cancelScannerSubscription(int tickerId)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( tickerId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < 24) {
+	//	m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support API scanner subscription.");
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( CANCEL_SCANNER_SUBSCRIPTION);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( tickerId);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::reqFundamentalData(TickerId reqId, const Contract& contract,
+									   const IBString& reportType)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( reqId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) {
+		m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+			"  It does not support fundamental data requests.");
+		return;
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( REQ_FUNDAMENTAL_DATA);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( reqId);
+
+	// send contract fields
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.primaryExchange);
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol);
+
+	ENCODE_FIELD( reportType);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::cancelFundamentalData( TickerId reqId)
+{
+		// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( reqId, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) {
+		m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+			"  It does not support fundamental data requests.");
+		return;
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( CANCEL_FUNDAMENTAL_DATA);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( reqId);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::calculateImpliedVolatility(TickerId reqId, const Contract &contract, double optionPrice, double underPrice) {
+
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT) {
+		m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+			"  It does not support calculate implied volatility requests.");
+		return;
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( REQ_CALC_IMPLIED_VOLAT);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( reqId);
+
+	// send contract fields
+	ENCODE_FIELD( contract.conId);
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier);
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.primaryExchange);
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol);
+
+	ENCODE_FIELD( optionPrice);
+	ENCODE_FIELD( underPrice);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::cancelCalculateImpliedVolatility(TickerId reqId) {
+
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT) {
+		m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+			"  It does not support calculate implied volatility cancellation.");
+		return;
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( CANCEL_CALC_IMPLIED_VOLAT);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( reqId);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::calculateOptionPrice(TickerId reqId, const Contract &contract, double volatility, double underPrice) {
+
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_OPTION_PRICE) {
+		m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+			"  It does not support calculate option price requests.");
+		return;
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( REQ_CALC_OPTION_PRICE);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( reqId);
+
+	// send contract fields
+	ENCODE_FIELD( contract.conId);
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier);
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.primaryExchange);
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol);
+
+	ENCODE_FIELD( volatility);
+	ENCODE_FIELD( underPrice);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::cancelCalculateOptionPrice(TickerId reqId) {
+
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE) {
+		m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+			"  It does not support calculate option price cancellation.");
+		return;
+	}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	ENCODE_FIELD( CANCEL_CALC_OPTION_PRICE);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( reqId);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::reqContractDetails( int reqId, const Contract& contract)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	// This feature is only available for versions of TWS >=4
+	//if( m_serverVersion < 4) {
+	//	m_pEWrapper->error( NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg());
+	//	return;
+	//}
+	if (m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) {
+		if( !IsEmpty(contract.secIdType) || !IsEmpty(contract.secId)) {
+			m_pEWrapper->error( reqId, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+     			"  It does not support secIdType and secId parameters.");
+     		return;
+     	}
+    }
+        
+	std::ostringstream msg;
+
+	const int VERSION = 6;
+
+	// send req mkt data msg
+	ENCODE_FIELD( REQ_CONTRACT_DATA);
+	ENCODE_FIELD( VERSION);
+
+	if( m_serverVersion >= MIN_SERVER_VER_CONTRACT_DATA_CHAIN) {
+		ENCODE_FIELD( reqId);
+	}
+
+	// send contract fields
+	ENCODE_FIELD( contract.conId); // srv v37 and above
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier); // srv v15 and above
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol);
+	ENCODE_FIELD( contract.includeExpired); // srv v31 and above
+
+	if( m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE){
+		ENCODE_FIELD( contract.secIdType);
+		ENCODE_FIELD( contract.secId);
+	}
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::reqCurrentTime()
+{
+    // not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( NO_VALID_ID, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	// This feature is only available for versions of TWS >= 33
+	//if( m_serverVersion < 33) {
+	//	m_pEWrapper->error(NO_VALID_ID, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//		"  It does not support current time requests.");
+	//	return;
+	//}
+
+	std::ostringstream msg;
+
+	const int VERSION = 1;
+
+	// send current time req
+	ENCODE_FIELD( REQ_CURRENT_TIME);
+	ENCODE_FIELD( VERSION);
+
+	bufferedSend( msg.str());
+}
+
+void EClientSocketBase::placeOrder( OrderId id, const Contract &contract, const Order &order)
+{
+	// not connected?
+	if( !m_connected) {
+		m_pEWrapper->error( id, NOT_CONNECTED.code(), NOT_CONNECTED.msg());
+		return;
+	}
+
+	// Not needed anymore validation
+	//if( m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS) {
+	//	if( order.scaleNumComponents != UNSET_INTEGER ||
+	//		order.scaleComponentSize != UNSET_INTEGER ||
+	//		order.scalePriceIncrement != UNSET_DOUBLE) {
+	//		m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//			"  It does not support Scale orders.");
+	//		return;
+	//	}
+	//}
+	//
+	//if( m_serverVersion < MIN_SERVER_VER_SSHORT_COMBO_LEGS) {
+	//	if( contract.comboLegs && !contract.comboLegs->empty()) {
+	//		typedef Contract::ComboLegList ComboLegList;
+	//		const ComboLegList& comboLegs = *contract.comboLegs;
+	//		ComboLegList::const_iterator iter = comboLegs.begin();
+	//		const ComboLegList::const_iterator iterEnd = comboLegs.end();
+	//		for( ; iter != iterEnd; ++iter) {
+	//			const ComboLeg* comboLeg = *iter;
+	//			assert( comboLeg);
+	//			if( comboLeg->shortSaleSlot != 0 ||
+	//				!comboLeg->designatedLocation.IsEmpty()) {
+	//				m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//					"  It does not support SSHORT flag for combo legs.");
+	//				return;
+	//			}
+	//		}
+	//	}
+	//}
+	//
+	//if( m_serverVersion < MIN_SERVER_VER_WHAT_IF_ORDERS) {
+	//	if( order.whatIf) {
+	//		m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+	//			"  It does not support what-if orders.");
+	//		return;
+	//	}
+	//}
+
+	if( m_serverVersion < MIN_SERVER_VER_UNDER_COMP) {
+		if( contract.underComp) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support delta-neutral orders.");
+			return;
+		}
+	}
+
+	if( m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS2) {
+		if( order.scaleSubsLevelSize != UNSET_INTEGER) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support Subsequent Level Size for Scale orders.");
+			return;
+		}
+	}
+
+	if( m_serverVersion < MIN_SERVER_VER_ALGO_ORDERS) {
+
+		if( !IsEmpty(order.algoStrategy)) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support algo orders.");
+			return;
+		}
+	}
+
+	if( m_serverVersion < MIN_SERVER_VER_NOT_HELD) {
+		if (order.notHeld) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support notHeld parameter.");
+			return;
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) {
+		if( !IsEmpty(contract.secIdType) || !IsEmpty(contract.secId)) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+     			"  It does not support secIdType and secId parameters.");
+			return;
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_PLACE_ORDER_CONID) {
+		if( contract.conId > 0) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+     			"  It does not support conId parameter.");
+			return;
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_SSHORTX) {
+		if( order.exemptCode != -1) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support exemptCode parameter.");
+			return;
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_SSHORTX) {
+		const Contract::ComboLegList* const comboLegs = contract.comboLegs.get();
+		const int comboLegsCount = comboLegs ? comboLegs->size() : 0;
+		for( int i = 0; i < comboLegsCount; ++i) {
+			const ComboLeg* comboLeg = ((*comboLegs)[i]).get();
+			assert( comboLeg);
+			if( comboLeg->exemptCode != -1 ){
+				m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+					"  It does not support exemptCode parameter.");
+				return;
+			}
+		}
+	}
+
+	if( m_serverVersion < MIN_SERVER_VER_HEDGE_ORDERS) {
+		if( !IsEmpty(order.hedgeType)) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+     			"  It does not support hedge orders.");
+			return;
+		}
+	}
+
+	if( m_serverVersion < MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) {
+		if (order.optOutSmartRouting) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support optOutSmartRouting parameter.");
+			return;
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_DELTA_NEUTRAL_CONID) {
+		if (order.deltaNeutralConId > 0 
+				|| !IsEmpty(order.deltaNeutralSettlingFirm)
+				|| !IsEmpty(order.deltaNeutralClearingAccount)
+				|| !IsEmpty(order.deltaNeutralClearingIntent)
+				) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+				"  It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent.");
+			return;
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS3) {
+		if (order.scalePriceIncrement > 0 && order.scalePriceIncrement != UNSET_DOUBLE) {
+			if (order.scalePriceAdjustValue != UNSET_DOUBLE 
+				|| order.scalePriceAdjustInterval != UNSET_INTEGER 
+				|| order.scaleProfitOffset != UNSET_DOUBLE 
+				|| order.scaleAutoReset 
+				|| order.scaleInitPosition != UNSET_INTEGER 
+				|| order.scaleInitFillQty != UNSET_INTEGER 
+				|| order.scaleRandomPercent) {
+				m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+						"  It does not support Scale order parameters: PriceAdjustValue, PriceAdjustInterval, " +
+						"ProfitOffset, AutoReset, InitPosition, InitFillQty and RandomPercent");
+				return;
+			}
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && Compare(contract.secType, "BAG") == 0) {
+		const Order::OrderComboLegList* const orderComboLegs = order.orderComboLegs.get();
+		const int orderComboLegsCount = orderComboLegs ? orderComboLegs->size() : 0;
+		for( int i = 0; i < orderComboLegsCount; ++i) {
+			const OrderComboLeg* orderComboLeg = ((*orderComboLegs)[i]).get();
+			assert( orderComboLeg);
+			if( orderComboLeg->price != UNSET_DOUBLE) {
+				m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+					"  It does not support per-leg prices for order combo legs.");
+				return;
+			}
+		}
+	}
+
+	if (m_serverVersion < MIN_SERVER_VER_TRAILING_PERCENT) {
+		if (order.trailingPercent != UNSET_DOUBLE) {
+			m_pEWrapper->error( id, UPDATE_TWS.code(), UPDATE_TWS.msg() +
+					"  It does not support trailing percent parameter");
+			return;
+		}
+	}
+
+	std::ostringstream msg;
+
+	int VERSION = (m_serverVersion < MIN_SERVER_VER_NOT_HELD) ? 27 : 38;
+
+	// send place order msg
+	ENCODE_FIELD( PLACE_ORDER);
+	ENCODE_FIELD( VERSION);
+	ENCODE_FIELD( id);
+
+	// send contract fields
+	if( m_serverVersion >= MIN_SERVER_VER_PLACE_ORDER_CONID) {
+		ENCODE_FIELD( contract.conId);
+	}
+	ENCODE_FIELD( contract.symbol);
+	ENCODE_FIELD( contract.secType);
+	ENCODE_FIELD( contract.expiry);
+	ENCODE_FIELD( contract.strike);
+	ENCODE_FIELD( contract.right);
+	ENCODE_FIELD( contract.multiplier); // srv v15 and above
+	ENCODE_FIELD( contract.exchange);
+	ENCODE_FIELD( contract.primaryExchange); // srv v14 and above
+	ENCODE_FIELD( contract.currency);
+	ENCODE_FIELD( contract.localSymbol); // srv v2 and above
+
+	if( m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE){
+		ENCODE_FIELD( contract.secIdType);
+		ENCODE_FIELD( contract.secId);
+	}
+
+	// send main order fields
+	ENCODE_FIELD( order.action);
+	ENCODE_FIELD( order.totalQuantity);
+	ENCODE_FIELD( order.orderType);
+	if( m_serverVersion < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE) {
+		ENCODE_FIELD( order.lmtPrice == UNSET_DOUBLE ? 0 : order.lmtPrice);
+	}
+	else {
+		ENCODE_FIELD_MAX( order.lmtPrice);
+	}
+	if( m_serverVersion < MIN_SERVER_VER_TRAILING_PERCENT) {
+		ENCODE_FIELD( order.auxPrice == UNSET_DOUBLE ? 0 : order.auxPrice);
+	}
+	else {
+		ENCODE_FIELD_MAX( order.auxPrice);
+	}
+
+	// send extended order fields
+	ENCODE_FIELD( order.tif);
+	ENCODE_FIELD( order.ocaGroup);
+	ENCODE_FIELD( order.account);
+	ENCODE_FIELD( order.openClose);
+	ENCODE_FIELD( order.origin);
+	ENCODE_FIELD( order.orderRef);
+	ENCODE_FIELD( order.transmit);
+	ENCODE_FIELD( order.parentId); // srv v4 and above
+
+	ENCODE_FIELD( order.blockOrder); // srv v5 and above
+	ENCODE_FIELD( order.sweepToFill); // srv v5 and above
+	ENCODE_FIELD( order.displaySize); // srv v5 and above
+	ENCODE_FIELD( order.triggerMethod); // srv v5 and above
+
+	//if( m_serverVersion < 38) {
+	// will never happen
+	//	ENCODE_FIELD(/* order.ignoreRth */ false);
+	//}
+	//else {
+		ENCODE_FIELD( order.outsideRth); // srv v5 and above
+	//}
+
+	ENCODE_FIELD( order.hidden); // srv v7 and above
+
+	// Send combo legs for BAG requests (srv v8 and above)
+	if( Compare(contract.secType, "BAG") == 0)
+	{
+		const Contract::ComboLegList* const comboLegs = contract.comboLegs.get();
+		const int comboLegsCount = comboLegs ? comboLegs->size() : 0;
+		ENCODE_FIELD( comboLegsCount);
+		if( comboLegsCount > 0) {
+			for( int i = 0; i < comboLegsCount; ++i) {
+				const ComboLeg* comboLeg = ((*comboLegs)[i]).get();
+				assert( comboLeg);
+				ENCODE_FIELD( comboLeg->conId);
+				ENCODE_FIELD( comboLeg->ratio);
+				ENCODE_FIELD( comboLeg->action);
+				ENCODE_FIELD( comboLeg->exchange);
+				ENCODE_FIELD( comboLeg->openClose);
+
+				ENCODE_FIELD( comboLeg->shortSaleSlot); // srv v35 and above
+				ENCODE_FIELD( comboLeg->designatedLocation); // srv v35 and above
+				if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { 
+					ENCODE_FIELD( comboLeg->exemptCode);
+				}
+			}
+		}
+	}
+
+	// Send order combo legs for BAG requests
+	if( m_serverVersion >= MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && Compare(contract.secType, "BAG") == 0)
+	{
+		const Order::OrderComboLegList* const orderComboLegs = order.orderComboLegs.get();
+		const int orderComboLegsCount = orderComboLegs ? orderComboLegs->size() : 0;
+		ENCODE_FIELD( orderComboLegsCount);
+		if( orderComboLegsCount > 0) {
+			for( int i = 0; i < orderComboLegsCount; ++i) {
+				const OrderComboLeg* orderComboLeg = ((*orderComboLegs)[i]).get();
+				assert( orderComboLeg);
+				ENCODE_FIELD_MAX( orderComboLeg->price);
+			}
+		}
+	}	
+
+	if( m_serverVersion >= MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS && Compare(contract.secType, "BAG") == 0) {
+		const TagValueList* const smartComboRoutingParams = order.smartComboRoutingParams.get();
+		const int smartComboRoutingParamsCount = smartComboRoutingParams ? smartComboRoutingParams->size() : 0;
+		ENCODE_FIELD( smartComboRoutingParamsCount);
+		if( smartComboRoutingParamsCount > 0) {
+			for( int i = 0; i < smartComboRoutingParamsCount; ++i) {
+				const TagValue* tagValue = ((*smartComboRoutingParams)[i]).get();
+				ENCODE_FIELD( tagValue->tag);
+				ENCODE_FIELD( tagValue->value);
+			}
+		}
+	}
+
+	/////////////////////////////////////////////////////////////////////////////
+	// Send the shares allocation.
+	//
+	// This specifies the number of order shares allocated to each Financial
+	// Advisor managed account. The format of the allocation string is as
+	// follows:
+	//			<account_code1>/<number_shares1>,<account_code2>/<number_shares2>,...N
+	// E.g.
+	//		To allocate 20 shares of a 100 share order to account 'U101' and the
+	//      residual 80 to account 'U203' enter the following share allocation string:
+	//          U101/20,U203/80
+	/////////////////////////////////////////////////////////////////////////////
+	{
+		// send deprecated sharesAllocation field
+		ENCODE_FIELD( ""); // srv v9 and above
+	}
+
+	ENCODE_FIELD( order.discretionaryAmt); // srv v10 and above
+	ENCODE_FIELD( order.goodAfterTime); // srv v11 and above
+	ENCODE_FIELD( order.goodTillDate); // srv v12 and above
+
+	ENCODE_FIELD( order.faGroup); // srv v13 and above
+	ENCODE_FIELD( order.faMethod); // srv v13 and above
+	ENCODE_FIELD( order.faPercentage); // srv v13 and above
+	ENCODE_FIELD( order.faProfile); // srv v13 and above
+
+	// institutional short saleslot data (srv v18 and above)
+	ENCODE_FIELD( order.shortSaleSlot);      // 0 for retail, 1 or 2 for institutions
+	ENCODE_FIELD( order.designatedLocation); // populate only when shortSaleSlot = 2.
+	if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { 
+		ENCODE_FIELD( order.exemptCode);
+	}
+
+	// not needed anymore
+	//bool isVolOrder = (order.orderType.CompareNoCase("VOL") == 0);
+
+	// srv v19 and above fields
+	ENCODE_FIELD( order.ocaType);
+	//if( m_serverVersion < 38) {
+	// will never happen
+	//	send( /* order.rthOnly */ false);
+	//}
+	ENCODE_FIELD( order.rule80A);
+	ENCODE_FIELD( order.settlingFirm);
+	ENCODE_FIELD( order.allOrNone);
+	ENCODE_FIELD_MAX( order.minQty);
+	ENCODE_FIELD_MAX( order.percentOffset);
+	ENCODE_FIELD( order.eTradeOnly);
+	ENCODE_FIELD( order.firmQuoteOnly);
+	ENCODE_FIELD_MAX( order.nbboPriceCap);
+	ENCODE_FIELD( order.auctionStrategy); // AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT
+	ENCODE_FIELD_MAX( order.startingPrice);
+	ENCODE_FIELD_MAX( order.stockRefPrice);
+	ENCODE_FIELD_MAX( order.delta);
+	// Volatility orders had specific watermark price attribs in server version 26
+	//double lower = (m_serverVersion == 26 && isVolOrder) ? DBL_MAX : order.stockRangeLower;
+	//double upper = (m_serverVersion == 26 && isVolOrder) ? DBL_MAX : order.stockRangeUpper;
+	ENCODE_FIELD_MAX( order.stockRangeLower);
+	ENCODE_FIELD_MAX( order.stockRangeUpper);
+
+	ENCODE_FIELD( order.overridePercentageConstraints); // srv v22 and above
+
+	// Volatility orders (srv v26 and above)
+	ENCODE_FIELD_MAX( order.volatility);
+	ENCODE_FIELD_MAX( order.volatilityType);
+	// will never happen
+	//if( m_serverVersion < 28) {
+	//	send( order.deltaNeutralOrderType.CompareNoCase("MKT") == 0);
+	//}
+	//else {
+		ENCODE_FIELD( order.deltaNeutralOrderType); // srv v28 and above
+		ENCODE_FIELD_MAX( order.deltaNeutralAuxPrice); // srv v28 and above
+
+		if (m_serverVersion >= MIN_SERVER_VER_DELTA_NEUTRAL_CONID && !IsEmpty(order.deltaNeutralOrderType)){
+			ENCODE_FIELD( order.deltaNeutralConId);
+			ENCODE_FIELD( order.deltaNeutralSettlingFirm);
+			ENCODE_FIELD( order.deltaNeutralClearingAccount);
+			ENCODE_FIELD( order.deltaNeutralClearingIntent);
+		}
+
+	//}
+	ENCODE_FIELD( order.continuousUpdate);
+	//if( m_serverVersion == 26) {
+	//	// Volatility orders had specific watermark price attribs in server version 26
+	//	double lower = (isVolOrder ? order.stockRangeLower : DBL_MAX);
+	//	double upper = (isVolOrder ? order.stockRangeUpper : DBL_MAX);
+	//	ENCODE_FIELD_MAX( lower);
+	//	ENCODE_FIELD_MAX( upper);
+	//}
+	ENCODE_FIELD_MAX( order.referencePriceType);
+
+	ENCODE_FIELD_MAX( order.trailStopPrice); // srv v30 and above
+
+	if( m_serverVersion >= MIN_SERVER_VER_TRAILING_PERCENT) {
+		ENCODE_FIELD_MAX( order.trailingPercent);
+	}
+
+	// SCALE orders
+	if( m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS2) {
+		ENCODE_FIELD_MAX( order.scaleInitLevelSize);
+		ENCODE_FIELD_MAX( order.scaleSubsLevelSize);
+	}
+	else {
+		// srv v35 and above)
+		ENCODE_FIELD( ""); // for not supported scaleNumComponents
+		ENCODE_FIELD_MAX( order.scaleInitLevelSize); // for scaleComponentSize
+	}
+
+	ENCODE_FIELD_MAX( order.scalePriceIncrement);
+
+	if( m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS3 
+		&& order.scalePriceIncrement > 0.0 && order.scalePriceIncrement != UNSET_DOUBLE) {
+		ENCODE_FIELD_MAX( order.scalePriceAdjustValue);
+		ENCODE_FIELD_MAX( order.scalePriceAdjustInterval);
+		ENCODE_FIELD_MAX( order.scaleProfitOffset);
+		ENCODE_FIELD( order.scaleAutoReset);
+		ENCODE_FIELD_MAX( order.scaleInitPosition);
+		ENCODE_FIELD_MAX( order.scaleInitFillQty);
+		ENCODE_FIELD( order.scaleRandomPercent);
+	}
+
+	// HEDGE orders
+	if( m_serverVersion >= MIN_SERVER_VER_HEDGE_ORDERS) {
+		ENCODE_FIELD( order.hedgeType);
+		if ( !IsEmpty(order.hedgeType)) {
+			ENCODE_FIELD( order.hedgeParam);
+		}
+	}
+
+	if( m_serverVersion >= MIN_SERVER_VER_OPT_OUT_SMART_ROUTING){
+		ENCODE_FIELD( order.optOutSmartRouting);
+	}
+
+	if( m_serverVersion >= MIN_SERVER_VER_PTA_ORDERS) {
+		ENCODE_FIELD( order.clearingAccount);
+		ENCODE_FIELD( order.clearingIntent);
+	}
+
+	if( m_serverVersion >= MIN_SERVER_VER_NOT_HELD){
+		ENCODE_FIELD( order.notHeld);
+	}
+
+	if( m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) {
+		if( contract.underComp) {
+			const UnderComp& underComp = *contract.underComp;
+			ENCODE_FIELD( true);
+			ENCODE_FIELD( underComp.conId);
+			ENCODE_FIELD( underComp.delta);
+			ENCODE_FIELD( underComp.price);
+		}
+		else {
+			ENCODE_FIELD( false);