iklan header

Getting prices out of the IB API with swigibpy / python

NOTE:

There is now a local python API for interactive brokers. An updated version of this submit using the local API may be determined here

Okay so you have controlled to run the time telling code in my last publish.

Now we are able to do some thing a bit more exciting, get a few market fees. Arguably it's far nonetheless now not that exciting, and these items will in no way be as exciting as a respectable ebook or a very good bottle of crimson wine, but we've all were given to get the money to buy the ones books and bottles and this is better than many other alternatives for reaching that.

Let us peruse the IB ABI commands...

Whenever you are trying something new out with the API you need to identify the EClientSocket (command to ask the server for stuff) and EWrapper (command run by the wrapper client when stuff is presented unto it) functions. So Reading The Frigging Manual (to be precise the C++ section) is worth doing.

And indeed there isn't simply one but four locations inside the weird and mysterious world of EClientSocket wherein it looks like charges may be located:

  • Market Data
  • Historical Data
  • Real Time Bars
  • Market Depth

Market Data: Returns a stream of price ticks (updated quotes and trades). Because it is a stream you have to ask for it, and then ask for it to stop lest you be buried under a huge pile of ticks. It is level 1, eg 'top of the order book' data.

Historical Data: Returns a one off chunk of data, both prices and volumes, with a given look back history and frequency.

Real Time Bars: Returns a stream of averages of the trades (or bid, ask, midpoint) over an interval, currently only 5 seconds. So its kind of like pre-clumped tick data arriving at regular intervals. Its a stream, so you have to ask for it... you get the idea.

Market Depth: Returns a stream of updates to the order book, both prices and size. This requires a requires a level 2 subscription. Its a stream...!

Because real time bars, market data and market depth deliver very similar information I won't discuss them all (and since I am a tightwad I don't have any Level 2 data subscriptions!). In this post we'll go through the 'one shot' historical data; and in the next one we'll look at one kind of streaming data (market data).

Before we begin

You need to get some other python library, pandas. This should additionally get numpy (for numerical analysis) and matplotlib (for drawing first-rate photos) in case you did not have the ones on your python set up already.

Historical Data AKA Those Who Cannot Remember the Past Are Doomed...

First get the code from thisrepo somewhere on a server far far away... the files we'll be using today are test2_IB and wrapper_v2 (with a guest appearance from IButils.py).

 Getting some price information

Just run the test2_IB file (assuming you still have an IB connection available as per the previous post). You should get something like this:

close    high        low        open  volume

2013-12-12  6334.0  6338.5  6338.5  6338.5       1

2014-01-02  6610.5  6625.0  6625.0  6625.0       1

2014-01-06  6621.0  6632.5  6628.0  6632.5       8

2014-01-07  6644.5  6658.5  6632.0  6632.0       2

.....

2014-03-25  6537.0  6569.0  6467.0  6474.5  110350

2014-03-26  6544.5  6587.5  6498.5  6556.5  108996

2014-03-27  6530.5  6538.0  6502.0  6507.5   94293

2014-03-28  6555.0  6576.0  6527.5  6536.5   91171

2014-03-31  6569.0  6602.0  6556.5  6563.5   50112

Obviously those are the charges for the FTSE one hundred June 2014 futures agreement. If you get an blunders you may want to exchange the expiry date for the agreement. I'll show you the way to try this tommorrow.

(Note before blending those with any kind of other costs or doing proper backtesting I might personally append a 'fixed' cease of date timestamp to them eg 23:59:fifty nine to make certain there may be no mild look forward bias. This is mentioned more right here.)

The IB agreement item or How IB Knows What We Want

Some more code from the test2_IB file:

ibcontract = IBcontract()

    ibcontract.SecType = "FUT"

ibcontract.Expiry="201406"

ibcontract.Symbol="Z"

    ibcontract.Trade="LIFFE"

