├── .gitignore ├── HistDataRetrieval.py ├── README ├── dataAq.py ├── getHistOpt.py ├── getRealTimeData.py ├── mainDataAq.py ├── mainGetHistOpt.py └── others ├── getVixOptChain.py ├── histData.py ├── mainHistData.py └── testib.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py.swp 2 | __p* 3 | *.dat 4 | *.list 5 | -------------------------------------------------------------------------------- /HistDataRetrieval.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | from ib.ext.Contract import Contract 3 | from ib.opt import ibConnection, message 4 | 5 | def price_tick_handler(msg): 6 | print msg 7 | 8 | 9 | tws = ibConnection() 10 | tws.register(price_tick_handler, message.tickPrice) 11 | tws.connect() 12 | 13 | c = Contract 14 | c.m_symbol = "SPY" 15 | c.m_secType = "STK" 16 | c.m_exchange = "SMART" 17 | c.m_currency = "USD" 18 | 19 | tws.reqMktData(1, c, "", False) 20 | 21 | sleep(10) 22 | 23 | print "all done" 24 | 25 | tws.disconnect() 26 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wcant/ib-options/724d5805ccf5b124da0baa9b89b4034c08b8e2bf/README -------------------------------------------------------------------------------- /dataAq.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python2.7 2 | 3 | #IbPy 4 | import ib 5 | from ib.ext.Contract import Contract 6 | from ib.opt import ibConnection, message 7 | 8 | #StdLib 9 | import logger 10 | import os 11 | import datetime as dt 12 | from time import sleep,strftime 13 | 14 | 15 | def makeContract(symbol, derivative, exchange, expiration = None, 16 | strike = None, call_put = None, currency = "USD", 17 | tradingClass = None, multiplier = None): 18 | contract = Contract() 19 | contract.m_symbol = symbol 20 | contract.m_secType = derivative 21 | contract.m_exchange = exchange 22 | contract.m_currency = currency 23 | if derivative == "OPT": 24 | contract.m_expiry = expiration 25 | contract.m_strike = strike 26 | contract.m_right = call_put 27 | contract.m_multiplier = multiplier 28 | contract.m_tradingClass = tradingClass 29 | if derivative == "FUT": 30 | contract.m_expiry = expiration 31 | 32 | return contract 33 | 34 | class Downloader(): 35 | def __init__(self): 36 | """__init__ passes the object its first parameters.""" 37 | self.con = ibConnection() 38 | self.con.register(self.tickPriceHandler, 'TickPrice') 39 | self.con.registerAll(self.listener) 40 | self.con.connect() 41 | self.tickID = 1 42 | self.recordFile = open('aapl_100.dat', 'a') 43 | #self.genericTicklist = [233,221,106,104] 44 | 45 | def listener(self, msg): 46 | print(msg) 47 | #self.recordFile.write(str(msg)+"\n"+strftime("%Y-%m-%d %H:%M:%S")) 48 | 49 | def getContractDetails(self, contract): 50 | #Only accepts Symbol,SecType,Exch,Currency 51 | self.con.reqContractDetails(contract) 52 | 53 | def disconnect(self): 54 | self.con.disconnect() 55 | self.recordFile.close() 56 | self.symbols.close() 57 | 58 | data = {} 59 | def tickPriceHandler(self, msg): 60 | #Tick value of 4 refers to Last Price 61 | if msg.field == 4: 62 | #tickerId was previously specified in the call to reqMktData() 63 | self.data[msg.tickerId] = msg.price 64 | 65 | def getSpotTick(self, contract): 66 | self.symbols.close() 67 | self.con.reqMktData(self.tickID, contract,'', False) 68 | self.tickID += 1 69 | -------------------------------------------------------------------------------- /getHistOpt.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python2.7 2 | 3 | #IbPy 4 | import ib 5 | from ib.ext.Contract import Contract 6 | from ib.opt import ibConnection, message 7 | 8 | #StdLib 9 | import logger 10 | import os 11 | import datetime as dt 12 | from time import sleep,strftime 13 | 14 | class Downloader(): 15 | def __init__(self): 16 | """__init__ passes the object its first parameters.""" 17 | self.con = ibConnection() 18 | self.con.register(self.tickPriceHandler, 'TickPrice') 19 | self.con.registerAll(self.listener) 20 | self.con.connect() 21 | self.tickID = 1 22 | self.recordFile = open('aapl_100.dat', 'a') 23 | #self.genericTicklist = [233,221,106,104] 24 | 25 | def listener(self, msg): 26 | print(msg) 27 | self.recordFile.write(str(msg)+"\n"+strftime("%Y-%m-%d %H:%M:%S")) 28 | 29 | 30 | 31 | def disconnect(self): 32 | self.con.disconnect() 33 | 34 | data = {} 35 | def tickPriceHandler(self, msg): 36 | #Tick value of 4 refers to Last Price 37 | if msg.field == 4: 38 | #tickerId was previously specified in the call to reqMktData() 39 | self.data[msg.tickerId] = msg.price 40 | 41 | def getSpotTick(self, contract): 42 | self.con.reqMktData(self.tickID, contract,'', False) 43 | self.tickID += 1 44 | 45 | def makeContract(symbol, derivative, exchange, expiration = None, strike = None, call_put = None, currency = "USD", tradingClass = None, multiplier = None): 46 | contract = Contract() 47 | contract.m_symbol = symbol 48 | contract.m_secType = derivative 49 | contract.m_exchange = exchange 50 | contract.m_currency = currency 51 | if derivative == "OPT": 52 | contract.m_expiry = expiration 53 | contract.m_strike = strike 54 | contract.m_right = call_put 55 | contract.m_multiplier = multiplier 56 | contract.m_tradingClass = tradingClass 57 | if derivative == "FUT": 58 | contract.m_expiry = expiration 59 | 60 | return contract 61 | 62 | # def reset(self): 63 | # self._log.debug('Resetting data') 64 | # self.dataReady = False 65 | # self._timestamp = [] 66 | # self.data = {'open':[],'high':[],'low':[],'close':[], 67 | # 'volume':[],'count':[],'WAP':[]} 68 | 69 | dl = Downloader() 70 | 71 | opt = makeContract("AAPL", "OPT", "SMART", "20140829", 100, "C", multiplier=100) 72 | dl.getSpotTick(opt) 73 | #strikes = [i/5.0 for i in range(150, 250)] 74 | #for strike in strikes: 75 | # vixOpt = makeContract("SPY", "OPT", "CBOE", '20141017', 76 | # strike, "C") 77 | # dl.getSpotTick(vixOpt) 78 | #sleep(5) 79 | 80 | #for i, strike in enumerate(strikes): 81 | # if i in dl.data.keys(): 82 | # print(strike, dl.data[i]) 83 | #dl.disconnect() 84 | 85 | -------------------------------------------------------------------------------- /getRealTimeData.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | from ib.ext.Contract import Contract 3 | from ib.opt import ibConnection, message 4 | 5 | def price_tick_handler(msg): 6 | print msg 7 | 8 | 9 | tws = ibConnection() 10 | tws.register(price_tick_handler, message.tickPrice) 11 | tws.connect() 12 | 13 | c = Contract 14 | c.m_symbol = "SPY" 15 | c.m_secType = "STK" 16 | c.m_exchange = "SMART" 17 | c.m_currency = "USD" 18 | 19 | tws.reqMktData(1, c, "", False) 20 | 21 | sleep(10) 22 | 23 | print "all done" 24 | 25 | tws.disconnect() 26 | -------------------------------------------------------------------------------- /mainDataAq.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python2.7 2 | 3 | #IB 4 | import dataAq as daq 5 | import datetime as dt 6 | 7 | #STDLIB 8 | from time import sleep,strftime 9 | 10 | dl = daq.Downloader() 11 | 12 | symbols = [] 13 | with open('symbols.list', 'r') as f: 14 | for line in f: 15 | symbols.append(line.rstrip()) 16 | 17 | def getSecType(symbol): 18 | if symbol.isalpha(): 19 | return 'OPT' 20 | else: 21 | return 'FUT' 22 | 23 | def getDetails(symbol, derivative): 24 | contract = daq.Contract() 25 | contract.m_symbol = symbol 26 | dl.getContractDetails(1,symbol) 27 | 28 | #Build Dictionaries for each underlying 29 | #Contracts for each strike will be built 30 | meta = {} 31 | for s in symbols: 32 | meta[s] = {} 33 | derivative = getSecType(s) 34 | meta[s]['secType'] = derivative 35 | 36 | #opt = makeContract("AAPL", "OPT", "SMART", "20140829", 100, "C", multiplier=100) 37 | #dl.getSpotTick(opt) 38 | 39 | #strikes = [i/5.0 for i in range(150, 250)] 40 | #for strike in strikes: 41 | # vixOpt = makeContract("SPY", "OPT", "CBOE", '20141017', 42 | # strike, "C") 43 | # dl.getSpotTick(vixOpt) 44 | #sleep(5) 45 | 46 | #for i, strike in enumerate(strikes): 47 | # if i in dl.data.keys(): 48 | # print(strike, dl.data[i]) 49 | #dl.disconnect() 50 | -------------------------------------------------------------------------------- /mainGetHistOpt.py: -------------------------------------------------------------------------------- 1 | import getHistOpt 2 | 3 | dir(getHistOpt) 4 | -------------------------------------------------------------------------------- /others/getVixOptChain.py: -------------------------------------------------------------------------------- 1 | import time 2 | from ib.ext.Contract import Contract 3 | from ib.ext.Order import Order 4 | from ib.ext.TickType import TickType 5 | from ib.opt import ibConnection, message 6 | 7 | class DataGetter(): 8 | def __init__(self): 9 | self.con = ibConnection() 10 | self.con.register(self.tickPriceHandler, 'TickPrice') 11 | self.con.registerAll(self.watcher) 12 | self.con.connect() 13 | self.tickID = 1 14 | 15 | def watcher(self, msg): 16 | print msg 17 | 18 | def disconnect(self): 19 | self.con.disconnect() 20 | 21 | data = {} 22 | def tickPriceHandler(self, msg): 23 | if msg.field == 4: 24 | self.data[msg.tickerId] = msg.price 25 | 26 | def getSpotTick(self, contract): 27 | self.con.reqMktData(self.tickID, contract, '', True) 28 | self.tickID += 1 29 | 30 | 31 | def makeContract(symbol, derivative, exchange, expiration = None, 32 | strike = None, call_put = None, currency = "USD"): 33 | contract = Contract() 34 | contract.m_symbol = symbol 35 | contract.m_secType = derivative 36 | contract.m_exchange = exchange 37 | contract.m_currency = currency 38 | if derivative == "OPT": 39 | contract.m_expiry = expiration 40 | contract.m_strike = strike 41 | contract.m_right = call_put 42 | if derivative == "FUT": 43 | contract.m_expiry = expiration 44 | 45 | return contract 46 | 47 | 48 | # here the data retrieval starts 49 | dg = DataGetter() 50 | 51 | strikes = [i/2.0 for i in range(20, 100)] 52 | for strike in strikes: 53 | vixOpt = makeContract("VIX", "OPT", "CBOE", '20140819', strike, "C") 54 | dg.getSpotTick(vixOpt) 55 | 56 | time.sleep(5) 57 | 58 | for i, strike in enumerate(strikes): 59 | if i in dg.data.keys(): 60 | print strike, dg.data[i] 61 | 62 | dg.disconnect() 63 | -------------------------------------------------------------------------------- /others/histData.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 8, 2013 3 | Copyright: Jev Kuznetsov 4 | License: BSD 5 | 6 | Module for downloading historic data from IB 7 | 8 | ''' 9 | 10 | import ib 11 | import pandas as pd 12 | from ib.ext.Contract import Contract 13 | from ib.opt import ibConnection, message 14 | 15 | import logger as logger 16 | 17 | from pandas import DataFrame, Index 18 | 19 | import os 20 | import datetime as dt 21 | import time 22 | from time import sleep 23 | from extra import timeFormat, dateFormat 24 | 25 | class Downloader(object): 26 |     def __init__(self,debug=False): 27 | self._log = logger.getLogger('DLD')         28 | self._log.debug('Initializing data downloader. Pandas version={0}, ibpy version:{1}'.format(pd.__version__,ib.version)) 29 | self.tws = ibConnection() 30 | self._dataHandler = _HistDataHandler(self.tws) 31 |         32 | if debug: 33 | self.tws.registerAll(self._debugHandler) 34 | self.tws.unregister(self._debugHandler,message.HistoricalData) 35 | 36 | self._log.debug('Connecting to tws') 37 | self.tws.connect() 38 |         39 | self._timeKeeper = TimeKeeper() # keep track of past requests 40 | self._reqId = 1 # current request id 41 |       42 |         43 | def _debugHandler(self,msg): 44 | print '[debug]', msg 45 |     46 | def requestData(self,contract,endDateTime,durationStr='1 D',barSizeSetting='30 secs',whatToShow='TRADES',useRTH=1,formatDate=1):   47 | 48 | if isinstance(endDateTime,dt.datetime): # convert to string 49 | endDateTime = endDateTime.strftime(timeFormat) 50 | 51 | self._log.debug('Requesting data for %s end time %s.' % (contract.m_symbol,endDateTime)) 52 |         53 | while self._timeKeeper.nrRequests(timeSpan=600) > 59: 54 | print 'Too many requests done. Waiting... ' 55 | time.sleep(10) 56 | 57 | self._timeKeeper.addRequest() 58 | self._dataHandler.reset() 59 | self.tws.reqHistoricalData(self._reqId,contract,endDateTime,durationStr,barSizeSetting,whatToShow,useRTH,formatDate) 60 | self._reqId+=1 61 |     62 | #wait for data 63 | startTime = time.time() 64 | timeout = 3 65 | while not self._dataHandler.dataReady and (time.time()-startTime < timeout): 66 | sleep(2) 67 | 68 | if not self._dataHandler.dataReady: 69 | self._log.error('Data timeout')     70 |           71 | print self._dataHandler.data 72 |         73 | return self._dataHandler.data   74 |     75 | #     def getIntradayData(self,contract, dateTuple ): 76 | #         ''' get full day data on 1-s interval 77 | #             date: a tuple of (yyyy,mm,dd) 78 | #         ''' 79 | #         80 | #         openTime = dt.datetime(*dateTuple)+dt.timedelta(hours=16) 81 | #         closeTime =  dt.datetime(*dateTuple)+dt.timedelta(hours=22) 82 | #         83 | #         timeRange = pd.date_range(openTime,closeTime,freq='30min') 84 | #         85 | #         datasets = [] 86 | #         87 | #         for t in timeRange: 88 | #             datasets.append(self.requestData(contract,t.strftime(timeFormat))) 89 | #         90 | #         return pd.concat(datasets) 91 |         92 |     93 | def disconnect(self): 94 | self.tws.disconnect()     95 | 96 | class _HistDataHandler(object): 97 | ''' handles incoming messages ''' 98 | def __init__(self,tws): 99 | self._log = logger.getLogger('DH') 100 | tws.register(self.msgHandler,message.HistoricalData) 101 | self.reset() 102 |     103 | def reset(self): 104 | self._log.debug('Resetting data') 105 | self.dataReady = False 106 | self._timestamp = [] 107 | self._data = {'open':[],'high':[],'low':[],'close':[],'volume':[],'count':[],'WAP':[]} 108 |     109 | def msgHandler(self,msg): 110 | #print '[msg]', msg 111 |         112 | if msg.date[:8] == 'finished': 113 | self._log.debug('Data recieved') 114 | self.dataReady = True 115 | return 116 |         117 | if len(msg.date) > 8: 118 | self._timestamp.append(dt.datetime.strptime(msg.date,timeFormat)) 119 | else: 120 | self._timestamp.append(dt.datetime.strptime(msg.date,dateFormat)) 121 |                         122 |             123 | for k in self._data.keys(): 124 | self._data[k].append(getattr(msg, k)) 125 |     126 | @property 127 | def data(self): 128 | ''' return  downloaded data as a DataFrame ''' 129 | df = DataFrame(data=self._data,index=Index(self._timestamp)) 130 | return df 131 |     132 | 133 |         134 | class TimeKeeper(object): 135 | ''' 136 | class for keeping track of previous requests, to satify the IB requirements 137 | (max 60 requests / 10 min) 138 | 139 | each time a requiest is made, a timestamp is added to a txt file in the user dir. 140 | 141 | ''' 142 |     143 | def __init__(self): 144 | self._log = logger.getLogger('TK') 145 | dataDir = os.path.expanduser('~')+'/twpData' 146 |         147 | if not os.path.exists(dataDir): 148 | os.mkdir(dataDir) 149 | 150 | self._timeFormat = "%Y%m%d %H:%M:%S" 151 | self.dataFile = os.path.normpath(os.path.join(dataDir,'requests.txt')) 152 | self._log.debug('Data file: {0}'.format(self.dataFile)) 153 |         154 | def addRequest(self): 155 | ''' adds a timestamp of current request''' 156 | with open(self.dataFile,'a') as f: 157 | f.write(dt.datetime.now().strftime(self._timeFormat)+'\n') 158 |             159 | 160 | def nrRequests(self,timeSpan=600): 161 | ''' return number of requests in past timespan (s) ''' 162 | delta = dt.timedelta(seconds=timeSpan) 163 | now = dt.datetime.now() 164 | requests = 0 165 |         166 | with open(self.dataFile,'r') as f: 167 | lines = f.readlines() 168 |             169 | for line in lines: 170 | if now-dt.datetime.strptime(line.strip(),self._timeFormat) < delta: 171 | requests+=1 172 |     173 | if requests==0: # erase all contents if no requests are relevant 174 | open(self.dataFile,'w').close() 175 |             176 | self._log.debug('past requests: {0}'.format(requests)) 177 | return requests 178 | 179 | -------------------------------------------------------------------------------- /others/mainHistData.py: -------------------------------------------------------------------------------- 1 | import tradingWithPython as twp 2 | 3 | #---check for correct version 4 | print 'twp version', twp.__version__ 5 | assert twp.__version__ >= '0.0.6', 'Your twp distribution is too old, please update' 6 | 7 | from tradingWithPython.lib.interactiveBrokers import histData, createContract 8 | 9 | 10 | dl = histData.Downloader(debug=True) # historic data downloader class 11 | 12 | contract = createContract('SPY') # create contract using defaults (STK,SMART,USD) 13 | data = dl.requestData(contract,"20130508 16:00:00 EST") # request 30-second data bars up till now 14 | 15 | data.to_csv('SPY.csv') # write data to csv 16 | 17 | print 'Done' 18 | 19 | -------------------------------------------------------------------------------- /others/testib.py: -------------------------------------------------------------------------------- 1 | from ib.opt import ibConnection, message 2 | 3 | def my_account_handler(msg): 4 | 5 | 6 | 7 | 8 | 9 | def my_tick_handler(msg): 10 | 11 | 12 | 13 | 14 | connection = ibConnection() 15 | connection.register(my_account_handler, 'UpdateAccountValue') 16 | connection.register(my_tick_handler, 'TickSize', 'TickPrice') 17 | connection.connect() 18 | connection.reqAccountUpdates( ) 19 | --------------------------------------------------------------------------------