1

Hi I have tried the below code to get IBPy to give me the last price for a list of securities then save these prices to a csv

from ib.opt import Connection
from ib.ext.Contract import Contract
import time
import csv

Equity = Contract()
Equity.m_secType = 'Stk'
Equity.m_exchange = 'Smart'
Equity.m_currency = 'USD'

EquityList = ['XOM', 'JNJ', 'BRK B', 'JPM','GE','T','WFC','BAC','PG','CVX','VZ','PFE','MRK','HD','C','KO','DIS','V','UNH','PEP','PM','IBM','MO','SLB','ORCL','MMM','MDT','MA','WMT','MCD','ABBV','BMY','BA','HON','CVS','SPY']
PriceList = []
PriceData = csv.writer(open('price.csv','wb'))

def savepx(msg):
   global px
   if msg.field == 4:
     px = msg.price

def main():
   conn = Connection.create(port=7496,clientId=100)
   conn.connect()
   count = 0

   for ticker in EquityList:
      Equity.m_symbol = ticker
      conn.register(savepx,'TickPrice')
      conn.reqMktData(count,Equity,225,False)
      time.sleep(.15)
      conn.cancelMktData(count)
      PriceList.insert(count,px)
      count = count + 1

conn.disconnect()
PriceData.writerow(EquityList)
PriceData.writerow(PriceList)

When I use this code it begins getting data for the list of equities I've provided, but eventually gets caught on a single ticker where it repeats the price for the next several tickers. This happens sporadically throughout the list, but for example on one run it gave the price of SLB as 80.63(correct) then simply repeated the price of 80.63 for for the rest of the equities in the list somehow not updated the variable px to new values for the new tickers. Each time I run this this always seems to happen somewhere in the list where correct data is pulled for a ticker and then several subsequent tickers have the same value. Any ideas on how to fix this or a different way to pull real time data from IB that avoids this issue for a list of equities?

brian
  • 10,619
  • 4
  • 21
  • 79
Darth
  • 11
  • 1

1 Answers1

0

You're counting on the assumption that the data will arrive within .15 seconds and in the same order it was asked for. You have a tickerId in the callback that will tell you which security the msg is for.

def savepx(msg):
   #global px don't use this
   if msg.field == 4:
     PriceList.insert(msg.tickerId,msg.price)

Notice XOM is requested with count = 0 so when the msg arrives it will have tickerId = 0, in this case you're using it for the index as well.

You can remove some code from the loop

for ticker in EquityList:
      Equity.m_symbol = ticker
      conn.register(savepx,'TickPrice')# move this out of loop, just do it once
      conn.reqMktData(count,Equity,225,True)#true snapshot
      #time.sleep(.15) #not needed unless over 50 messages per second
      #conn.cancelMktData(count) don't do this, use snapshot 
      #PriceList.insert(count,px) do in callback
      count = count + 1

Then don't disconnect until all data has been received or some timeout setting.

Look here for a more complete example https://stackoverflow.com/a/30157553/2855515

Community
  • 1
  • 1
brian
  • 10,619
  • 4
  • 21
  • 79