(Note if you acquire an errors above right here is your danger to change the expiry to the current one. So for instance as I'm revising this in July 2015 the subsequent quarterly FTSE expiry will be "201509".)

Here is another 'gotcha' - the IB contract object (when I say 'gotcha' it can be stuff I've literally spent days banging my metaphorical head against and in some cases my actual head). This is a complete description which identifies a particular thing you can trade. Most of the data you need is available from thehttps://www.interactivebrokers.com/ product listing pages. Some problems I have (there may be more associated with other asset classes) mainly in not giving enough information to uniquely identify a contract:

  • Getting the exchange name right - it needs to be exactly the same as on the product page.
  • Having to specify a currency. This seems to be a problem for CAC40 and AEX futures (specify ibcontract.currency="EUR") and silver (USD).
  • Having to specify a multiplier effectively contract movement in cash terms per price point (For CAC ibcontract.multiplier="10", AEX is 200 and SILVER is 5000).

  Note you don't need to specify the 'ConId' (a protracted meaningless wide variety) which modifications consistent with contract roll, thank goodness.

(By the manner I do not truely use this agreement item in the relaxation of my code. Instead I have some other elegance which includes extra beneficial facts, after which a convert_to_ibcontract characteristic. This feature handles the terrible unique cases above and also interprets among meaningless names like Z and better names like JohnBoy - my personal pet name for the FTSE100 destiny *).

(* This is a shaggy dog story)

There's truly even extra horribleness approximately those items but that is for another day.

All this is Fascinating Rob But How will we Actually get the Prices?!

Here is some code from the IB client object in wrapper_v2.py:

Def get_IB_historical_data(self, ibcontract, durationStr="1 Y", barSizeSetting="1 day", tickerid=MEANINGLESS_NUMBER):

        """

        Returns historic prices for a settlement, up to these days

        tws is a result of calling IBConnector()

        """

        today=datetime.Datetime.Now()

        self.Cb.Init_error()

        self.Cb.Init_historicprices(tickerid)

        # Request a few historical records.

        Self.Tws.ReqHistoricalData(

                tickerid,                                          # tickerId,

                ibcontract,                                   # contract,

                today.strftime("%Y%m%d %H:%M:%S %Z"),       # endDateTime,

                durationStr,                                      # durationStr,

                barSizeSetting,                                    # barSizeSetting,

                "TRADES",                                   # whatToShow,

                1,                                          # useRTH,

                1                                           # formatDate

            )

        start_time=time.Time()

        completed=False

        iserror=False

        at the same time as not completed and not iserror:

            completed=self.Cb.Flag_historicdata_finished

            iserror=self.Cb.Flag_iserror

            if (time.time() - start_time) > MAX_WAIT:

                iserror=True

            pass

        if iserror:

            print self.Cb.Error_msg

            improve Exception("Problem getting historic information")

        historicdata=self.Cb.Data_historicdata[tickerid]

        outcomes=historicdata.To_pandas("date")

        go back outcomes

The wellknown structure of this function must be apparent to every person who study the last put up. We:

  • call some init functions in the callback instance (self.cb) so there is somewhere for error messages and our price data to go
  • Ask the IB API server for something with tws.reqHistoricalData()
  • Wait patiently until a callback finished flag is set, or we get an error, or we get bored
  • Complain about an error, or return the results as appropriate

The tws.ReqHistoricalData() asks the server for historical price records. We can set duration of time (a year in this situation, even though there is unlikely to be that a good deal for a futures contract that rolls quarterly and in which no person trades the returned months, being like unhappy lonely people at a element that no person dances with) durationStr, the give up time, the bar length (in this case days; no longer honestly the size of the kind of bar you get liquids from) and some different things you could observe the documentation yourself to find out about. Just to be aware no longer all the combinations of term and bar period are authorized - you can't get second via 2nd costs for a yr (see this link.)

About the handiest issue that might not be apparent is tickerid. You might be the type of wild crazy individual who requests hundreds of ancient records for exceptional contracts. In which case you'll get statistics coming back randomly and you wouldn't realize which agreement it become for. So you need to provide a few kind of label for the request in case you request hundreds of things immediately. Note you can not certainly do that because in case you request greater than 1 set of records approximately every 10 seconds you get a 'pacing violation' (essentially, do not take the mickey).

Oh Yeah I recall now, we must have an EWrapper characteristic on the server aspect...

From the IBWrapper class in wrapper_v2:

Def init_historicprices(self, tickerid):

        if "data_historicdata" no longer in dir(self):

            histdict=dict()

        else:

            histdict=self.Data_historicdata

        histdict[tickerid]=EMPTY_HDATA

        setattr(self, "data_historicdata", histdict)

        setattr(self, "flag_historicdata_finished", False)

    def historicalData(self, reqId, date, openprice, excessive,

                       low, close, quantity,

                       barCount, WAP, hasGaps):

        if date[:8] == 'completed':

            setattr(self, "flag_historicdata_finished", True)

        else:

            historicdata=self.Data_historicdata[reqId]

            date=datetime.Datetime.Strptime(date,"%Y%m%d")

            historicdata.Add_row(date=date, open=openprice, high=high, low=low, near=close, volume=extent)

Essentially to write down this stuff you look inside the API reference to see what the wrapper feature returns. In this case the wrapper characteristic beastie is referred to as again and again with the same arguments for each row of statistics, earlier than you get one final and awesomely inelegant very last call to mention that we are finished. To catch up on this inelegance I use a little magnificence item in IButils.Py to tidily acquire the rows right into a pandas dataframe.

That then is the whole lot you want to realize approximately historic records. I will cowl market information, i.E. The notable international of streaming facts, in the next submit.

This is the second one in a chain of posts.

The preceding post become:

http://qoppac.Blogspot.Co.United kingdom/2014/03/the usage of-swigibpy-so-that-python-will-play.Html

The subsequent submit is:

http://qoppac.Blogspot.Co.Uk/2014/04/streaming-costs-from-ib-api-swigibpy.Html

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel