void TwsDL::connectTws() { assert( !twsClient->isConnected() && !connectivity_IB_TWS ); int64_t w = nowInMsecs() - lastConnectionTime; if( w < cfg.tws_conTimeout ) { DEBUG_PRINTF( "Waiting %ldms before connecting again.", (long)(cfg.tws_conTimeout - w) ); curIdleTime = cfg.tws_conTimeout - w; return; } lastConnectionTime = nowInMsecs(); changeState( WAIT_TWS_CON ); /* this may callback (negative) error messages only */ bool con = twsClient->connectTWS( cfg.tws_host, cfg.tws_port, cfg.tws_client_id, cfg.ai_family ); assert( con == twsClient->isConnected() ); if( !con ) { DEBUG_PRINTF("TWS connection failed."); changeState(IDLE); } else { DEBUG_PRINTF("TWS connection established: %d, %s", twsClient->serverVersion(), twsClient->TwsConnectionTime().c_str()); /* this must be set before any possible "Connectivity" callback msg */ connectivity_IB_TWS = true; /* waiting for first messages until tws_time is received */ tws_hb->reset(); tws_hb->cnt_sent = 1; tws_hb->time_sent = nowInMsecs(); twsClient->reqCurrentTime(); } }
int PacingControl::goodTime(const char** ddd) const { const int64_t now = nowInMsecs(); const char* dbg = "don't wait"; int retVal = INT_MIN; if( dateTimes.empty() ) { *ddd = dbg; return retVal; } int waitMin = dateTimes.back() + minPacingTime - now; SWAP_MAX( waitMin, "wait min" ); // int waitAvg = dateTimes.last() + avgPacingTime - now; // SWAP_MAX( waitAvg, "wait avg" ); int waitViol = violations.back() ? (dateTimes.back() + violationPause - now) : INT_MIN; SWAP_MAX( waitViol, "wait violation" ); int waitBurst = INT_MIN; int p_index = dateTimes.size() - maxRequests; if( p_index >= 0 ) { int64_t p_time = dateTimes.at( p_index ); waitBurst = p_time + checkInterval - now; } SWAP_MAX( waitBurst, "wait burst" ); *ddd = dbg; return retVal; }
void TwsDL::twsConnectionClosed() { DEBUG_PRINTF( "disconnected in state %d", state ); if( currentRequest.reqType() != GenericRequest::NONE ) { if( !packet->finished() ) { switch( currentRequest.reqType() ) { case GenericRequest::CONTRACT_DETAILS_REQUEST: case GenericRequest::ACC_STATUS_REQUEST: case GenericRequest::EXECUTIONS_REQUEST: case GenericRequest::ORDERS_REQUEST: assert(false); // TODO repeat break; case GenericRequest::HIST_REQUEST: packet->closeError( REQ_ERR_TWSCON ); break; case GenericRequest::NONE: assert(false); break; } } } assert( p_orders.empty() ); // TODO repeat connectivity_IB_TWS = false; dataFarms.setAllBroken(); pacingControl.clear(); /* avoid re-connect right now */ lastConnectionTime = nowInMsecs(); }
void PacketPlaceOrder::record( long orderId, const PlaceOrder& oP ) { assert( mode == CLEAN && error == REQ_ERR_NONE && request == NULL ); mode = RECORD; this->request = new PlaceOrder( oP ); this->request->orderId = orderId; this->request->time_sent = nowInMsecs(); }
void PacketPlaceOrder::modify( const PlaceOrder& oP ) { assert( mode == RECORD ); assert( this->request->orderId == oP.orderId ); delete this->request; this->request = new PlaceOrder( oP ); this->request->time_sent = nowInMsecs(); }
void TwsDL::waitData() { finPlaceOrder(); if( packet == NULL || currentRequest.reqType() == GenericRequest::NONE ) { return; } if( !packet->finished() ) { if( currentRequest.age() <= cfg.tws_reqTimeout ) { static int64_t last = 0; int64_t now = nowInMsecs(); if( now - last > 2000 ) { last = now; DEBUG_PRINTF( "Still waiting for data." ); } return; } else { DEBUG_PRINTF( "Timeout waiting for data." ); packet->closeError( REQ_ERR_TIMEOUT ); } } bool ok = false; switch( currentRequest.reqType() ) { case GenericRequest::CONTRACT_DETAILS_REQUEST: ok = finContracts(); break; case GenericRequest::HIST_REQUEST: ok = finHist(); break; case GenericRequest::ACC_STATUS_REQUEST: case GenericRequest::EXECUTIONS_REQUEST: case GenericRequest::ORDERS_REQUEST: packet->dumpXml(); ok = true; break; case GenericRequest::NONE: assert(false); break; } if( !ok ) { error = 1; _lastError = "Fatal error."; quit = true; } delete packet; packet = NULL; currentRequest.close(); }
void TwsDL::twsTickSize( int reqId, IB::TickType field, int size ) { Quote &q = quotes->at(reqId-1); q.val[field] = size; q.stamp[field] = nowInMsecs(); const std::vector<MktDataRequest> &mdlist = workTodo->getMktDataTodo().mktDataRequests; assert( reqId > 0 && reqId <= (int)mdlist.size() ); const IB::Contract &c = workTodo->getMktDataTodo().mktDataRequests[reqId - 1].ibContract; DEBUG_PRINTF( "TICK_SIZE: %d %s %ld %s %d", reqId, c.symbol.c_str(), c.conId, ibToString(field).c_str(), size ); }
void PacingControl::clear() { if( !dateTimes.empty() ) { int64_t now = nowInMsecs(); if( now - dateTimes.back() < 5000 ) { // HACK race condition might cause assert in notifyViolation(), // to avoid this we would need to ack each request DEBUG_PRINTF( "Warning, keep last pacing date time " "because it looks too new." ); dateTimes.erase( dateTimes.begin(), --(dateTimes.end()) ); violations.erase( violations.begin(), --(violations.end()) ); } else { dateTimes.clear(); violations.clear(); } } }
bool TwsDL::finPlaceOrder() { bool ok = true; std::map<long, PacketPlaceOrder*>::iterator it = p_orders.begin(); while( it != p_orders.end() ) { /* increment it already here and use it_tmp because erase would invalidate it */ std::map<long, PacketPlaceOrder*>::iterator it_tmp = it++; long orderId = it_tmp->first; PacketPlaceOrder* p = it_tmp->second; const PlaceOrder &r = p->getRequest(); assert( orderId == r.orderId ); if( ! p->finished() ) { /* close non transmit orders where we haven't received errors */ if( !r.order.transmit && (nowInMsecs() - r.time_sent) > 5000 ) { p->closeError( REQ_ERR_NONE ); } else { continue; } } switch( p->getError() ) { case REQ_ERR_NONE: case REQ_ERR_REQUEST: case REQ_ERR_TIMEOUT: p->dumpXml(); DEBUG_PRINTF("fin order, %ld %s, %ld", orderId, r.contract.symbol.c_str(), r.contract.conId); assert( p_orders_old.find(orderId) == p_orders_old.end() ); p_orders_old[orderId] = p; p_orders.erase( it_tmp ); case REQ_ERR_NODATA: case REQ_ERR_NAV: break; case REQ_ERR_TWSCON: ok = false; } } return ok; }
void TwsDL::waitTwsCon() { int64_t w = cfg.tws_conTimeout - (nowInMsecs() - lastConnectionTime); if( twsClient->isConnected() ) { if( tws_hb->tws_time != 0 ) { DEBUG_PRINTF( "Connection process finished." ); changeState( IDLE ); } else if( w > 0 ) { DEBUG_PRINTF( "Still waiting for connection finish." ); curIdleTime = w; } else { DEBUG_PRINTF( "Timeout connecting TWS." ); twsClient->disconnectTWS(); } } else { // TODO print a specific error DEBUG_PRINTF( "Connecting TWS failed." ); changeState( IDLE ); } }
int PacingControl::countLeft() const { const int64_t now = nowInMsecs(); if( (dateTimes.size() > 0) && violations.back() ) { int waitViol = dateTimes.back() + violationPause - now; if( waitViol > 0 ) { return 0; } } int retVal = maxRequests; std::vector<int64_t>::const_iterator it = dateTimes.end(); while( it != dateTimes.begin() ) { it--; int waitBurst = *it + checkInterval - now; if( waitBurst > 0 ) { retVal--; } else { break; } } return retVal; }
void TwsDL::twsCurrentTime( long time ) { tws_hb->cnt_recv++; tws_hb->time_recv = nowInMsecs(); tws_hb->tws_time = time; }
void GenericRequest::nextRequest( ReqType t ) { _reqType = t; _reqId++; _ctime = nowInMsecs(); }
int GenericRequest::age() const { return (nowInMsecs() - _ctime); }
void PacingControl::addRequest() { const int64_t now_t = nowInMsecs(); dateTimes.push_back( now_t ); violations.push_back( false ); }