vnpy/vn.ib/ibapi/windows/client/EDecoder.cpp
2016-11-12 00:42:37 +08:00

2077 lines
54 KiB
C++

/* 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 <assert.h>
#include <string>
#include "EWrapper.h"
#include "Order.h"
#include "Contract.h"
#include "OrderState.h"
#include "Execution.h"
#include "CommissionReport.h"
#include "TwsSocketClientErrors.h"
#include "EDecoder.h"
#include "EClientMsgSink.h"
#include <string.h>
EDecoder::EDecoder(int serverVersion, EWrapper *callback, EClientMsgSink *clientMsgSink) {
m_pEWrapper = callback;
m_serverVersion = serverVersion;
m_pClientMsgSink = clientMsgSink;
}
const char* EDecoder::processTickPriceMsg(const char* ptr, const char* endPtr) {
int version;
int tickerId;
int tickTypeInt;
double price;
int size;
int canAutoExecute;
DECODE_FIELD( version);
DECODE_FIELD( tickerId);
DECODE_FIELD( tickTypeInt);
DECODE_FIELD( price);
DECODE_FIELD( size); // ver 2 field
DECODE_FIELD( canAutoExecute); // ver 3 field
m_pEWrapper->tickPrice( tickerId, (TickType)tickTypeInt, price, canAutoExecute);
// process ver 2 fields
{
TickType sizeTickType = NOT_SET;
switch( (TickType)tickTypeInt) {
case BID:
sizeTickType = BID_SIZE;
break;
case ASK:
sizeTickType = ASK_SIZE;
break;
case LAST:
sizeTickType = LAST_SIZE;
break;
default:
break;
}
if( sizeTickType != NOT_SET)
m_pEWrapper->tickSize( tickerId, sizeTickType, size);
}
return ptr;
}
const char* EDecoder::processTickSizeMsg(const char* ptr, const char* endPtr) {
int version;
int tickerId;
int tickTypeInt;
int size;
DECODE_FIELD( version);
DECODE_FIELD( tickerId);
DECODE_FIELD( tickTypeInt);
DECODE_FIELD( size);
m_pEWrapper->tickSize( tickerId, (TickType)tickTypeInt, size);
return ptr;
}
const char* EDecoder::processTickOptionComputationMsg(const char* ptr, const char* endPtr) {
int version;
int tickerId;
int tickTypeInt;
double impliedVol;
double delta;
double optPrice = DBL_MAX;
double pvDividend = DBL_MAX;
double gamma = DBL_MAX;
double vega = DBL_MAX;
double theta = DBL_MAX;
double undPrice = DBL_MAX;
DECODE_FIELD( version);
DECODE_FIELD( tickerId);
DECODE_FIELD( tickTypeInt);
DECODE_FIELD( impliedVol);
DECODE_FIELD( delta);
if( impliedVol < 0) { // -1 is the "not computed" indicator
impliedVol = DBL_MAX;
}
if( delta > 1 || delta < -1) { // -2 is the "not computed" indicator
delta = DBL_MAX;
}
if( version >= 6 || tickTypeInt == MODEL_OPTION) { // introduced in version == 5
DECODE_FIELD( optPrice);
DECODE_FIELD( pvDividend);
if( optPrice < 0) { // -1 is the "not computed" indicator
optPrice = DBL_MAX;
}
if( pvDividend < 0) { // -1 is the "not computed" indicator
pvDividend = DBL_MAX;
}
}
if( version >= 6) {
DECODE_FIELD( gamma);
DECODE_FIELD( vega);
DECODE_FIELD( theta);
DECODE_FIELD( undPrice);
if( gamma > 1 || gamma < -1) { // -2 is the "not yet computed" indicator
gamma = DBL_MAX;
}
if( vega > 1 || vega < -1) { // -2 is the "not yet computed" indicator
vega = DBL_MAX;
}
if( theta > 1 || theta < -1) { // -2 is the "not yet computed" indicator
theta = DBL_MAX;
}
if( undPrice < 0) { // -1 is the "not computed" indicator
undPrice = DBL_MAX;
}
}
m_pEWrapper->tickOptionComputation( tickerId, (TickType)tickTypeInt,
impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice);
return ptr;
}
const char* EDecoder::processTickGenericMsg(const char* ptr, const char* endPtr) {
int version;
int tickerId;
int tickTypeInt;
double value;
DECODE_FIELD( version);
DECODE_FIELD( tickerId);
DECODE_FIELD( tickTypeInt);
DECODE_FIELD( value);
m_pEWrapper->tickGeneric( tickerId, (TickType)tickTypeInt, value);
return ptr;
}
const char* EDecoder::processTickStringMsg(const char* ptr, const char* endPtr) {
int version;
int tickerId;
int tickTypeInt;
std::string value;
DECODE_FIELD( version);
DECODE_FIELD( tickerId);
DECODE_FIELD( tickTypeInt);
DECODE_FIELD( value);
m_pEWrapper->tickString( tickerId, (TickType)tickTypeInt, value);
return ptr;
}
const char* EDecoder::processTickEfpMsg(const char* ptr, const char* endPtr) {
int version;
int tickerId;
int tickTypeInt;
double basisPoints;
std::string formattedBasisPoints;
double impliedFuturesPrice;
int holdDays;
std::string futureLastTradeDate;
double dividendImpact;
double dividendsToLastTradeDate;
DECODE_FIELD( version);
DECODE_FIELD( tickerId);
DECODE_FIELD( tickTypeInt);
DECODE_FIELD( basisPoints);
DECODE_FIELD( formattedBasisPoints);
DECODE_FIELD( impliedFuturesPrice);
DECODE_FIELD( holdDays);
DECODE_FIELD( futureLastTradeDate);
DECODE_FIELD( dividendImpact);
DECODE_FIELD( dividendsToLastTradeDate);
m_pEWrapper->tickEFP( tickerId, (TickType)tickTypeInt, basisPoints, formattedBasisPoints,
impliedFuturesPrice, holdDays, futureLastTradeDate, dividendImpact, dividendsToLastTradeDate);
return ptr;
}
const char* EDecoder::processOrderStatusMsg(const char* ptr, const char* endPtr) {
int version;
int orderId;
std::string status;
double filled;
double remaining;
double avgFillPrice;
int permId;
int parentId;
double lastFillPrice;
int clientId;
std::string whyHeld;
DECODE_FIELD( version);
DECODE_FIELD( orderId);
DECODE_FIELD( status);
if (m_serverVersion >= MIN_SERVER_VER_FRACTIONAL_POSITIONS)
{
DECODE_FIELD( filled);
}
else
{
int iFilled;
DECODE_FIELD(iFilled);
filled = iFilled;
}
if (m_serverVersion >= MIN_SERVER_VER_FRACTIONAL_POSITIONS)
{
DECODE_FIELD( remaining);
}
else
{
int iRemaining;
DECODE_FIELD(iRemaining);
remaining = iRemaining;
}
DECODE_FIELD( avgFillPrice);
DECODE_FIELD( permId); // ver 2 field
DECODE_FIELD( parentId); // ver 3 field
DECODE_FIELD( lastFillPrice); // ver 4 field
DECODE_FIELD( clientId); // ver 5 field
DECODE_FIELD( whyHeld); // ver 6 field
m_pEWrapper->orderStatus( orderId, status, filled, remaining,
avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld);
return ptr;
}
const char* EDecoder::processErrMsgMsg(const char* ptr, const char* endPtr) {
int version;
int id; // ver 2 field
int errorCode; // ver 2 field
std::string errorMsg;
DECODE_FIELD( version);
DECODE_FIELD( id);
DECODE_FIELD( errorCode);
DECODE_FIELD( errorMsg);
m_pEWrapper->error( id, errorCode, errorMsg);
return ptr;
}
const char* EDecoder::processOpenOrderMsg(const char* ptr, const char* endPtr) {
// read version
int version;
DECODE_FIELD( version);
// read order id
Order order;
DECODE_FIELD( order.orderId);
// read contract fields
Contract contract;
DECODE_FIELD( contract.conId); // ver 17 field
DECODE_FIELD( contract.symbol);
DECODE_FIELD( contract.secType);
DECODE_FIELD( contract.lastTradeDateOrContractMonth);
DECODE_FIELD( contract.strike);
DECODE_FIELD( contract.right);
if (version >= 32) {
DECODE_FIELD( contract.multiplier);
}
DECODE_FIELD( contract.exchange);
DECODE_FIELD( contract.currency);
DECODE_FIELD( contract.localSymbol); // ver 2 field
if (version >= 32) {
DECODE_FIELD( contract.tradingClass);
}
// read order fields
DECODE_FIELD( order.action);
if (m_serverVersion >= MIN_SERVER_VER_FRACTIONAL_POSITIONS)
{
DECODE_FIELD( order.totalQuantity);
}
else
{
long lTotalQuantity;
DECODE_FIELD(lTotalQuantity);
order.totalQuantity = lTotalQuantity;
}
DECODE_FIELD( order.orderType);
if (version < 29) {
DECODE_FIELD( order.lmtPrice);
}
else {
DECODE_FIELD_MAX( order.lmtPrice);
}
if (version < 30) {
DECODE_FIELD( order.auxPrice);
}
else {
DECODE_FIELD_MAX( order.auxPrice);
}
DECODE_FIELD( order.tif);
DECODE_FIELD( order.ocaGroup);
DECODE_FIELD( order.account);
DECODE_FIELD( order.openClose);
int orderOriginInt;
DECODE_FIELD( orderOriginInt);
order.origin = (Origin)orderOriginInt;
DECODE_FIELD( order.orderRef);
DECODE_FIELD( order.clientId); // ver 3 field
DECODE_FIELD( order.permId); // ver 4 field
//if( version < 18) {
// // will never happen
// /* order.ignoreRth = */ readBoolFromInt();
//}
DECODE_FIELD( order.outsideRth); // ver 18 field
DECODE_FIELD( order.hidden); // ver 4 field
DECODE_FIELD( order.discretionaryAmt); // ver 4 field
DECODE_FIELD( order.goodAfterTime); // ver 5 field
{
std::string sharesAllocation;
DECODE_FIELD( sharesAllocation); // deprecated ver 6 field
}
DECODE_FIELD( order.faGroup); // ver 7 field
DECODE_FIELD( order.faMethod); // ver 7 field
DECODE_FIELD( order.faPercentage); // ver 7 field
DECODE_FIELD( order.faProfile); // ver 7 field
if( m_serverVersion >= MIN_SERVER_VER_MODELS_SUPPORT ) {
DECODE_FIELD( order.modelCode);
}
DECODE_FIELD( order.goodTillDate); // ver 8 field
DECODE_FIELD( order.rule80A); // ver 9 field
DECODE_FIELD_MAX( order.percentOffset); // ver 9 field
DECODE_FIELD( order.settlingFirm); // ver 9 field
DECODE_FIELD( order.shortSaleSlot); // ver 9 field
DECODE_FIELD( order.designatedLocation); // ver 9 field
if( m_serverVersion == MIN_SERVER_VER_SSHORTX_OLD){
int exemptCode;
DECODE_FIELD( exemptCode);
}
else if( version >= 23){
DECODE_FIELD( order.exemptCode);
}
DECODE_FIELD( order.auctionStrategy); // ver 9 field
DECODE_FIELD_MAX( order.startingPrice); // ver 9 field
DECODE_FIELD_MAX( order.stockRefPrice); // ver 9 field
DECODE_FIELD_MAX( order.delta); // ver 9 field
DECODE_FIELD_MAX( order.stockRangeLower); // ver 9 field
DECODE_FIELD_MAX( order.stockRangeUpper); // ver 9 field
DECODE_FIELD( order.displaySize); // ver 9 field
//if( version < 18) {
// // will never happen
// /* order.rthOnly = */ readBoolFromInt();
//}
DECODE_FIELD( order.blockOrder); // ver 9 field
DECODE_FIELD( order.sweepToFill); // ver 9 field
DECODE_FIELD( order.allOrNone); // ver 9 field
DECODE_FIELD_MAX( order.minQty); // ver 9 field
DECODE_FIELD( order.ocaType); // ver 9 field
DECODE_FIELD( order.eTradeOnly); // ver 9 field
DECODE_FIELD( order.firmQuoteOnly); // ver 9 field
DECODE_FIELD_MAX( order.nbboPriceCap); // ver 9 field
DECODE_FIELD( order.parentId); // ver 10 field
DECODE_FIELD( order.triggerMethod); // ver 10 field
DECODE_FIELD_MAX( order.volatility); // ver 11 field
DECODE_FIELD( order.volatilityType); // ver 11 field
DECODE_FIELD( order.deltaNeutralOrderType); // ver 11 field (had a hack for ver 11)
DECODE_FIELD_MAX( order.deltaNeutralAuxPrice); // ver 12 field
if (version >= 27 && !order.deltaNeutralOrderType.empty()) {
DECODE_FIELD( order.deltaNeutralConId);
DECODE_FIELD( order.deltaNeutralSettlingFirm);
DECODE_FIELD( order.deltaNeutralClearingAccount);
DECODE_FIELD( order.deltaNeutralClearingIntent);
}
if (version >= 31 && !order.deltaNeutralOrderType.empty()) {
DECODE_FIELD( order.deltaNeutralOpenClose);
DECODE_FIELD( order.deltaNeutralShortSale);
DECODE_FIELD( order.deltaNeutralShortSaleSlot);
DECODE_FIELD( order.deltaNeutralDesignatedLocation);
}
DECODE_FIELD( order.continuousUpdate); // ver 11 field
// will never happen
//if( m_serverVersion == 26) {
// order.stockRangeLower = readDouble();
// order.stockRangeUpper = readDouble();
//}
DECODE_FIELD( order.referencePriceType); // ver 11 field
DECODE_FIELD_MAX( order.trailStopPrice); // ver 13 field
if (version >= 30) {
DECODE_FIELD_MAX( order.trailingPercent);
}
DECODE_FIELD_MAX( order.basisPoints); // ver 14 field
DECODE_FIELD_MAX( order.basisPointsType); // ver 14 field
DECODE_FIELD( contract.comboLegsDescrip); // ver 14 field
if (version >= 29) {
int comboLegsCount = 0;
DECODE_FIELD( comboLegsCount);
if (comboLegsCount > 0) {
Contract::ComboLegListSPtr comboLegs( new Contract::ComboLegList);
comboLegs->reserve( comboLegsCount);
for (int i = 0; i < comboLegsCount; ++i) {
ComboLegSPtr comboLeg( new ComboLeg());
DECODE_FIELD( comboLeg->conId);
DECODE_FIELD( comboLeg->ratio);
DECODE_FIELD( comboLeg->action);
DECODE_FIELD( comboLeg->exchange);
DECODE_FIELD( comboLeg->openClose);
DECODE_FIELD( comboLeg->shortSaleSlot);
DECODE_FIELD( comboLeg->designatedLocation);
DECODE_FIELD( comboLeg->exemptCode);
comboLegs->push_back( comboLeg);
}
contract.comboLegs = comboLegs;
}
int orderComboLegsCount = 0;
DECODE_FIELD( orderComboLegsCount);
if (orderComboLegsCount > 0) {
Order::OrderComboLegListSPtr orderComboLegs( new Order::OrderComboLegList);
orderComboLegs->reserve( orderComboLegsCount);
for (int i = 0; i < orderComboLegsCount; ++i) {
OrderComboLegSPtr orderComboLeg( new OrderComboLeg());
DECODE_FIELD_MAX( orderComboLeg->price);
orderComboLegs->push_back( orderComboLeg);
}
order.orderComboLegs = orderComboLegs;
}
}
if (version >= 26) {
int smartComboRoutingParamsCount = 0;
DECODE_FIELD( smartComboRoutingParamsCount);
if( smartComboRoutingParamsCount > 0) {
TagValueListSPtr smartComboRoutingParams( new TagValueList);
smartComboRoutingParams->reserve( smartComboRoutingParamsCount);
for( int i = 0; i < smartComboRoutingParamsCount; ++i) {
TagValueSPtr tagValue( new TagValue());
DECODE_FIELD( tagValue->tag);
DECODE_FIELD( tagValue->value);
smartComboRoutingParams->push_back( tagValue);
}
order.smartComboRoutingParams = smartComboRoutingParams;
}
}
if( version >= 20) {
DECODE_FIELD_MAX( order.scaleInitLevelSize);
DECODE_FIELD_MAX( order.scaleSubsLevelSize);
}
else {
// ver 15 fields
int notSuppScaleNumComponents = 0;
DECODE_FIELD_MAX( notSuppScaleNumComponents);
DECODE_FIELD_MAX( order.scaleInitLevelSize); // scaleComponectSize
}
DECODE_FIELD_MAX( order.scalePriceIncrement); // ver 15 field
if (version >= 28 && order.scalePriceIncrement > 0.0 && order.scalePriceIncrement != UNSET_DOUBLE) {
DECODE_FIELD_MAX( order.scalePriceAdjustValue);
DECODE_FIELD_MAX( order.scalePriceAdjustInterval);
DECODE_FIELD_MAX( order.scaleProfitOffset);
DECODE_FIELD( order.scaleAutoReset);
DECODE_FIELD_MAX( order.scaleInitPosition);
DECODE_FIELD_MAX( order.scaleInitFillQty);
DECODE_FIELD( order.scaleRandomPercent);
}
if( version >= 24) {
DECODE_FIELD( order.hedgeType);
if( !order.hedgeType.empty()) {
DECODE_FIELD( order.hedgeParam);
}
}
if( version >= 25) {
DECODE_FIELD( order.optOutSmartRouting);
}
DECODE_FIELD( order.clearingAccount); // ver 19 field
DECODE_FIELD( order.clearingIntent); // ver 19 field
if( version >= 22) {
DECODE_FIELD( order.notHeld);
}
UnderComp underComp;
if( version >= 20) {
bool underCompPresent = false;
DECODE_FIELD(underCompPresent);
if( underCompPresent){
DECODE_FIELD(underComp.conId);
DECODE_FIELD(underComp.delta);
DECODE_FIELD(underComp.price);
contract.underComp = &underComp;
}
}
if( version >= 21) {
DECODE_FIELD( order.algoStrategy);
if( !order.algoStrategy.empty()) {
int algoParamsCount = 0;
DECODE_FIELD( algoParamsCount);
if( algoParamsCount > 0) {
TagValueListSPtr algoParams( new TagValueList);
algoParams->reserve( algoParamsCount);
for( int i = 0; i < algoParamsCount; ++i) {
TagValueSPtr tagValue( new TagValue());
DECODE_FIELD( tagValue->tag);
DECODE_FIELD( tagValue->value);
algoParams->push_back( tagValue);
}
order.algoParams = algoParams;
}
}
}
if (version >= 33) {
DECODE_FIELD(order.solicited);
}
OrderState orderState;
DECODE_FIELD( order.whatIf); // ver 16 field
DECODE_FIELD( orderState.status); // ver 16 field
DECODE_FIELD( orderState.initMargin); // ver 16 field
DECODE_FIELD( orderState.maintMargin); // ver 16 field
DECODE_FIELD( orderState.equityWithLoan); // ver 16 field
DECODE_FIELD_MAX( orderState.commission); // ver 16 field
DECODE_FIELD_MAX( orderState.minCommission); // ver 16 field
DECODE_FIELD_MAX( orderState.maxCommission); // ver 16 field
DECODE_FIELD( orderState.commissionCurrency); // ver 16 field
DECODE_FIELD( orderState.warningText); // ver 16 field
if (version >= 34) {
DECODE_FIELD(order.randomizeSize);
DECODE_FIELD(order.randomizePrice);
}
if (m_serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK) {
if (order.orderType == "PEG BENCH") {
DECODE_FIELD(order.referenceContractId);
DECODE_FIELD(order.isPeggedChangeAmountDecrease);
DECODE_FIELD(order.peggedChangeAmount);
DECODE_FIELD(order.referenceChangeAmount);
DECODE_FIELD(order.referenceExchangeId);
}
int conditionsSize;
DECODE_FIELD(conditionsSize);
if (conditionsSize > 0) {
for (; conditionsSize; conditionsSize--) {
int conditionType;
DECODE_FIELD(conditionType);
ibapi::shared_ptr<OrderCondition> item = ibapi::shared_ptr<OrderCondition>(OrderCondition::create((OrderCondition::OrderConditionType)conditionType));
if (!(ptr = item->readExternal(ptr, endPtr)))
return 0;
order.conditions.push_back(item);
}
DECODE_FIELD(order.conditionsIgnoreRth);
DECODE_FIELD(order.conditionsCancelOrder);
}
DECODE_FIELD(order.adjustedOrderType);
DECODE_FIELD(order.triggerPrice);
DECODE_FIELD(order.trailStopPrice);
DECODE_FIELD(order.lmtPriceOffset);
DECODE_FIELD(order.adjustedStopPrice);
DECODE_FIELD(order.adjustedStopLimitPrice);
DECODE_FIELD(order.adjustedTrailingAmount);
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);
return ptr;
}
const char* EDecoder::processAcctValueMsg(const char* ptr, const char* endPtr) {
int version;
std::string key;
std::string val;
std::string cur;
std::string accountName;
DECODE_FIELD( version);
DECODE_FIELD( key);
DECODE_FIELD( val);
DECODE_FIELD( cur);
DECODE_FIELD( accountName); // ver 2 field
m_pEWrapper->updateAccountValue( key, val, cur, accountName);
return ptr;
}
const char* EDecoder::processPortfolioValueMsg(const char* ptr, const char* endPtr) {
// decode version
int version;
DECODE_FIELD( version);
// read contract fields
Contract contract;
DECODE_FIELD( contract.conId); // ver 6 field
DECODE_FIELD( contract.symbol);
DECODE_FIELD( contract.secType);
DECODE_FIELD( contract.lastTradeDateOrContractMonth);
DECODE_FIELD( contract.strike);
DECODE_FIELD( contract.right);
if( version >= 7) {
DECODE_FIELD( contract.multiplier);
DECODE_FIELD( contract.primaryExchange);
}
DECODE_FIELD( contract.currency);
DECODE_FIELD( contract.localSymbol); // ver 2 field
if (version >= 8) {
DECODE_FIELD( contract.tradingClass);
}
double position;
double marketPrice;
double marketValue;
double averageCost;
double unrealizedPNL;
double realizedPNL;
if (m_serverVersion >= MIN_SERVER_VER_FRACTIONAL_POSITIONS)
{
DECODE_FIELD( position);
}
else
{
int iPosition;
DECODE_FIELD(iPosition);
position = iPosition;
}
DECODE_FIELD( marketPrice);
DECODE_FIELD( marketValue);
DECODE_FIELD( averageCost); // ver 3 field
DECODE_FIELD( unrealizedPNL); // ver 3 field
DECODE_FIELD( realizedPNL); // ver 3 field
std::string accountName;
DECODE_FIELD( accountName); // ver 4 field
if( version == 6 && m_serverVersion == 39) {
DECODE_FIELD( contract.primaryExchange);
}
m_pEWrapper->updatePortfolio( contract,
position, marketPrice, marketValue, averageCost,
unrealizedPNL, realizedPNL, accountName);
return ptr;
}
const char* EDecoder::processAcctUpdateTimeMsg(const char* ptr, const char* endPtr) {
int version;
std::string accountTime;
DECODE_FIELD( version);
DECODE_FIELD( accountTime);
m_pEWrapper->updateAccountTime( accountTime);
return ptr;
}
const char* EDecoder::processNextValidIdMsg(const char* ptr, const char* endPtr) {
int version;
int orderId;
DECODE_FIELD( version);
DECODE_FIELD( orderId);
m_pEWrapper->nextValidId(orderId);
return ptr;
}
const char* EDecoder::processContractDataMsg(const char* ptr, const char* endPtr) {
int version;
DECODE_FIELD( version);
int reqId = -1;
if( version >= 3) {
DECODE_FIELD( reqId);
}
ContractDetails contract;
DECODE_FIELD( contract.summary.symbol);
DECODE_FIELD( contract.summary.secType);
DECODE_FIELD( contract.summary.lastTradeDateOrContractMonth);
DECODE_FIELD( contract.summary.strike);
DECODE_FIELD( contract.summary.right);
DECODE_FIELD( contract.summary.exchange);
DECODE_FIELD( contract.summary.currency);
DECODE_FIELD( contract.summary.localSymbol);
DECODE_FIELD( contract.marketName);
DECODE_FIELD( contract.summary.tradingClass);
DECODE_FIELD( contract.summary.conId);
DECODE_FIELD( contract.minTick);
DECODE_FIELD( contract.summary.multiplier);
DECODE_FIELD( contract.orderTypes);
DECODE_FIELD( contract.validExchanges);
DECODE_FIELD( contract.priceMagnifier); // ver 2 field
if( version >= 4) {
DECODE_FIELD( contract.underConId);
}
if( version >= 5) {
DECODE_FIELD( contract.longName);
DECODE_FIELD( contract.summary.primaryExchange);
}
if( version >= 6) {
DECODE_FIELD( contract.contractMonth);
DECODE_FIELD( contract.industry);
DECODE_FIELD( contract.category);
DECODE_FIELD( contract.subcategory);
DECODE_FIELD( contract.timeZoneId);
DECODE_FIELD( contract.tradingHours);
DECODE_FIELD( contract.liquidHours);
}
if( version >= 8) {
DECODE_FIELD( contract.evRule);
DECODE_FIELD( contract.evMultiplier);
}
if( version >= 7) {
int secIdListCount = 0;
DECODE_FIELD( secIdListCount);
if( secIdListCount > 0) {
TagValueListSPtr secIdList( new TagValueList);
secIdList->reserve( secIdListCount);
for( int i = 0; i < secIdListCount; ++i) {
TagValueSPtr tagValue( new TagValue());
DECODE_FIELD( tagValue->tag);
DECODE_FIELD( tagValue->value);
secIdList->push_back( tagValue);
}
contract.secIdList = secIdList;
}
}
m_pEWrapper->contractDetails( reqId, contract);
return ptr;
}
const char* EDecoder::processBondContractDataMsg(const char* ptr, const char* endPtr) {
int version;
DECODE_FIELD( version);
int reqId = -1;
if( version >= 3) {
DECODE_FIELD( reqId);
}
ContractDetails contract;
DECODE_FIELD( contract.summary.symbol);
DECODE_FIELD( contract.summary.secType);
DECODE_FIELD( contract.cusip);
DECODE_FIELD( contract.coupon);
DECODE_FIELD( contract.maturity);
DECODE_FIELD( contract.issueDate);
DECODE_FIELD( contract.ratings);
DECODE_FIELD( contract.bondType);
DECODE_FIELD( contract.couponType);
DECODE_FIELD( contract.convertible);
DECODE_FIELD( contract.callable);
DECODE_FIELD( contract.putable);
DECODE_FIELD( contract.descAppend);
DECODE_FIELD( contract.summary.exchange);
DECODE_FIELD( contract.summary.currency);
DECODE_FIELD( contract.marketName);
DECODE_FIELD( contract.summary.tradingClass);
DECODE_FIELD( contract.summary.conId);
DECODE_FIELD( contract.minTick);
DECODE_FIELD( contract.orderTypes);
DECODE_FIELD( contract.validExchanges);
DECODE_FIELD( contract.nextOptionDate); // ver 2 field
DECODE_FIELD( contract.nextOptionType); // ver 2 field
DECODE_FIELD( contract.nextOptionPartial); // ver 2 field
DECODE_FIELD( contract.notes); // ver 2 field
if( version >= 4) {
DECODE_FIELD( contract.longName);
}
if( version >= 6) {
DECODE_FIELD( contract.evRule);
DECODE_FIELD( contract.evMultiplier);
}
if( version >= 5) {
int secIdListCount = 0;
DECODE_FIELD( secIdListCount);
if( secIdListCount > 0) {
TagValueListSPtr secIdList( new TagValueList);
secIdList->reserve( secIdListCount);
for( int i = 0; i < secIdListCount; ++i) {
TagValueSPtr tagValue( new TagValue());
DECODE_FIELD( tagValue->tag);
DECODE_FIELD( tagValue->value);
secIdList->push_back( tagValue);
}
contract.secIdList = secIdList;
}
}
m_pEWrapper->bondContractDetails( reqId, contract);
return ptr;
}
const char* EDecoder::processExecutionDataMsg(const char* ptr, const char* endPtr) {
int version;
DECODE_FIELD( version);
int reqId = -1;
if( version >= 7) {
DECODE_FIELD(reqId);
}
int orderId;
DECODE_FIELD( orderId);
// decode contract fields
Contract contract;
DECODE_FIELD( contract.conId); // ver 5 field
DECODE_FIELD( contract.symbol);
DECODE_FIELD( contract.secType);
DECODE_FIELD( contract.lastTradeDateOrContractMonth);
DECODE_FIELD( contract.strike);
DECODE_FIELD( contract.right);
if( version >= 9) {
DECODE_FIELD( contract.multiplier);
}
DECODE_FIELD( contract.exchange);
DECODE_FIELD( contract.currency);
DECODE_FIELD( contract.localSymbol);
if (version >= 10) {
DECODE_FIELD( contract.tradingClass);
}
// decode execution fields
Execution exec;
exec.orderId = orderId;
DECODE_FIELD( exec.execId);
DECODE_FIELD( exec.time);
DECODE_FIELD( exec.acctNumber);
DECODE_FIELD( exec.exchange);
DECODE_FIELD( exec.side);
if (m_serverVersion >= MIN_SERVER_VER_FRACTIONAL_POSITIONS) {
DECODE_FIELD( exec.shares)
}
else {
int iShares;
DECODE_FIELD(iShares);
exec.shares = iShares;
}
DECODE_FIELD( exec.price);
DECODE_FIELD( exec.permId); // ver 2 field
DECODE_FIELD( exec.clientId); // ver 3 field
DECODE_FIELD( exec.liquidation); // ver 4 field
if( version >= 6) {
DECODE_FIELD( exec.cumQty);
DECODE_FIELD( exec.avgPrice);
}
if( version >= 8) {
DECODE_FIELD( exec.orderRef);
}
if( version >= 9) {
DECODE_FIELD( exec.evRule);
DECODE_FIELD( exec.evMultiplier);
}
if( m_serverVersion >= MIN_SERVER_VER_MODELS_SUPPORT) {
DECODE_FIELD( exec.modelCode);
}
m_pEWrapper->execDetails( reqId, contract, exec);
return ptr;
}
const char* EDecoder::processMarketDepthMsg(const char* ptr, const char* endPtr) {
int version;
int id;
int position;
int operation;
int side;
double price;
int size;
DECODE_FIELD( version);
DECODE_FIELD( id);
DECODE_FIELD( position);
DECODE_FIELD( operation);
DECODE_FIELD( side);
DECODE_FIELD( price);
DECODE_FIELD( size);
m_pEWrapper->updateMktDepth( id, position, operation, side, price, size);
return ptr;
}
const char* EDecoder::processMarketDepthL2Msg(const char* ptr, const char* endPtr) {
int version;
int id;
int position;
std::string marketMaker;
int operation;
int side;
double price;
int size;
DECODE_FIELD( version);
DECODE_FIELD( id);
DECODE_FIELD( position);
DECODE_FIELD( marketMaker);
DECODE_FIELD( operation);
DECODE_FIELD( side);
DECODE_FIELD( price);
DECODE_FIELD( size);
m_pEWrapper->updateMktDepthL2( id, position, marketMaker, operation, side,
price, size);
return ptr;
}
const char* EDecoder::processNewsBulletinsMsg(const char* ptr, const char* endPtr) {
int version;
int msgId;
int msgType;
std::string newsMessage;
std::string originatingExch;
DECODE_FIELD( version);
DECODE_FIELD( msgId);
DECODE_FIELD( msgType);
DECODE_FIELD( newsMessage);
DECODE_FIELD( originatingExch);
m_pEWrapper->updateNewsBulletin( msgId, msgType, newsMessage, originatingExch);
return ptr;
}
const char* EDecoder::processManagedAcctsMsg(const char* ptr, const char* endPtr) {
int version;
std::string accountsList;
DECODE_FIELD( version);
DECODE_FIELD( accountsList);
m_pEWrapper->managedAccounts( accountsList);
return ptr;
}
const char* EDecoder::processReceiveFaMsg(const char* ptr, const char* endPtr) {
int version;
int faDataTypeInt;
std::string cxml;
DECODE_FIELD( version);
DECODE_FIELD( faDataTypeInt);
DECODE_FIELD( cxml);
m_pEWrapper->receiveFA( (faDataType)faDataTypeInt, cxml);
return ptr;
}
const char* EDecoder::processHistoricalDataMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
std::string startDateStr;
std::string endDateStr;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( startDateStr); // ver 2 field
DECODE_FIELD( endDateStr); // ver 2 field
int itemCount;
DECODE_FIELD( itemCount);
typedef std::vector<BarData> BarDataList;
BarDataList bars;
bars.reserve( itemCount);
for( int ctr = 0; ctr < itemCount; ++ctr) {
BarData bar;
DECODE_FIELD( bar.date);
DECODE_FIELD( bar.open);
DECODE_FIELD( bar.high);
DECODE_FIELD( bar.low);
DECODE_FIELD( bar.close);
DECODE_FIELD( bar.volume);
DECODE_FIELD( bar.average);
DECODE_FIELD( bar.hasGaps);
DECODE_FIELD( bar.barCount); // ver 3 field
bars.push_back(bar);
}
assert( (int)bars.size() == itemCount);
for( int ctr = 0; ctr < itemCount; ++ctr) {
const BarData& bar = bars[ctr];
m_pEWrapper->historicalData( reqId, bar.date, bar.open, bar.high, bar.low,
bar.close, bar.volume, bar.barCount, bar.average,
bar.hasGaps == "true");
}
// send end of dataset marker
std::string finishedStr = std::string("finished-") + startDateStr + "-" + endDateStr;
m_pEWrapper->historicalData( reqId, finishedStr, -1, -1, -1, -1, -1, -1, -1, 0);
return ptr;
}
const char* EDecoder::processScannerDataMsg(const char* ptr, const char* endPtr) {
int version;
int tickerId;
DECODE_FIELD( version);
DECODE_FIELD( tickerId);
int numberOfElements;
DECODE_FIELD( numberOfElements);
typedef std::vector<ScanData> ScanDataList;
ScanDataList scannerDataList;
scannerDataList.reserve( numberOfElements);
for( int ctr=0; ctr < numberOfElements; ++ctr) {
ScanData data;
DECODE_FIELD( data.rank);
DECODE_FIELD( data.contract.summary.conId); // ver 3 field
DECODE_FIELD( data.contract.summary.symbol);
DECODE_FIELD( data.contract.summary.secType);
DECODE_FIELD( data.contract.summary.lastTradeDateOrContractMonth);
DECODE_FIELD( data.contract.summary.strike);
DECODE_FIELD( data.contract.summary.right);
DECODE_FIELD( data.contract.summary.exchange);
DECODE_FIELD( data.contract.summary.currency);
DECODE_FIELD( data.contract.summary.localSymbol);
DECODE_FIELD( data.contract.marketName);
DECODE_FIELD( data.contract.summary.tradingClass);
DECODE_FIELD( data.distance);
DECODE_FIELD( data.benchmark);
DECODE_FIELD( data.projection);
DECODE_FIELD( data.legsStr);
scannerDataList.push_back( data);
}
assert( (int)scannerDataList.size() == numberOfElements);
for( int ctr=0; ctr < numberOfElements; ++ctr) {
const ScanData& data = scannerDataList[ctr];
m_pEWrapper->scannerData( tickerId, data.rank, data.contract,
data.distance, data.benchmark, data.projection, data.legsStr);
}
m_pEWrapper->scannerDataEnd( tickerId);
return ptr;
}
const char* EDecoder::processScannerParametersMsg(const char* ptr, const char* endPtr) {
int version;
std::string xml;
DECODE_FIELD( version);
DECODE_FIELD( xml);
m_pEWrapper->scannerParameters( xml);
return ptr;
}
const char* EDecoder::processCurrentTimeMsg(const char* ptr, const char* endPtr) {
int version;
int time;
DECODE_FIELD(version);
DECODE_FIELD(time);
m_pEWrapper->currentTime( time);
return ptr;
}
const char* EDecoder::processRealTimeBarsMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
int time;
double open;
double high;
double low;
double close;
int volume;
double average;
int count;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( time);
DECODE_FIELD( open);
DECODE_FIELD( high);
DECODE_FIELD( low);
DECODE_FIELD( close);
DECODE_FIELD( volume);
DECODE_FIELD( average);
DECODE_FIELD( count);
m_pEWrapper->realtimeBar( reqId, time, open, high, low, close,
volume, average, count);
return ptr;
}
const char* EDecoder::processFundamentalDataMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
std::string data;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( data);
m_pEWrapper->fundamentalData( reqId, data);
return ptr;
}
const char* EDecoder::processContractDataEndMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
m_pEWrapper->contractDetailsEnd( reqId);
return ptr;
}
const char* EDecoder::processOpenOrderEndMsg(const char* ptr, const char* endPtr) {
int version;
DECODE_FIELD( version);
m_pEWrapper->openOrderEnd();
return ptr;
}
const char* EDecoder::processAcctDownloadEndMsg(const char* ptr, const char* endPtr) {
int version;
std::string account;
DECODE_FIELD( version);
DECODE_FIELD( account);
m_pEWrapper->accountDownloadEnd( account);
return ptr;
}
const char* EDecoder::processExecutionDataEndMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
m_pEWrapper->execDetailsEnd( reqId);
return ptr;
}
const char* EDecoder::processDeltaNeutralValidationMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
UnderComp underComp;
DECODE_FIELD( underComp.conId);
DECODE_FIELD( underComp.delta);
DECODE_FIELD( underComp.price);
m_pEWrapper->deltaNeutralValidation( reqId, underComp);
return ptr;
}
const char* EDecoder::processTickSnapshotEndMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
m_pEWrapper->tickSnapshotEnd( reqId);
return ptr;
}
const char* EDecoder::processMarketDataTypeMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
int marketDataType;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( marketDataType);
m_pEWrapper->marketDataType( reqId, marketDataType);
return ptr;
}
const char* EDecoder::processCommissionReportMsg(const char* ptr, const char* endPtr) {
int version;
DECODE_FIELD( version);
CommissionReport commissionReport;
DECODE_FIELD( commissionReport.execId);
DECODE_FIELD( commissionReport.commission);
DECODE_FIELD( commissionReport.currency);
DECODE_FIELD( commissionReport.realizedPNL);
DECODE_FIELD( commissionReport.yield);
DECODE_FIELD( commissionReport.yieldRedemptionDate);
m_pEWrapper->commissionReport( commissionReport);
return ptr;
}
const char* EDecoder::processPositionDataMsg(const char* ptr, const char* endPtr) {
int version;
std::string account;
double position;
double avgCost = 0;
DECODE_FIELD( version);
DECODE_FIELD( account);
// decode contract fields
Contract contract;
DECODE_FIELD( contract.conId);
DECODE_FIELD( contract.symbol);
DECODE_FIELD( contract.secType);
DECODE_FIELD( contract.lastTradeDateOrContractMonth);
DECODE_FIELD( contract.strike);
DECODE_FIELD( contract.right);
DECODE_FIELD( contract.multiplier);
DECODE_FIELD( contract.exchange);
DECODE_FIELD( contract.currency);
DECODE_FIELD( contract.localSymbol);
if (version >= 2) {
DECODE_FIELD( contract.tradingClass);
}
if (m_serverVersion >= MIN_SERVER_VER_FRACTIONAL_POSITIONS)
{
DECODE_FIELD( position);
}
else
{
int iPosition;
DECODE_FIELD(iPosition);
position = iPosition;
}
if (version >= 3) {
DECODE_FIELD( avgCost);
}
m_pEWrapper->position( account, contract, position, avgCost);
return ptr;
}
const char* EDecoder::processPositionEndMsg(const char* ptr, const char* endPtr) {
int version;
DECODE_FIELD( version);
m_pEWrapper->positionEnd();
return ptr;
}
const char* EDecoder::processAccountSummaryMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
std::string account;
std::string tag;
std::string value;
std::string curency;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( account);
DECODE_FIELD( tag);
DECODE_FIELD( value);
DECODE_FIELD( curency);
m_pEWrapper->accountSummary( reqId, account, tag, value, curency);
return ptr;
}
const char* EDecoder::processAccountSummaryEndMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
m_pEWrapper->accountSummaryEnd( reqId);
return ptr;
}
const char* EDecoder::processVerifyMessageApiMsg(const char* ptr, const char* endPtr) {
int version;
std::string apiData;
DECODE_FIELD( version);
DECODE_FIELD( apiData);
m_pEWrapper->verifyMessageAPI( apiData);
return ptr;
}
const char* EDecoder::processVerifyCompletedMsg(const char* ptr, const char* endPtr) {
int version;
std::string isSuccessful;
std::string errorText;
DECODE_FIELD( version);
DECODE_FIELD( isSuccessful);
DECODE_FIELD( errorText);
bool bRes = isSuccessful == "true";
m_pEWrapper->verifyCompleted( bRes, errorText);
return ptr;
}
const char* EDecoder::processDisplayGroupListMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
std::string groups;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( groups);
m_pEWrapper->displayGroupList( reqId, groups);
return ptr;
}
const char* EDecoder::processDisplayGroupUpdatedMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
std::string contractInfo;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( contractInfo);
m_pEWrapper->displayGroupUpdated( reqId, contractInfo);
return ptr;
}
const char* EDecoder::processVerifyAndAuthMessageApiMsg(const char* ptr, const char* endPtr) {
int version;
std::string apiData;
std::string xyzChallenge;
DECODE_FIELD( version);
DECODE_FIELD( apiData);
DECODE_FIELD( xyzChallenge);
m_pEWrapper->verifyAndAuthMessageAPI( apiData, xyzChallenge);
return ptr;
}
const char* EDecoder::processVerifyAndAuthCompletedMsg(const char* ptr, const char* endPtr) {
int version;
std::string isSuccessful;
std::string errorText;
DECODE_FIELD( version);
DECODE_FIELD( isSuccessful);
DECODE_FIELD( errorText);
bool bRes = isSuccessful == "true";
m_pEWrapper->verifyAndAuthCompleted( bRes, errorText);
return ptr;
}
const char* EDecoder::processPositionMultiMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
std::string account;
std::string modelCode;
double position;
double avgCost = 0;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( account);
// decode contract fields
Contract contract;
DECODE_FIELD( contract.conId);
DECODE_FIELD( contract.symbol);
DECODE_FIELD( contract.secType);
DECODE_FIELD( contract.lastTradeDateOrContractMonth);
DECODE_FIELD( contract.strike);
DECODE_FIELD( contract.right);
DECODE_FIELD( contract.multiplier);
DECODE_FIELD( contract.exchange);
DECODE_FIELD( contract.currency);
DECODE_FIELD( contract.localSymbol);
DECODE_FIELD( contract.tradingClass);
DECODE_FIELD( position);
DECODE_FIELD( avgCost);
DECODE_FIELD( modelCode);
m_pEWrapper->positionMulti( reqId, account, modelCode, contract, position, avgCost);
return ptr;
}
const char* EDecoder::processPositionMultiEndMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
m_pEWrapper->positionMultiEnd( reqId);
return ptr;
}
const char* EDecoder::processAccountUpdateMultiMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
std::string account;
std::string modelCode;
std::string key;
std::string value;
std::string currency;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
DECODE_FIELD( account);
DECODE_FIELD( modelCode);
DECODE_FIELD( key);
DECODE_FIELD( value);
DECODE_FIELD( currency);
m_pEWrapper->accountUpdateMulti( reqId, account, modelCode, key, value, currency);
return ptr;
}
const char* EDecoder::processAccountUpdateMultiEndMsg(const char* ptr, const char* endPtr) {
int version;
int reqId;
DECODE_FIELD( version);
DECODE_FIELD( reqId);
m_pEWrapper->accountUpdateMultiEnd( reqId);
return ptr;
}
const char* EDecoder::processSecurityDefinitionOptionalParameterMsg(const char* ptr, const char* endPtr) {
int reqId;
std::string exchange;
int underlyingConId;
std::string tradingClass;
std::string multiplier;
int expirationsSize, strikesSize;
std::set<std::string> expirations;
std::set<double> strikes;
DECODE_FIELD(reqId);
DECODE_FIELD(exchange);
DECODE_FIELD(underlyingConId);
DECODE_FIELD(tradingClass);
DECODE_FIELD(multiplier);
DECODE_FIELD(expirationsSize);
for (int i = 0; i < expirationsSize; i++) {
std::string expiration;
DECODE_FIELD(expiration);
expirations.insert(expiration);
}
DECODE_FIELD(strikesSize);
for (int i = 0; i < strikesSize; i++) {
double strike;
DECODE_FIELD(strike);
strikes.insert(strike);
}
m_pEWrapper->securityDefinitionOptionalParameter(reqId, exchange, underlyingConId, tradingClass, multiplier, expirations, strikes);
return ptr;
}
const char* EDecoder::processSecurityDefinitionOptionalParameterEndMsg(const char* ptr, const char* endPtr) {
int reqId;
DECODE_FIELD(reqId);
m_pEWrapper->securityDefinitionOptionalParameterEnd(reqId);
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)
{
// process a connect Ack message from the buffer;
// return number of bytes consumed
assert( beginPtr && beginPtr < endPtr);
try {
const char* ptr = beginPtr;
// check server version
DECODE_FIELD( m_serverVersion);
// handle redirects
if( m_serverVersion < 0) {
m_serverVersion = 0;
std::string hostport, host;
int port = -1;
DECODE_FIELD( hostport);
std::string::size_type sep = hostport.find( ':');
if( sep != std::string::npos) {
host = hostport.substr(0, sep);
port = atoi( hostport.c_str() + ++sep);
}
else {
host = hostport;
}
if (m_pClientMsgSink)
m_pClientMsgSink->redirect(host.c_str(), port);
} else {
std::string twsTime;
if( m_serverVersion >= 20) {
DECODE_FIELD(twsTime);
}
if (m_pClientMsgSink)
m_pClientMsgSink->serverVersion(m_serverVersion, twsTime.c_str());
m_pEWrapper->connectAck();
}
int processed = ptr - beginPtr;
beginPtr = ptr;
return processed;
}
catch( std::exception e) {
m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(),
SOCKET_EXCEPTION.msg() + errMsg( e) );
}
return 0;
}
int EDecoder::parseAndProcessMsg(const char*& beginPtr, const char* endPtr) {
// process a single message from the buffer;
// return number of bytes consumed
assert( beginPtr && beginPtr < endPtr);
if (m_serverVersion == 0)
return processConnectAck(beginPtr, endPtr);
try {
const char* ptr = beginPtr;
int msgId;
DECODE_FIELD( msgId);
switch( msgId) {
case TICK_PRICE:
ptr = processTickPriceMsg(ptr, endPtr);
break;
case TICK_SIZE:
ptr = processTickSizeMsg(ptr, endPtr);
break;
case TICK_OPTION_COMPUTATION:
ptr = processTickOptionComputationMsg(ptr, endPtr);
break;
case TICK_GENERIC:
ptr = processTickGenericMsg(ptr, endPtr);
break;
case TICK_STRING:
ptr = processTickStringMsg(ptr, endPtr);
break;
case TICK_EFP:
ptr = processTickEfpMsg(ptr, endPtr);
break;
case ORDER_STATUS:
ptr = processOrderStatusMsg(ptr, endPtr);
break;
case ERR_MSG:
ptr = processErrMsgMsg(ptr, endPtr);
break;
case OPEN_ORDER:
ptr = processOpenOrderMsg(ptr, endPtr);
break;
case ACCT_VALUE:
ptr = processAcctValueMsg(ptr, endPtr);
break;
case PORTFOLIO_VALUE:
ptr = processPortfolioValueMsg(ptr, endPtr);
break;
case ACCT_UPDATE_TIME:
ptr = processAcctUpdateTimeMsg(ptr, endPtr);
break;
case NEXT_VALID_ID:
ptr = processNextValidIdMsg(ptr, endPtr);
break;
case CONTRACT_DATA:
ptr = processContractDataMsg(ptr, endPtr);
break;
case BOND_CONTRACT_DATA:
ptr = processBondContractDataMsg(ptr, endPtr);
break;
case EXECUTION_DATA:
ptr = processExecutionDataMsg(ptr, endPtr);
break;
case MARKET_DEPTH:
ptr = processMarketDepthMsg(ptr, endPtr);
break;
case MARKET_DEPTH_L2:
ptr = processMarketDepthL2Msg(ptr, endPtr);
break;
case NEWS_BULLETINS:
ptr = processNewsBulletinsMsg(ptr, endPtr);
break;
case MANAGED_ACCTS:
ptr = processManagedAcctsMsg(ptr, endPtr);
break;
case RECEIVE_FA:
ptr = processReceiveFaMsg(ptr, endPtr);
break;
case HISTORICAL_DATA:
ptr = processHistoricalDataMsg(ptr, endPtr);
break;
case SCANNER_DATA:
ptr = processScannerDataMsg(ptr, endPtr);
break;
case SCANNER_PARAMETERS:
ptr = processScannerParametersMsg(ptr, endPtr);
break;
case CURRENT_TIME:
ptr = processCurrentTimeMsg(ptr, endPtr);
break;
case REAL_TIME_BARS:
ptr = processRealTimeBarsMsg(ptr, endPtr);
break;
case FUNDAMENTAL_DATA:
ptr = processFundamentalDataMsg(ptr, endPtr);
break;
case CONTRACT_DATA_END:
ptr = processContractDataEndMsg(ptr, endPtr);
break;
case OPEN_ORDER_END:
ptr = processOpenOrderEndMsg(ptr, endPtr);
break;
case ACCT_DOWNLOAD_END:
ptr = processAcctDownloadEndMsg(ptr, endPtr);
break;
case EXECUTION_DATA_END:
ptr = processExecutionDataEndMsg(ptr, endPtr);
break;
case DELTA_NEUTRAL_VALIDATION:
ptr = processDeltaNeutralValidationMsg(ptr, endPtr);
break;
case TICK_SNAPSHOT_END:
ptr = processTickSnapshotEndMsg(ptr, endPtr);
break;
case MARKET_DATA_TYPE:
ptr = processMarketDataTypeMsg(ptr, endPtr);
break;
case COMMISSION_REPORT:
ptr = processCommissionReportMsg(ptr, endPtr);
break;
case POSITION_DATA:
ptr = processPositionDataMsg(ptr, endPtr);
break;
case POSITION_END:
ptr = processPositionEndMsg(ptr, endPtr);
break;
case ACCOUNT_SUMMARY:
ptr = processAccountSummaryMsg(ptr, endPtr);
break;
case ACCOUNT_SUMMARY_END:
ptr = processAccountSummaryEndMsg(ptr, endPtr);
break;
case VERIFY_MESSAGE_API:
ptr = processVerifyMessageApiMsg(ptr, endPtr);
break;
case VERIFY_COMPLETED:
ptr = processVerifyCompletedMsg(ptr, endPtr);
break;
case DISPLAY_GROUP_LIST:
ptr = processDisplayGroupListMsg(ptr, endPtr);
break;
case DISPLAY_GROUP_UPDATED:
ptr = processDisplayGroupUpdatedMsg(ptr, endPtr);
break;
case VERIFY_AND_AUTH_MESSAGE_API:
ptr = processVerifyAndAuthMessageApiMsg(ptr, endPtr);
break;
case VERIFY_AND_AUTH_COMPLETED:
ptr = processVerifyAndAuthCompletedMsg(ptr, endPtr);
break;
case POSITION_MULTI:
ptr = processPositionMultiMsg(ptr, endPtr);
break;
case POSITION_MULTI_END:
ptr = processPositionMultiEndMsg(ptr, endPtr);
break;
case ACCOUNT_UPDATE_MULTI:
ptr = processAccountUpdateMultiMsg(ptr, endPtr);
break;
case ACCOUNT_UPDATE_MULTI_END:
ptr = processAccountUpdateMultiEndMsg(ptr, endPtr);
break;
case SECURITY_DEFINITION_OPTION_PARAMETER:
ptr = processSecurityDefinitionOptionalParameterMsg(ptr, endPtr);
break;
case SECURITY_DEFINITION_OPTION_PARAMETER_END:
ptr = processSecurityDefinitionOptionalParameterEndMsg(ptr, endPtr);
break;
case SOFT_DOLLAR_TIERS:
ptr = processSoftDollarTiersMsg(ptr, endPtr);
break;
default:
{
m_pEWrapper->error( msgId, UNKNOWN_ID.code(), UNKNOWN_ID.msg());
m_pEWrapper->connectionClosed();
break;
}
}
if (!ptr)
return 0;
int processed = ptr - beginPtr;
beginPtr = ptr;
return processed;
}
catch( std::exception e) {
m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(),
SOCKET_EXCEPTION.msg() + errMsg(e));
}
return 0;
}
bool EDecoder::CheckOffset(const char* ptr, const char* endPtr)
{
assert (ptr && ptr <= endPtr);
return (ptr && ptr < endPtr);
}
const char* EDecoder::FindFieldEnd(const char* ptr, const char* endPtr)
{
return (const char*)memchr(ptr, 0, endPtr - ptr);
}
bool EDecoder::DecodeField(bool& boolValue, const char*& ptr, const char* endPtr)
{
int intValue;
if( !DecodeField(intValue, ptr, endPtr))
return false;
boolValue = (intValue > 0);
return true;
}
bool EDecoder::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 EDecoder::DecodeField(long& longValue, const char*& ptr, const char* endPtr)
{
int intValue;
if( !DecodeField(intValue, ptr, endPtr))
return false;
longValue = intValue;
return true;
}
bool EDecoder::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 EDecoder::DecodeField(std::string& 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 EDecoder::DecodeFieldMax(int& intValue, const char*& ptr, const char* endPtr)
{
std::string stringValue;
if( !DecodeField(stringValue, ptr, endPtr))
return false;
intValue = stringValue.empty() ? UNSET_INTEGER : atoi(stringValue.c_str());
return true;
}
bool EDecoder::DecodeFieldMax(long& longValue, const char*& ptr, const char* endPtr)
{
int intValue;
if( !DecodeFieldMax(intValue, ptr, endPtr))
return false;
longValue = intValue;
return true;
}
bool EDecoder::DecodeFieldMax(double& doubleValue, const char*& ptr, const char* endPtr)
{
std::string stringValue;
if( !DecodeField(stringValue, ptr, endPtr))
return false;
doubleValue = stringValue.empty() ? UNSET_DOUBLE : atof(stringValue.c_str());
return true;
}