Skip to content

Example: Retrieve History

Richard Holowczak edited this page Jan 20, 2016 · 9 revisions
/*========================================================================
 * TwsApiC++ - Demonstration program
 * Retrieving historical data from Interactive Brokers
 * See the ///blocks for some explanation
 *========================================================================
 */

///Easier: Just one include statement for all functionality
#include "TwsApiL0.h"

///Faster: Check spelling of parameter at compile time instead of runtime.
#include "TwsApiDefs.h"
using namespace TwsApi; // for TwsApiDefs.h

///Advantages of deriving from EWrapperL0
/// Faster: implement only the methods you need.
/// Safe: receive notification of methods called you didn't implement
/// Robust: exceptions thrown by your code are catched safely and notified to you
class YourEWrapper: public EWrapperL0 {

  public:
  bool m_Done, m_ErrorForRequest;
  bool notDone( void ) { return !(m_Done || m_ErrorForRequest); }
 
  ///Easier: The EReader calls all methods automatically(optional)
  YourEWrapper( bool runEReader = true ): EWrapperL0( runEReader ) {
    m_Done            = false;
    m_ErrorForRequest = false;
  }

  ///Methods winError & error print the errors reported by IB TWS
  virtual void winError( const IBString& str, int lastError ) {
    fprintf( stderr, "WinError: %d = %s\n", lastError, (const char*)str );
    m_ErrorForRequest = true;
  }

  virtual void error( const int id, const int errorCode, const IBString errorString ) {
    fprintf( stderr, "Error for id=%d: %d = %s\n"
	   , id, errorCode, (const char*)errorString );
    m_ErrorForRequest = (id > 0);    // id == -1 are 'system' messages, not for user requests
  }


  ///Safer: uncatched exceptions are catched before they reach the IB library code.
  ///       The Id is tickerId, orderId, or reqId, or -1 when no id known
  virtual void OnCatch( const char* MethodName, const long Id ) {
    fprintf( stderr, "*** Catch in EWrapper::%s( Id=%ld, ...) \n", MethodName, Id );
  }
  
  ///Faster: Implement only the method for the task.
  /// => TwsApiC++  provides an empty implementation for each EWrapper method.
  virtual void historicalData( TickerId reqId, const IBString& date
                             , double open, double high, double low, double close
                             ,int volume, int barCount, double WAP, int hasGaps ) {

    ///Easier: EWrapperL0 provides an extra method to check all data was retrieved
    if( IsEndOfHistoricalData(date) ) {
      m_Done = true;
      return;
    }

    fprintf( stdout, "%10s, %5.3f, %5.3f, %5.3f, %5.3f, %7d\n"
      , (const  char*)date,  open,  high,   low, close, volume );
  }
}

//========================================================================
// main entry
//========================================================================
int main(void) {
    ///Easier: just allocate your wrapper and instantiate the EClientL0 with it.
    YourEWrapper  YW( false );                      // false: not using the EReader
    EClientL0*    EC = EClientL0::New( &YW );

    ///Easier: All structures defined by IB are immediately available.
    ///Faster: Use of TwsApiDefs.h codes check typos at compile time
    Contract          C;
    C.symbol          = "MSFT";
    C.secType         = *SecType::STK;              // instead of "STK"
    C.currency        = "USD";
    C.exchange        = *Exchange::IB_SMART;        // instead of "SMART"
    C.primaryExchange = *Exchange::AMEX;            // instead of "AMEX"

    ///Easier: Use of TwsApiDefs.h makes code self explanatory,
    ///        i.e. UseRTH::OnlyRegularTradingData instead of true or 1.
    if( EC->eConnect( "", 7496, 100 ) ) {
      EC->reqHistoricalData
        ( 20
        , C
        , EndDateTime(2013,02,20)                   // 20130220 00:00:00
        , DurationStr(1, *DurationHorizon::Months)  // instead of "1 M"
        , *BarSizeSetting::_1_day                   // instead of "1 day"
        , *WhatToShow::TRADES                       // instead of "TRADES"
        , UseRTH::OnlyRegularTradingData            // instead of 1
        , FormatDate::AsDate                        // instead of 1
        ); 

      ///Easier: Call checkMessages() in a loop. No need to wait between two calls.
      while( YW.notDone() ) {
        EC->checkMessages();
      }
      
    }

    EC->eDisconnect();
    delete EC;
}

Some tips for implementing this example with Visual Studio 2012 or 2013

Below are some of the tweaks to make a Visual Studio project when creating a fresh TwsApiC++ project. Assuming you have copied the TwsApiC++ to C:\Jts\TwsApiCpp (adjust to your installation accordingly) and have compiled the TwsApiC++ library TwsApi.lib and saved it to C:\Jts\TwsApiCpp\TwsApiC++\Api

  • For the Project property: Project -> Properties -> C/C++ -> General -> Additional Include Directories Add the following folders for Shared and the API so that Visual Studio can find the header files:
    C:\Jts\TwsApiCpp\source\PosixClient\Shared
    C:\Jts\TwsApiCpp\TwsApiC++\Api
  • For the Project property: Project -> Properties -> Linker -> General -> Additional Library Directories Add the following folder:

C:\Jts\TwsApiCpp\TwsApiC++\Api

  • For the Project property: Project -> Properties -> Linker -> Input -> Additional Dependencies Add the following files:
    TwsApi.lib  (for Release)
    TwsApiD.lib  (for Debug)
    ws2_32.lib 
  • For the Project property: Project -> Properties -> C/C++ -> Code Generation -> Runtime Library

For Release: Set to Multi-Threaded /MT to match the other libraries.

For Debug: Set to Multi-Threaded Debug /MTd to match the other libraries.

  • If you are building for Debug, use the Multi-Threaded Debug /MTd switch and add the TwsApiD.lib file.

  • If you are building for Release, use the Multi-Threaded /MT switch and add the TwsApi.lib file.

  • In Visual Studio 2013, you may also receive some warnings about the use of the "unsafe" functions like sprintf and localtime. The suggested replacements are sprintf_s and localtime_s. The sprintf_s call is a direct replacement for sprintf but localtime_s uses some different structures.

To get around these warnings (which may keep your program from compiling), add a #define _CRT_SECURE_NO_WARNINGS at the top of your program.

Clone this wiki locally