I am trying to use IBpy to return historical data from some instruments, but when I try the code in the documentation I get an empty result.
I managed to make it work using R Ibroker but I would really prefer to have it working using the Python API.
Here is the code I am testing.
from time import sleep, strftime
from time import sleep
from ib.ext.Contract import Contract
from ib.opt import ibConnection, message
def my_account_handler(msg):
print(msg)
def my_tick_handler(msg):
print(msg)
if __name__ == '__main__':
con = ibConnection()
con.register(my_account_handler, 'UpdateAccountValue')
con.register(my_tick_handler, message.tickSize, message.tickPrice)
con.connect()
def inner():
qqqq = Contract()
qqqq.m_secType = "CASH"
qqqq.m_symbol = "MSFT"
qqqq.m_currency = "USD"
qqqq.m_exchange = "IDEALPRO"
endtime = strftime('%Y%m%d %H:%M:%S')
con.reqHistoricalData(1,qqqq,endtime,"5 D","1 hour","MIDPOINT",1,1)
sleep(10)
inner()
sleep(5)
print('disconnected', con.disconnect())
Any idea what might be going wrong?
You need to register for the historical data message.
con.register(my_hist_data_handler, message.historicalData)
Then define whatever you want to do with it
def my_hist_data_handler(msg):
print(msg)
Also note MSFT (or QQQ) is a stock
qqqq.m_secType = "STK" #cash is for forex
qqqq.m_symbol = "MSFT" #use less confusing var name
qqqq.m_currency = "USD"
qqqq.m_exchange = "SMART" #for stocks usually
Related
First one:
### configuration details
TELEGRAM_TOKEN = '' # telegram bot token
TELEGRAM_CHANNEL ='' # channel id
INTERVAL = '1m' # binance time interval
SHORT_EMA = 7 # short interval for ema
LONG_EMA = 21 # long interval for ema
Here is my second code:
import requests
import talib
import time
import numpy as np
import websocket
from config import TELEGRAM_TOKEN, TELEGRAM_CHANNEL , INTERVAL, SHORT_EMA , LONG_EMA
def streamKline(currency, interval):
websocket.enableTrace(False)
socket = f'wss://stream.binance.com:9443/ws/{currency}#kline_{interval}'
ws = websocket.WebSocketApp(socket)
ws.run_forever()
#SYMBOLS TO LOOK FOR ALERTS
SYMBOLS = [
"ETHUSDT",
"BTCUSDT",
"ATOMUSDT",
"BNBUSDT",
"FTMBUSD",
"ENJUSDT",
"WAXPUSDT"
]
#sending alerts to telegram
def send_message(message):
url = "https://api.telegram.org/bot{}/sendMessage?chat_id={}&text={}&parse_mode=markdown".format(TELEGRAM_TOKEN,TELEGRAM_CHANNEL,message)
res = requests.get(url);print(url);
return res
# getting klines data to process
def streamKline(symbol):
data = socket.streamKline(symbol=symbol,interval=INTERVAL,limit=300) # more data means more precision but at the trade off between speed and time
return_data = []
# taking closing data for each kline
for each in data:
return_data.append(float(each[4])) # 4 is the index of the closing data in each kline
return np.array(return_data) # returning as numpy array for better precision and performance
def main():
# making a infinite loop that keeps checking for condition
while True:
#looping through each coin
for each in SYMBOLS:
data = streamKline(each)
ema_short = talib.EMA(data,int(SHORT_EMA))
ema_long = talib.EMA(data,int(LONG_EMA))
last_ema_short = ema_short[-2]
last_ema_long = ema_long[-2]
ema_short = ema_short[-1]
ema_long = ema_long[-1]
# conditions for alerts
if(ema_short > ema_long and last_ema_short < last_ema_long):
message = each + "bullcoming "+ str(SHORT_EMA) + " over "+str(LONG_EMA);print(each ,"alert came");
send_message(message);
time.sleep(0.5);
# calling the function
if __name__ == "__main__":
main()
The part of config is all settle done, just second for the kline data, the error mention lot like this.
data = socket.streamKline(symbol=symbol,interval=INTERVAL,limit=300) # more data means more precision but at the
trade off between speed and time
NameError: name 'socket' is not defined
I just don't know how to do it, I want build a ema alert that can give me a message when I am not watching chart, through this way seems not work, I have tried many times, and also find many video but still, I am just an beginner, nothing improving at all.
i am new to Interactive brokers API, wondering if there is any way to get quote of NIFTY50 index, as i can see examples of NIFTY FUTURES, etc but not on index price quote of NIFTY50 or BANKNIFTY,
need help with some example, thanks,
sample on on getting quote of NIFTY OPTIONS,
from locale import currency
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.ticktype import TickTypeEnum
from ibapi.common import *
import threading
import time
def get_close_quote(symbol, secType='OPT', exchange='NSE', currency='INR'):
class IBapi(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
def historicalData(self, reqId, bar):
print(f'Time: {bar.date} Close: {bar.close}')
def tickPrice(self, reqId, tickType, price, attrib):
if tickType == TickTypeEnum.LAST or tickType == TickTypeEnum.DELAYED_LAST:
self.last = price;
self.disconnect()
def run_loop():
app.run()
app = IBapi()
app.connect('127.0.0.1', 7496, 123)
#Start the socket in a thread
api_thread = threading.Thread(target=run_loop, daemon=True)
api_thread.start()
time.sleep(1) #Sleep interval to allow time for connection to server
#Create contract object
contract = Contract()
contract.localSymbol = symbol
contract.secType = secType
contract.exchange = exchange
contract.currency = currency
app.reqMktData(100, contract, "", False, False, None)
time.sleep(2) #sleep to allow enough time for data to be returned
app.disconnect()
return(app.last)
I am not familiar with Interactive brokers API but from digging on their website I did find those useful commands. You are welcome to check more than provided in this answer.
If you are trying to get a different type of security, as per the documentation, you would change the contract.secType to one of the following:
The security's type: STK - stock (or ETF) OPT - option FUT - future
IND - index FOP - futures option CASH - forex pair BAG - combo WAR -
warrant BOND- bond CMDTY- commodity NEWS- news FUND- mutual fund.
As I understood, you also want to get the actual price as part of the request for example last price is tick id = 4 as seen on the documentation of different types, and in general only have to request for specific ticks.
In reqMktData the genericTickList (3rd parameter) can be used to specify extra ticks to monitor, like demonstrated in documentation:
# Requesting RTVolume (Time & Sales) and shortable generic ticks
self.reqMktData(1004, ContractSamples.USStockAtSmart(), "233,236", False, False, [])
Where "233, 236" are the specified ticks to get from the website.
Also when checking the contract documentation, you can acquire the Strike price from the contract object.
I took the below code from one of the answered queries in Stackoverflow (unfortunately i cannot give full credit as i cannot locate the page anymore). I changed it a bit to fit my purpose.
I want to extract historical Reuters data (fundamentalData) for a list of tickers. The below code works fine but it only grabs the last ticker data. I know i need to build a while loop but i tried many times and none worked. I'm sure this is a quick fix but since I am new at coding and python in general I just can't find the solution. Any help would be appreciated!
#Import all libriaries
from ib.opt import ibConnection, message
from time import sleep
import lxml.etree
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
from IPython.core.debugger import set_trace
from ibapi import wrapper
from ibapi.client import EClient
from ibapi.common import *
from ibapi.contract import Contract
#upload excel file of list of company tickers you want to review
us_list= pd.read_excel(r'C:\TWS API\Request Reuters data\Quant Project IB TWS_test.xlsx', engine='openpyxl')
stocksList = us_list[['TICKER']]
stocksList
def fundamentalData_handler(msg):
global imported
imported = msg.data
def error_handler(msg):
pass
# processing of the lines in financial statements
def extractVauleFromLineItem(fiscalperiod, code):
stage1 = fiscalperiod.find(name='lineitem', coacode=code)
if (not stage1 is None):
stage2 = stage1.get_text()
if (stage2 == stage2):
stage3 = float(stage2)
if (stage3 == stage3):
return (stage3)
else:
return (0.0)
result = pd.DataFrame(columns =['Year', 'Ticker','control','TotalRevenue', 'GrossProfit', 'CommonSharesOutstanding','DilutedNormalizedEPS', 'totalCash', 'TotalDebt','Dividends'])
outcomes = []
for i, row in stocksList.iterrows():
contract = Contract()
contract.symbol = row['TICKER']
contract.secType = "STK"
contract.currency = "USD"
contract.exchange = "SMART"
tws = ibConnection("127.0.0.1",port=7497, clientId=901)
tws.register(error_handler, message.Error)
tws.register(fundamentalData_handler, message.fundamentalData)
tws.connect()
tws.reqFundamentalData(1,contract,'ReportsFinStatements')
sleep(1)
tws.disconnect()
print(contract.symbol)
soup = BeautifulSoup(imported) # library for processing of the obtained XML data
data = []
print(soup.find(name='issueid', type="Ticker").get_text())
print(soup.find(name='coid', type="CompanyName").get_text())
# I found that IB API is not very stable.
# Sometimes it returns data of the wrong company.
# So the control is important
print('Control -',contract.symbol == soup.find(name='issueid', type="Ticker").get_text())
print()
for fiscalperiod in soup.find_all(name="fiscalperiod", type="Annual"):
year = fiscalperiod['fiscalyear']
TotalRevenue = extractVauleFromLineItem(fiscalperiod, 'RTLR')
GrossProfit = extractVauleFromLineItem(fiscalperiod, 'SGRP')
CommonSharesOutstanding = extractVauleFromLineItem(fiscalperiod, 'QTCO')
DilutedNormalizedEPS = extractVauleFromLineItem(fiscalperiod, 'VDES')
totalCash = extractVauleFromLineItem(fiscalperiod, 'OTLO')
TotalDebt = extractVauleFromLineItem(fiscalperiod, 'STLD')
Dividends = extractVauleFromLineItem(fiscalperiod, 'FCDP')
thisYearData = (year,contract.symbol, (contract.symbol == soup.find(name='issueid', type="Ticker").get_text()),TotalRevenue , GrossProfit, CommonSharesOutstanding, totalCash, TotalDebt, Dividends)
data.append(thisYearData)
df_data = pd.DataFrame(data, columns =['Year','control','TotalRevenue', 'GrossProfit', 'CommonSharesOutstanding','DilutedNormalizedEPS', 'totalCash', 'TotalDebt','Dividends'])
df_data = df_data.sort_values(by=['Year'])
I was able to piece together a script from IB's documentation/examples and forums on this site. I am getting the output I want for a single symbol, however, if I use a list of stocks, I cannot figure out a way to pass the ticker symbol through to the DF output file. My workaround was to create a dictionary that uses the list sequence (see below) however the output from IB's api changes slightly each time rendering the symbols mostly pointless. The list i am using below normally has 20+ names but may change, i cut it down to make it easier to view.
#Brian/and or other developers, if there is a way to create either a unique ID/sequence for each symbol call and stamp it to data that is brought back, i can then utilize a dictionary to apply the symbol. In the other forum, you passed in a line where n_id = n_id +1, if that can be applied and is linked to each specific call which is done in order of the list, then that could work?
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
import pandas as pd
import threading
import time
from datetime import timedelta
import datetime
class IBapi(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.data = [] #Initialize variable to store candle
def historicalData(self, reqId, bar):
#print(f'Time: {bar.date} Close: {bar.close} Volume: {bar.volume}',reqId)
self.data.append([bar.date, bar.close, bar.volume, reqId])
def run_loop():
app.run()
app = IBapi()
app.connect('127.0.0.1', 7496, 123)
#Start the socket in a thread
api_thread = threading.Thread(target=run_loop, daemon=True)
api_thread.start()
time.sleep(1) #Sleep interval to allow time for connection to server
symbols = ['SPY','MSFT','GOOG','AAPL','QQQ','IWM','TSLA']
for sym in symbols:
contract = Contract()
contract.symbol = str(sym)
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
#contract.primaryExchange = "ISLAND"
app.reqHistoricalData(1, contract, "", "1 D", "10 mins", "ADJUSTED_LAST", 1, 2, False, [])
time.sleep(5) #sleep to allow enough time for data to be returned
df = pd.DataFrame(app.data, columns=['DateTime', 'ADJUSTED_LAST','Volume','reqId'])
df['DateTime'] = pd.to_datetime(df['DateTime'],unit='s') #,unit='s')
df['Count'] = df.groupby('DateTime').cumcount()+1
sym_dict = {1:'SPY',2:'MSFT',3:'GOOG',4:'AAPL',5:'QQQ',6:'IWM',7:'TSLA'}
df['Ticker'] = df['Count'].map(sym_dict)
print(df)
#edit, adding in #Brian's detail:
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
import pandas as pd
import time
from datetime import timedelta
import datetime
start = datetime.datetime.utcnow()
class IBapi(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.data = []
def error(self, reqId, errorCode, errorString):
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def historicalData(self, reqId, bar):
self.data.append([bar.date, bar.close, bar.volume, sym_dict[reqId]])
print("HistoricalData. ReqId:", sym_dict[reqId], "BarData.", bar)
# include this callback to track progress and maybe disconnectwhen all are finished
def historicalDataEnd(self, reqId: int, start: str, end: str):
print("finished", sym_dict[reqId])
def run_loop():
app.run()
app = IBapi()
app.connect('127.0.0.1', 7496, 123)
# you should wait for nextValidId instead of sleeping, what if it takes more than 1 second? #john: how do i do this?
time.sleep(5) #john: how do i do this? wait for nextValidId?
symbols = ['SPY','MSFT','GOOG','AAPL','QQQ','IWM','TSLA']
reqId = 1
sym_dict = {}
for sym in symbols:
contract = Contract()
contract.symbol = str(sym)
sym_dict[reqId] = sym
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
#contract.primaryExchange = "ISLAND" # you may need this for msft
app.reqHistoricalData(reqId, contract, "", "1 D", "10 mins", "ADJUSTED_LAST", 1, 2, False, [])
reqId += 1
time.sleep(5)
df = pd.DataFrame(app.data, columns=['DateTime', 'ADJUSTED_LAST','Volume','sym'])
df['DateTime'] = pd.to_datetime(df['DateTime'],unit='s') #,unit='s')
df = df.set_index(['sym','DateTime']).sort_index()
print(df)
app.disconnect()
You just need to maintain a dict of reqId and symbol.
I'm not sure that one DataFrame is the best way to store your data but if you do then set a multi index. Decide how much data you want and how you're going to store it on disk and then decide on a data structure. I suggest csv for speed or sqlite for simplicity. Pandas can handle either.
I deleted your comments and added some of my own.
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
import pandas as pd
import threading
import time
from datetime import timedelta
import datetime
# I added this code to get fake data, works wtihout tws running
from ibapi.common import BarData
from random import random
start = datetime.datetime.utcnow()
def fake_data(reqId, ib):
last = reqId*10
for i in range(60, 0, -10):
bar = BarData();
bar.date = start - timedelta(minutes=i)
last += random() - 0.5
bar.close = last
bar.volume = reqId * 1000
ib.historicalData(reqId, bar)
ib.historicalDataEnd(reqId,"","")
class IBapi(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.data = []
#always include this for important messages, also turn on api logging in TWS/IBG
def error(self, reqId, errorCode, errorString):
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def historicalData(self, reqId, bar):
self.data.append([bar.date, bar.close, bar.volume, sym_dict[reqId]])
# include this callback to track progress and maybe disconnectwhen all are finished
def historicalDataEnd(self, reqId: int, start: str, end: str):
print("finished", sym_dict[reqId])
def run_loop():
app.run()
app = IBapi()
app.connect('127.0.0.1', 7496, 123)
# threading is needed only if you plan to interact after run is called
# this is a good way if you use a ui like jupyter
api_thread = threading.Thread(target=run_loop, daemon=True)
api_thread.start()
# you should wait for nextValidId instead of sleeping, what if it takes more than 1 second?
time.sleep(1)
symbols = ['SPY','MSFT','GOOG','AAPL','QQQ','IWM','TSLA']
reqId = 1
sym_dict = {}
for sym in symbols:
contract = Contract()
contract.symbol = str(sym)
sym_dict[reqId] = sym
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
#contract.primaryExchange = "ISLAND" # you may need this for msft
#app.reqHistoricalData(reqId, contract, "", "1 D", "10 mins", "ADJUSTED_LAST", 1, 2, False, [])
fake_data(reqId, app)
reqId += 1
#now you need to sleep(10) to make sure you don't get a pacing error for too many requests
# don't sleep, use historicalDataEnd to know when finished
time.sleep(5)
df = pd.DataFrame(app.data, columns=['DateTime', 'ADJUSTED_LAST','Volume','sym'])
df['DateTime'] = pd.to_datetime(df['DateTime'],unit='s')
#make an index and sort
df = df.set_index(['sym','DateTime']).sort_index()
# now you can use the indexes
print(df.loc[("SPY","2021")])
#don't forget to disconnect somewhere or the clientId will still be in use
Hi guys am just starting to work on an Ibpy algorithm and i would like to test it with paper trading first but i have a little understanding how to use the reqMktData to get the last price. I have no problem placing orders but this returns nothing for 25 seconds, Im thinking that it is only to be used during trading hours or maybe am just using it wrong any thoughts?
from ib.opt import ibConnection, message
from ib.ext.Contract import Contract
from time import sleep
def my_callback_handler(msg):
inside_mkt_bid = ''
inside_mkt_ask = ''
if msg.field == 1:
inside_mkt_bid = msg.price
print 'bid', inside_mkt_bid
elif msg.field == 2:
inside_mkt_ask = msg.price
print 'ask', inside_mkt_ask
tws = ibConnection()
tws.register(my_callback_handler, message.tickSize, message.tickPrice)
tws.connect()
c = Contract()
c.m_symbol = "DATA"
c.m_secType = "STK"
c.m_exchange = "SMART"
c.m_currency = "USD"
tws.reqMktData(788,c,"",False)
sleep(25)
print 'All done'
tws.disconnect()
I have try IbPy before and successfully get the data but now I have use Ibapi instead which is more difficult and still can't fully trade in it but it has an adjusted historical price.
So this is my code which you have to tailor what so you want.
1.Get the stock member form Excel
from ib.opt import ibConnection, message
from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.ext.TickType import TickType as tt
from time import sleep, time, strftime
import datetime
from __future__ import print_function #I'm using 3.x style print
import pandas as pd
import numpy as np
from math import ceil
import re
xls_file = pd.ExcelFile('xxxx\\Interactive_Broker_trading\\SNP2.xlsx')
df = xls_file.parse('Sheet1')
Ticker = df.iloc[:,1]
all_data = pd.DataFrame(Ticker)
all_data.columns = ['ticker']
all_data['type'] = 'STK'
all_data['exchange'] = 'SMART'
all_data['curr'] = 'USD'
all_data['bidPrice'] =0
all_data['askPrice'] =0
all_data['lastPrice'] =0
all_data['HistoryPrice']=0
2.Get the Historical Price by using for loop since my account has a limit of 100 request per moment so I devide it into 8 multiple sessions for S&P 505. Then relogin at each 70 stocks. I can get the total of 505 in 2 minutes.
def error_handler(msg):
print(msg)
def my_callback_handler(msg):
if msg.field in [tt.BID,tt.ASK,tt.LAST]:
# from ib.ext.TickType import TickType as tt
#now we can just store the response in the data frame
all_data.loc[msg.tickerId,tt.getField(msg.field)] = msg.price
# if msg.field == tt.LAST:
# # print('a')
# print(all_data.loc[msg.tickerId,'ticker'],msg.price)
t = time()
max_amount_per_Iter = 70 #max number per iter to save cost
max_Iter = ceil(len(all_data)/max_amount_per_Iter)
for i in range (0,max_Iter):
print('====================for : ',i+1,'==========================')
sleep(1)
tws = ibConnection(clientId=11+i)
tws.register(my_callback_handler, message.tickPrice, message.tickSize)
tws.register(error_handler, 'Error')
tws.connect()
all_dum = all_data.iloc[i*max_amount_per_Iter:min((i+1)*max_amount_per_Iter,len(all_data)),:]
for index, row in all_dum.iterrows():
c = Contract()
c.m_symbol = row['ticker']
c.m_exchange = row['exchange']
c.m_currency = row['curr']
c.m_secType = row['type']
# the tickerId is just the index in but for some reason it needs str()
tws.reqMktData(str(index),c,'',False)
sleep(0.2)
sleep(2)
print('=========End round : ',i+1,'with time :',time() - t,'==============')
tws.disconnect()
I'm thinking it has something to do with the market data subscription within IB itself because I am having a similar problem. I get a TWS Time at connection... returned in the results along with the "market data farm connection" Msg.
Make sure you have a connection port & clientID established, i.e.:
tws = ibConnection(port=7496,clientId=100)
Note that 7496 is a common port, but the clientId is anything you wish to specify (within the IB account you are using under File->API->Settings).