C++ Backtesting to API

Discussion in 'App Development' started by Maverick1, Feb 8, 2019.

  1. Maverick1

    Maverick1

    GRUL and other Master/Yoda Coders...

    Young C++ Jedi here trying to make his way through IB's code galaxy...

    I'm working with Jan Boonen's TwsAPICpp code which apparently is still working for some on this forum

    https://github.com/JanBoonen/TwsApiCpp

    A kind soul suggested I take a look at how test.cpp is implemented for a base case. Here's what I can make out of the code:

    MyEWrapper inherits from EWrapperL0 which, according to TwsApilL0.h, in turn extends EWrapper; so the end-user basically needs to create a wrapper that wraps around another wrapper? (or is it my brain that's wrapped around itself?)

    I don't quite get the 'boolCalledFromThread = true' syntax:

    /*
    public:

    MyEWrapper( boolCalledFromThread = true ): EWrapperL0( CalledFromThread ) {}

    */

    but recognize the constructor format. The rest of the class looks like method declarations.

    In "Main", he creates a MyEWrapper class object MW (which is customized to derive from EWrapperL0 in TwsApiL0.h header file) which he then passes by reference to a new memory allocated EC object of type EClientL0. This object looks like its the big daddy (?) EClientL0 (also in the TwsApiL0.h header file) extends EClient (defined in the EClient.h header and looks fairly tight, contains the key eConnect and eDisconnect methods among a gazillion others)

    Then he connects to IB via this EC object of type EClientL0 and calls EC->eConnect, with the port number it looks like (7496?), requests some historical data for stock ticker C (Citigroup). Then comes a bunch of if statements that I'm not sure about: are these checking for a lack of connection between the client socket and the IB server socket? Not sure I get the ( 0 = id%50) syntax...

    So all in roughly, it looks like I need my own custom wrapper passed to a 'socket connection' object of type EClientL0? And therefore need to study TwsApiL0.h file carefully to know how to implement the wrapper and use it in my main?

    If you code expert marksmen can spare a thought or two, would be great to know if I'm on the right path...
     
    Last edited: Mar 12, 2019
    #41     Mar 12, 2019
  2. Maverick1

    Maverick1

    #42     Mar 12, 2019
  3. I am not an expert in C++ but this Test.cpp looks rather similar to how code in Java would look like.
    Indeed is a connection made to port 7496, which is the default port.
    The if-statements that you refer to are nested in a while-loop. This while loop has a counter id which starts at 0 and counts up to 1000. During several of the counts are individual functions being tested. Some are supposed to give you some result, whereas others are supposed to give you an error message.
    In Java does the % in id%50 stand for modulo. So "0 = id%50" is a fancy way of saying that if id is a multiple of 50 it should run reqMktData. I guess it is similar in C++?
    https://github.com/JanBoonen/TwsApiCpp/blob/master/TwsApiC++/Test/Src/Test.cpp
     
    #43     Mar 12, 2019
    Maverick1 likes this.
  4. ph1l

    ph1l

    MyEWrapper inherits from EWrapperL0 which, according to TwsApilL0.h, in turn extends EWrapper; so the end-user basically needs to create a wrapper that wraps around another wrapper?
    Yes. It looks like you can look at the various MyEWrapper classes to see what they do in their callback methods.
    TwsApiC++/Test/Src/Test.cpp
    29 class MyEWrapper: public EWrapperL0
    TwsApiC++/Test/Src/History.cpp
    14 class MyEWrapper: public EWrapperL0
    TwsApiC++/Test/Src/Bars.cpp
    39 class MyEWrapper: public EWrapperL0
    TwsApiC++/Test/Src/Clients.cpp
    26 class MyEWrapper: public EWrapperL0

    I don't quite get the 'boolCalledFromThread = true' syntax:
    The "= true" means the default value is true. For what it means,
    TwsApiC++/Api/TwsApiL0.h
    195 // When non threaded, one must call checkMessages periodically.

    with the port number it looks like (7496?)
    source/PosixClient/src/EPosixClientSocket.cpp
    60 sa.sin_port = htons( port);
    64 if( (connect( m_fd, (struct sockaddr *) &sa, sizeof( sa))) < 0) {

    Looks like the port to me too. < 0 means there was an error. The then part of this if doesn't look like it logs what the error was, but at least appears to try to avoid a file descriptor leak.

    Not sure I get the ( 0 = id%50) syntax
    TwsApiC++/Test/Src/Test.cpp
    310 if( 0 == id%50)
    311 TEST(id, EC->reqMktData( id, C, "", false ) );

    It means every 50 iterations, starting with iteration 50, send a request market data.

    it looks like I need my own custom wrapper passed to a 'socket connection' object of type EClientL0? And therefore need to study TwsApiL0.h
    Yes, but it's probably easier to look at the other MyEWrapper examples first. If you really want to know what happens when an EC object receives data (e.g., when methods in your EWrapperL0 implementation get called) , you could look at
    source/PosixClient/Shared/EClientSocketBaseImpl.h
    2783 int EClientSocketBase:: ProcessMsg(const char*& beginPtr, const char* endPtr)
    2784 {
    2785 // process a single message from the buffer;
    2786 // return number of bytes consumed
    ...
    4156 }

     
    #44     Mar 12, 2019
    Maverick1 likes this.
  5. Maverick1

    Maverick1

    Fantastic, thanks much!
     
    #45     Mar 12, 2019
  6. Maverick1

    Maverick1

    Ph1l, can you (or anyone) explain the following from the EWrapperL0 class implementation in TwsApiL0.h:

    [ // lines 199-203:

    EWrapperL0( bool CalledFromThread = true ): m_CalledFromThread( CalledFromThread ) {}

    bool IsCalledFromThread( void ) { return m_CalledFromThread; }

    protected:
    bool m_CalledFromThread;

    ]


    and the corresponding constructor in the MyEWrapper class implementation:

    [ // line 32 in test.cpp:

    public:

    MyEWrapper( bool CalledFromThread = true ): EWrapperL0( CalledFromThread ) {}

    ]

    Shouldn't line 199 be:

    EWrapperL0( bool CalledFromThread = true ): m_CalledFromThread( m_CalledFromThread ) {}

    Also, I get that he's passing a Boolean set to true to his EWrapperL0 constructor, but he lost me at m_CalledFromThread and IsCalledfromThread: how do they relate? IsCalledfromThread only appears in a commented out comment at line 306 in test.cpp
     
    Last edited: Mar 13, 2019
    #46     Mar 13, 2019
  7. ph1l

    ph1l

    Ph1l, can you (or anyone) explain the following from the EWrapperL0 class implementation in TwsApiL0.h:
    [ // lines 199-203:

    TwsApiC++/Api/TwsApiL0.h
    199 EWrapperL0( bool CalledFromThread = true ): m_CalledFromThread( CalledFromThread ) {}
    200 bool IsCalledFromThread( void ) { return m_CalledFromThread; }
    201
    202 protected:
    203 bool m_CalledFromThread;


    It means the constructor for the EWrapperL0 class takes a single bool argument with parameter name CalledFromThread and default value true.
    The constructor initializes the data member m_CalledFromThread with the value of CalledFromThread.

    Shouldn't line 199 be:

    EWrapperL0( bool CalledFromThread = true ): m_CalledFromThread( m_CalledFromThread ) {}

    No. This would initialize data member m_CalledFromThread with the current value of m_CalledFromThread which is undefined (has not been initialized yet).

    Also, I get that he's passing a Boolean set to true to his EWrapperL0 constructor, but he lost me at m_CalledFromThread and IsCalledfromThread: how do they relate? IsCalledfromThread only appears in a commented out comment at line 306 in test.cpp

    TwsApiC++/Test/Src/Test.cpp
    306 // if( !MW.IsCalledFromThread() ) EC->checkMessages();

    If it was uncommented out, the call to MW.IsCalledFromThread() would call the IsCalledFromThread method in the base class:
    TwsApiC++/Api/TwsApiL0.h
    200 bool IsCalledFromThread( void ) { return m_CalledFromThread; }

    which returns the value of the m_CalledFromThread data member. So if m_CalledFromThread is false, the checkMessages() method would be called. But MW used the default constructor:
    TwsApiC++/Test/Src/Test.cpp
    240 MyEWrapper MW;

    And the default constructor gets EWrapperL0::m_CalledFromThread set to true:
    TwsApiC++/Test/Src/Test.cpp
    29 class MyEWrapper: public EWrapperL0
    30 {
    31 public:
    32 MyEWrapper( bool CalledFromThread = true ): EWrapperL0( CalledFromThread ) {}

    So the call to EC->checkMessages() wouldn't be needed because the intent is background thread would do that for you:
    TwsApiC++/Src/TwsApiL0.cpp
    332 #ifdef WIN32
    333 int err = _beginthread( ThreadMain, 2*8192, this );
    ...
    340 #else
    341 pthread_t thr;
    342 int err = pthread_create(&thr, 0, (void *(*)(void *)) ThreadMain, this);
    ...
    504 void ThreadMain( void* pEClient )
    505 {
    506 _TRY_ ((EClientL0Impl*)pEClient)->checkMessagesLoop(); _CATCH_
     
    #47     Mar 14, 2019
    Maverick1 likes this.
  8. Maverick1

    Maverick1

    Ph1l,

    Just now having some time to stare at your notes for a while... You're the kind of guy I'd put in charge of fixing the Boeing 737 Max! Thanks for being a class-act (rare thing on ET!)

    Ok, I got it I think: so MyEWrapper constructor is calling the EWrapperL0 constructor (because MyEWrapper is derived from EWrapperL0). EWrapperL0 constructor already has CalledFromThread initialized to "True". Also, the MyEWrapper constructor is a default constructor since it is not initializing any member data belonging to EWrapperL0 constructor.

    EC->checkMessages() doesn't run in test.cpp because "intent is background thread would do that for you"

    By "background thread would do that for you" do you mean that there's a process running in the background in TwsApiC++/Src/TwsApiL0.cpp?

    What is that process doing exactly? (I presume lines 332-333, 340-342, 505-506 that you highlighted above) What are these lines doing?

    Not to mention also that some of the syntax is just terrifying, for example:

    int err = pthread_create(&thr, 0, (void *(*)(void *)) ThreadMain, this);
     
    #48     Mar 18, 2019
  9. ph1l

    ph1l

    What is that process doing exactly? (I presume lines 332-333, 340-342, 505-506 that you highlighted above) What are these lines doing?
    TwsApiC++/Src/TwsApiL0.cpp
    332 #ifdef WIN32
    333 int err = _beginthread( ThreadMain, 2*8192, this );
    ...
    340 #else
    341 pthread_t thr;
    342 int err = pthread_create(&thr, 0, (void *(*)(void *)) ThreadMain, this);

    These lines create the new thread either under Windows (when WIN32 is #defined at compile time) or using pthreads (Windows with a pthread library, Unix, or Linux).
    The Windows thread has a stack size of 2*8192 bytes, and the pthread uses default arguments (including some default stack size).

    The created thread is not a separate process. The difference is the thread has access to the memory in the process it was started from, but a separate process would not.

    The threads run concurrently wth other threads in the process on a single-core computer or simultaneously with other threads on a multi-core or multi-CPU computer. There is a subtle difference between concurrently and simultaneously, but it probably won't matter for this API.

    The created thread runs the ThreadMain function which gets an EClientL0Impl pointer (this) as the argument.

    https://docs.microsoft.com/en-us/cp...erence/beginthread-beginthreadex?view=vs-2017
    and
    http://man7.org/linux/man-pages/man3/pthread_create.3.html
    have more details about _beginthread and pthread_create. You probably don't need to study them.

    some of the syntax is just terrifying
    The ugly (void *(*)(void *)) cast is because pthread_create() wants a pointer to a C function that has a single void * paramter and returns a void *. It returns void * to support sending information to another thread that joins this one after this one returns (not applicable to TwsApiL0). The cast is needed here because ThreadMain has return type void (what _beginthread() wants) and not void *.

    ThreadMain() calls EClientL0Impl::checkMessagesLoop() which tries to process incoming messages and/or send data waiting to be sent in a loop as long as the connection stays up.
    TwsApiC++/Src/TwsApiL0.cpp
    506 _TRY_ ((EClientL0Impl*)pEClient)->checkMessagesLoop(); _CATCH_
    ...
    484 void checkMessagesLoop ( void )
    485 {
    ...
    489 while( isSocketOK() && isConnected() && m_EWrapperL0Impl.IsEnableCalls() )
    490 {
    491 checkMessagesOnce(1); // the minimal time possible to wait is enough
    492 } // to prevent this loop using 100% of the cpu

    451 bool checkMessagesOnce( long waitfor = 0 )
    452 {
    ...
    462 struct timeval timeout = {0,waitfor}; // wait for some milli/micro seconds
    463 int s = select( SH+1, &ReadSet, &WriteSet, &ErrorSet, &timeout );
    ...
    472 if( FD_ISSET(SH, &WriteSet) && isSocketOK() ) // socket is ready for writing
    473 onSend();
    474
    475 if( FD_ISSET(SH, &ReadSet ) && isSocketOK() ) // socket is ready for reading
    476 return EPosixClientSocket::checkMessages();


    These sockets are two-way connections, so data is sent and received on the same socket.

    source/PosixClient/src/EPosixClientSocket.cpp
    174 void EPosixClientSocket::onSend()
    175 {
    ...
    179 sendBufferedData();


    Example of control flow for sending data:
    TwsApiC++/Test/Src/History.cpp
    77 C.symbol = "MSFT";
    ...
    131 EC->reqHistoricalData
    132 ( 20
    133 , C
    134 , EndDateTime(EDTY,EDTM,EDTD) // Attention: for IB, this means last day will be 2013,02,19
    ...


    TwsApiC++/Src/TwsApiL0.cpp
    109 class EWrapperL0Impl: public EWrapperL0
    ...
    657 void reqHistoricalData ( TickerId id, const Contract &contract, const IBString &endDateTime, const IBString &durationStr, const IBString &barSizeSetting, const IBString &whatToShow, int useRTH, int formatDate, const TagValueListSPtr& chartOptions)
    ...
    659 EC.reqHistoricalData ( id, contract, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH, formatDate, chartOptions);


    source/PosixClient/Shared/EClientSocketBaseImpl.h
    758 void EClientSocketBase::reqHistoricalData( TickerId tickerId, const Contract &contract,
    ...
    787 ENCODE_FIELD( REQ_HISTORICAL_DATA);
    ...
    795 ENCODE_FIELD( contract.symbol);
    ...
    852 bufferedSend( msg.str());


    Example of control flow for receiving data
    source/PosixClient/Shared/EClientSocketBaseImpl.h
    2696 bool EClientSocketBase::checkMessages()
    2697 {
    ...
    2710 while( (m_connected ? processMsg( ptr, endPtr)
    ...
    2783 int EClientSocketBase::processMsg(const char*& beginPtr, const char* endPtr)
    2784 {
    2785 // process a single message from the buffer;
    2786 // return number of bytes consumed
    ...
    2797 switch( msgId) {
    ...
    3713 case HISTORICAL_DATA:
    ...
    3754 m_pEWrapper->historicalData( reqId, bar.date, bar.open, bar.high, bar.low,


    TwsApiC++/Test/Src/History.cpp
    14 class MyEWrapper: public EWrapperL0
    ...
    34 virtual void historicalData( TickerId reqId, const IBString& date, double open, double high, double low, double close, int volume, int barCount, double WAP, int hasGaps )
    ...
    42 fprintf( stdout, "%10s, %5.3f, %5.3f, %5.3f, %5.3f, %7d\n", (const char*)date, open, high, low, close, volume );
     
    #49     Mar 19, 2019