Open fcarpentey75012 opened 4 years ago
Here is a more complete version of the code, it might work in its entirety but you could also pull the improvements you need.
# -*- coding: utf-8 -*-
""" A wrapper for the Bloomberg API.
Designed to roughly emulate the Excel API.
All requests return well-formed Series or DataFrames where appropriate and can
handle any number of securities and fields within a single request.
Excel BDH: historicalRequest()
Excel BDP: referenceRequest()
Excel BDS: bulkRequest()
Note: Securities may be fetched by ticker, bbgid or cusip using the following
formats: "BMO CN Equity", "BBG0000000000", or "/cusip/000000000"
Created July 2015
@author: ryan
"""
import socket
import itertools
from datetime import datetime, date, time
import pandas as pd
import numpy as np
from pandas import Series
from pandas import DataFrame
# Default Connections
BLP_HOST = 'localhost'
BLP_PORT = 8194
PROXY_HOST = ''
PROXY_PORT = 5001
class RequestError(Exception):
"""A RequestError is raised when there is a problem with a Bloomberg API response."""
def __init__(self, description, value=None):
self.value = value
self.description = description
def __str__(self):
if self.value is not None:
return self.description + '\n' + self.value
return self.description
def _uwrap(s):
"""Helper function to convert a string or list into a list of unique entries."""
s = [s] if isinstance(s, str) else s
return list(set(s))
def _convertDate(d):
"""Helper function to convert dates and datetimes into blpapi strings."""
if isinstance(d, np.datetime64):
d = pd.Timestamp(d)
elif isinstance(d, pd.Period):
d = d.to_timestamp(freq='D')
if isinstance(d, date):
if isinstance(d, datetime) and (d.time() != time(0)):
return d.strftime('%Y-%m-%dT%H:%M:%S')
else:
return d.strftime('%Y%m%d')
return d
# Attempt to import the Bloomberg API. Technically this is a bad idea as it
# can mask unrelated ImportErrors but whatever.
try:
# noinspection PyUnresolvedReferences
import blpapi
# The Bloomberg API was successfully imported - Create the normal
# BLPInterface class.
DEFAULT_HOST = BLP_HOST
DEFAULT_PORT = BLP_PORT
class BLPInterface:
""" A wrapper for the Bloomberg API that returns DataFrames. This class
manages a //BLP/refdata service and therefore does not handle event
subscriptions.
All calls are blocking and responses are parsed and returned as
DataFrames where appropriate.
A RequestError is raised when an invalid security is queried. Invalid
fields will fail silently and may result in an empty DataFrame.
"""
# noinspection PyShadowingBuiltins
def __init__(self, host=BLP_HOST, port=BLP_PORT, open=True):
self.active = False
self.host = host
self.port = port
self.session = None
self.refDataService = None
if open:
self.open()
def open(self):
if not self.active:
sessionOptions = blpapi.SessionOptions()
sessionOptions.setServerHost(self.host)
sessionOptions.setServerPort(self.port)
sessionOptions.setAutoRestartOnDisconnection(True)
self.session = blpapi.Session(sessionOptions)
if (not self.session.start()) or (not self.session.openService("//blp/refdata")):
raise RequestError('Failed to start session')
self.refDataService = self.session.getService('//BLP/refdata')
self.active = True
def close(self):
if self.active:
self.session.stop()
self.active = False
def historicalRequest(self, securities, fields, startDate, endDate='', overrides=None, **kwargs):
""" Equivalent to the Excel BDH Function.
If securities are provided as a list, the returned DataFrame will
have a MultiIndex.
StartDate and endDate should be a datetime.date or YYYYMMDD string.
Datetimes or Timestamps with a non-zero time component will not be
recognized correctly by the Bloomberg API.
Useful kwargs are periodicitySelection, adjustmentNormal,
adjustmentAbnormal, adjustmentSplit, and currency.
"""
defaults = {'startDate' : startDate.replace('-', '') if isinstance(startDate, str) else startDate,
'endDate' : endDate.replace('-', '') if isinstance(endDate, str) else endDate,
'periodicityAdjustment' : 'CALENDAR',
'periodicitySelection' : 'DAILY',
'nonTradingDayFillOption' : 'NON_TRADING_WEEKDAYS',
'adjustmentNormal' : False,
'adjustmentAbnormal' : False,
'adjustmentSplit' : True,
'adjustmentFollowDPDF' : False}
defaults.update(kwargs)
usecurities = _uwrap(securities)
ufields = _uwrap(fields)
response = self.sendRequest('HistoricalData', usecurities, ufields, overrides, defaults)
data = []
keys = []
for msg in response:
securityData = msg.getElement('securityData')
fieldData = securityData.getElement('fieldData')
fieldDataList = [fieldData.getValueAsElement(i) for i in range(fieldData.numValues())]
df = DataFrame(columns=ufields)
for fld in fieldDataList:
for v in [fld.getElement(i) for i in range(fld.numElements())
if fld.getElement(i).name() != 'date']:
df.ix[fld.getElementAsDatetime('date'), str(v.name())] = v.getValue()
df.index = pd.to_datetime(df.index)
df.replace('#N/A History', np.nan, inplace=True)
keys.append(securityData.getElementAsString('security'))
data.append(df)
if len(data) == 0:
return DataFrame()
else:
data = pd.concat(data, keys=keys, axis=1, names=['Security', 'Field']).sort_index()
data.index.name = 'Date'
if isinstance(securities, str) and isinstance(fields, str):
data = data.iloc[:,0]
data.name = fields
elif isinstance(securities, str):
data.columns = data.columns.droplevel('Security')
data = data[fields]
elif isinstance(fields, str):
data.columns = data.columns.droplevel('Field')
data = data[securities]
else:
data = data[list(itertools.product(securities, fields))]
return data
def referenceRequest(self, securities, fields, overrides=None, **kwargs):
""" Equivalent to the Excel BDP Function.
If either securities or fields are provided as lists, a DataFrame
will be returned.
"""
usecurities = _uwrap(securities)
ufields = _uwrap(fields)
response = self.sendRequest('ReferenceData', usecurities, ufields, overrides, kwargs)
data = DataFrame(index=usecurities, columns=ufields)
for msg in response:
securityData = msg.getElement('securityData')
securityDataList = [securityData.getValueAsElement(i) for i in range(securityData.numValues())]
for sec in securityDataList:
fieldData = sec.getElement('fieldData')
fieldDataList = [fieldData.getElement(i) for i in range(fieldData.numElements())]
for fld in fieldDataList:
data.ix[sec.getElementAsString('security'), str(fld.name())] = fld.getValue()
if data.empty:
return DataFrame()
else:
data.index.name = 'Security'
data.columns.name = 'Field'
if isinstance(securities, str) and isinstance(fields, str):
data = data.iloc[0, 0]
elif isinstance(securities, str):
data = data.iloc[0, :][fields]
elif isinstance(fields, str):
data = data.iloc[:, 0][securities]
else:
data = data.loc[securities, fields]
return data
def bulkRequest(self, securities, fields, overrides=None, **kwargs):
""" Equivalent to the Excel BDS Function.
If securities are provided as a list, the returned DataFrame will
have a MultiIndex.
You may also pass a list of fields to a bulkRequest. An appropriate
MultiIndex will be generated, however such a DataFrame is unlikely
to be useful unless the bulk data fields contain overlapping columns.
"""
response = self.sendRequest('ReferenceData', securities, fields, overrides, kwargs)
data = []
keys = []
for msg in response:
securityData = msg.getElement('securityData')
securityDataList = [securityData.getValueAsElement(i) for i in range(securityData.numValues())]
for sec in securityDataList:
fieldData = sec.getElement('fieldData')
fieldDataList = [fieldData.getElement(i) for i in range(fieldData.numElements())]
fldData = []
fldKeys = []
for fld in fieldDataList:
df = DataFrame()
for v in [fld.getValueAsElement(i) for i in range(fld.numValues())]:
s = Series()
for d in [v.getElement(i) for i in range(v.numElements())]:
try:
s[str(d.name())] = d.getValue()
except:
# There is seriously no end to the shit getValue() can raise.
pass
# Bloomberg returns this magic number instead of NaN for certain bulk fields.
df = df.append(s.where(s != -2.4245362661989844e-14, np.nan), ignore_index=True)
try:
df = df.set_index(df.columns[0])
if not df.empty:
fldKeys.append(str(fld.name()))
fldData.append(df)
except IndexError:
pass
if fldData:
keys.append(sec.getElementAsString('security'))
data.append(pd.concat(fldData, keys=fldKeys, names=['Field']))
if data:
data = pd.concat(data, keys=keys, names=['Security'])
data.columns.name = 'Element'
else:
return DataFrame()
if isinstance(securities, str) and isinstance(fields, str):
data = data.reset_index(['Security', 'Field'], drop=True)
elif isinstance(securities, str):
data = data.reset_index('Security', drop=True)
elif isinstance(fields, str):
data = data.reset_index('Field', drop=True)
return data
def portfolioDataRequest(self, securities, fields, overrides=None, **kwargs):
response = self.sendRequest('PortfolioData', securities, fields, overrides, kwargs)
# TODO: Read exactly like bulkrequest
return response
def intradayBarRequest(self, security, startDate, endDate, **kwargs):
""" Performs an IntradayBarRequest.
IntradayBarRequests can only include a single security and will
return a predefined set of fields. The granularity of this
request can be set via the interval parameter in minutes.
To receive data, startDate and endDate must include a UTC time.
"""
defaults = {'startDateTime' : startDate,
'endDateTime' : endDate,
'eventType' : 'TRADE',
'interval' : 5,
'adjustmentNormal' : False,
'adjustmentAbnormal' : False,
'adjustmentSplit' : True,
'adjustmentFollowDPDF' : False}
defaults.update(kwargs)
response = self.sendRequest('IntradayBar', security, [], None, defaults)
data = DataFrame()
for msg in response:
tickData = msg.getElement('barData').getElement('barTickData')
tickDataList = [tickData.getValueAsElement(i) for i in range(tickData.numValues())]
for tick in tickDataList:
dt = tick.getElementAsDatetime('time').replace(tzinfo=None)
for v in [tick.getElement(i) for i in range(1, tick.numElements())]:
# Get every value as a string and cast to the apropriate type later
# This is pretty dirty but network latency dominates the runtime of this function
data.ix[dt, str(v.name())] = v.getValueAsString()
data.index.name = 'Date'
return data.apply(pd.to_numeric, errors='coerce').sort_index()
def intradayTickRequest(self, security, startDate, endDate, **kwargs):
""" Performs an IntradayTickRequest.
IntradayTickRequests can only include a single security and will
return a predefined set of fields.
To receive data, startDate and endDate must include a UTC time.
"""
defaults = {'startDateTime' : startDate,
'endDateTime' : endDate,
'eventTypes' : ['TRADE']}
defaults.update(kwargs)
response = self.sendRequest('IntradayTick', security, [], None, defaults)
data = DataFrame()
for msg in response:
tickData = msg.getElement('tickData').getElement('tickData')
tickDataList = [tickData.getValueAsElement(i) for i in range(tickData.numValues())]
for tick in tickDataList:
dt = tick.getElementAsDatetime('time').replace(tzinfo=None)
for v in [tick.getElement(i) for i in range(1, tick.numElements())]:
data.ix[dt, str(v.name())] = v.getValueAsString()
data.index.name = 'Date'
return data.apply(pd.to_numeric, errors='coerce').sort_index()
def sendRequest(self, requestType, securities, fields, overrides, elements):
""" Prepares and sends a request then blocks until it can return
the complete response.
Depending on the complexity of your request, incomplete and/or
unrelated messages may be returned as part of the response.
"""
request = self.refDataService.createRequest(requestType + 'Request')
if isinstance(securities, str):
securities = [securities]
if isinstance(fields, str):
fields = [fields]
for s in securities:
try:
request.getElement("securities").appendValue(s)
except:
request.set('security', s)
for f in fields:
request.getElement("fields").appendValue(f)
for k, v in elements.items():
if isinstance(v, list):
for i in v:
request.getElement(k).appendValue(_convertDate(i))
else:
request.set(k, _convertDate(v))
if overrides is not None:
for k, v in overrides.items():
ovr = request.getElement('overrides').appendElement()
ovr.setElement("fieldId", str(k))
ovr.setElement('value', str(_convertDate(v)))
self.session.sendRequest(request)
response = []
while True:
event = self.session.nextEvent(100)
for msg in event:
if msg.hasElement('responseError'):
raise RequestError('Response Error', str(msg.getElement('responseError')))
if msg.hasElement('securityData'):
if msg.getElement('securityData').hasElement('fieldExceptions') and\
(msg.getElement('securityData').getElement('fieldExceptions').numValues() > 0):
raise RequestError('Field Error', str(msg.getElement('securityData').getElement('fieldExceptions')))
if msg.getElement('securityData').hasElement('securityError'):
raise RequestError('Security Error', str(msg.getElement('securityData').getElement('securityError')))
if msg.messageType() == requestType + 'Response':
response.append(msg)
if event.eventType() == blpapi.Event.RESPONSE:
break
return response
def __enter__(self):
self.open()
return self
# noinspection PyUnusedLocal
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def __del__(self):
self.close()
except ImportError:
# The Bloomberg API was not found - Implement a Proxy BLPInterface
# instead.
from rqm.source import net
DEFAULT_HOST = PROXY_HOST
DEFAULT_PORT = PROXY_PORT
class BLPInterface:
""" A wrapper for the Bloomberg API that returns DataFrames. This is
the Proxy version of the BLPInterface and was created as the
current environment does not have Bloomberg access.
All requests will be forwarded to (host, port). Run BLPServer.py
on a computer to fulfil requests.
All calls are blocking and responses are parsed and returned as
DataFrames where appropriate.
"""
# noinspection PyShadowingBuiltins
def __init__(self, host=PROXY_HOST, port=PROXY_PORT, open=True):
self.active = False
self.host = host
self.port = port
self.socket = None
if open:
self.open()
def open(self):
if not self.active:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(60)
self.socket.connect((self.host, self.port))
self.active = True
def historicalRequest(self, securities, fields, startDate, endDate='', overrides=None, **kwargs):
kwargs['securities'] = securities
kwargs['fields'] = fields
kwargs['startDate'] = startDate
kwargs['endDate'] = endDate
kwargs['overrides'] = overrides
return self.sendRequest('historicalRequest', kwargs)
def referenceRequest(self, securities, fields, overrides=None, **kwargs):
kwargs['securities'] = securities
kwargs['fields'] = fields
kwargs['overrides'] = overrides
return self.sendRequest('referenceRequest', kwargs)
def bulkRequest(self, securities, fields, overrides=None, **kwargs):
kwargs['securities'] = securities
kwargs['fields'] = fields
kwargs['overrides'] = overrides
return self.sendRequest('bulkRequest', kwargs)
def intradayBarRequest(self, security, startDate, endDate, **kwargs):
kwargs['security'] = security
kwargs['startDate'] = startDate
kwargs['endDate'] = endDate
return self.sendRequest('intradayBarRequest', kwargs)
def intradayTickRequest(self, security, startDate, endDate, **kwargs):
kwargs['security'] = security
kwargs['startDate'] = startDate
kwargs['endDate'] = endDate
return self.sendRequest('intradayTickRequest', kwargs)
# noinspection PyTypeChecker
def sendRequest(self, requestType, arguments):
net.sendObject(self.socket, [requestType, arguments])
return net.receiveObject(self.socket)
def close(self):
if self.active:
self.socket.close()
self.active = False
def __enter__(self):
self.open()
return self
# noinspection PyUnusedLocal
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def __del__(self):
self.close()
def main():
""" Basic usage examples.
Note that if any tickers have changed since these examples were written
a RequestError will be raised.
"""
try:
blp = BLPInterface()
# ==============================
# = HistoricalRequest Examples =
# ==============================
# Requesting a single security and field returns a simple Series.
print(blp.historicalRequest('BMO CN Equity', 'PX_LAST', '20141231', '20150131'))
# Requesting multiple fields returns a DataFrame. Dates may also be passed as a datetime.
print(blp.historicalRequest('BNS CN Equity', ['PX_LAST', 'PX_VOLUME'],
datetime(2014, 12, 31), datetime(2015, 1, 31)))
# Requesting multiple securities and fields returns a DataFrame with a MultiIndex.
print(blp.historicalRequest(['CM CN Equity', 'NA CN Equity'], ['PX_LAST', 'PX_VOLUME'],
'20141231', '20150131'))
# You may force the returned data to be of a specific format by passing arguments as lists.
print(blp.historicalRequest(['NA CN Equity'], ['PX_LAST'], '20141231', '20150131'))
# Keyword arguments are added to the request, allowing you to perform advanced queries.
print(blp.historicalRequest('TD CN Equity', 'PCT_CHG_INSIDER_HOLDINGS', '20141231', '20150131',
periodicitySelection='WEEKLY'))
blp.close()
# The BLPInterface Class can also be used as a ContextManager.
with BLPInterface() as blp:
# =============================
# = ReferenceRequest Examples =
# =============================
# Requesting a single security/field will return the single value, not a DataFrame.
print(blp.referenceRequest('BBD/B CN Equity', 'GICS_SECTOR'))
# Requesting multiple securities or fields will return a Series or DataFrame.
print(blp.referenceRequest(['CNR CN Equity', 'CP CN Equity'], ['SECURITY_NAME_REALTIME', 'LAST_PRICE']))
# You may force any request to return a DataFrame by passing the arguments as lists.
print(blp.referenceRequest(['MDA CN Equity'], ['NAME_RT']))
# Passing overrides in a dictionary is also supported
print(blp.referenceRequest('TCK/B CN Equity', 'BICS_REVENUE_%_LEVEL_ASSIGNED',
overrides={'EQY_FUNDS_SEGMENT_NUMBER':1}))
print(blp.referenceRequest(['IBM US Equity', 'MSFT US Equity'], ['PX_LAST', 'DS002', 'EQY_WEIGHTED_AVG_PX'],
overrides={'VWAP_START_TIME' : '9:30',
'VWAP_END_TIME' : '11:30'}))
# ========================
# = BulkRequest Examples =
# ========================
# Requesting a single security and field will return a DataFrame.
print(blp.bulkRequest('CIG CN Equity', 'EQY_DVD_ADJUST_FACT'))
# You may request multiple securities and/or fields to receive a MultiIndex
# print (blp.bulkRequest(['CP CN Equity','CNR CN Equity'],'PG_REVENUE'))
# print (blp.bulkRequest('CIG CN Equity',['EQY_DVD_ADJUST_FACT','DVD_HIST_ALL']))
# ========================
# = Tick Examples ========
# ========================
# Tick requests can only contain a single security.
print(blp.intradayBarRequest('BMO CN Equity','2015-08-21T6:00:00','2015-08-21T16:00:00'))
print(blp.intradayTickRequest('ZCL CN Equity','2015-08-21T6:00:00','2015-08-21T16:00:00'))
except RequestError:
raise
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("Ctrl+C pressed. Stopping...")
BIG thanks !! The code work very well, we blocked on Override. Thanks you !
Hello, i have a new problem with API. I would this sendresquest : print(blp.referenceRequest(['C13 FP Equity'], ['INTERVAL_PERCENT_CHANGE','INTERVAL_PERCENT_CHANGE'],overrides={'CALC_INTERVAL':'1Y','CALC_INTERVAL':'5Y'})). But Bloomberg API send me back same value. It's possible to send same Field and same Overrides but with different value ? Thks you for your time !
Field INTERVAL_PERCENT_CHANGE INTERVAL_PERCENT_CHANGE
Security
C13 FP Equity 0.077103 0.077103
As far as I am aware you will need to submit two requests to do what you want. An override applies to the entire request.
blp.referenceRequest(['C13 FP Equity'], ['INTERVAL_PERCENT_CHANGE'],overrides={'CALC_INTERVAL':'1Y'})
blp.referenceRequest(['C13 FP Equity'], ['INTERVAL_PERCENT_CHANGE'],overrides={'CALC_INTERVAL':'5Y'})
Depending on how many intervals you need it might make more sense to do a history request and calculate the trailing periods in Pandas.
Thnks you for your response, i try this :
`def created_dictionnary(liste_overrides,liste_values): dictionnary_parameter={} if len(name_list) != liste_overrides: dictionnary_parameter={} for key,value in zip(liste_overrides,liste_values): if key not in dictionnary_parameter: dictionnary_parameter[key]=[value] else: dictionnary_parameter[key].append(value) return dictionnary_parameter
blp = BLPInterface() with BLPInterface() as blp:
list_one = ['CALC_INTERVAL', 'CALC_INTERVAL', 'CALC_INTERVAL', 'RISK_MEASURES_TIME_FRAME', 'RISK_MEASURES_TIME_FRAME']
list_two = ['1Y','3Y', '5Y', '4.0', '5.0']
my_list = []
name_list = list(dict.fromkeys(list_one))
if len(name_list) != list_one:
dictionnary_overrides_values = created_dictionnary(list_one,list_two)
for x in dictionnary_overrides_values:
list_values = dictionnary_overrides_values.get(x)
for i in list_values:
ss = []
ss.append(x)
cc = []
cc.append(i)
dictionnary_parametre = dict(zip(ss, cc))
df = blp.referenceRequest(['C13 FP Equity'], ['INTERVAL_PERCENT_CHANGE','MAXIMUM_DRAWDOWN_PCT'],overrides=dictionnary_parametre)
# name_list.append(df['INTERVAL_PERCENT_CHANGE'].tolist())
# print(name_list)
blp.close()
# `
But it's not very optimal, but i was think to modify your code for to take list in send and not dictionnary. I try this :
`class RequestError(Exception): """A RequestError is raised when there is a problem with a Bloomberg API response.""" def init (self, value, description): self.value = value self.description = description
def __str__ (self):
return self.description + '\n\n' + str(self.value)
class BLPInterface: """ A wrapper for the Bloomberg API that returns DataFrames. This class manages a //BLP/refdata service and therefore does not handle event subscriptions.
All calls are blocking and responses are parsed and returned as
DataFrames where appropriate.
A RequestError is raised when an invalid security is queried. Invalid
fields will fail silently and may result in an empty DataFrame.
"""
def __init__ (self, host='localhost', port=8194, open=True):
self.active = False
self.host = host
self.port = port
if open:
self.open()
def open (self):
if not self.active:
sessionOptions = blpapi.SessionOptions()
sessionOptions.setServerHost(self.host)
sessionOptions.setServerPort(self.port)
self.session = blpapi.Session(sessionOptions)
self.session.start()
self.session.openService('//BLP/refdata')
self.refDataService = self.session.getService('//BLP/refdata')
self.active = True
def close (self):
if self.active:
self.session.stop()
self.active = False
def historicalRequest (self, securities, fields, startDate, endDate, **kwargs):
""" Equivalent to the Excel BDH Function.
If securities are provided as a list, the returned DataFrame will
have a MultiIndex.
"""
defaults = {'startDate' : startDate,
'endDate' : endDate,
'periodicityAdjustment' : 'ACTUAL',
'periodicitySelection' : 'DAILY',
'nonTradingDayFillOption' : 'ACTIVE_DAYS_ONLY',
'adjustmentNormal' : False,
'adjustmentAbnormal' : False,
'adjustmentSplit' : True,
'adjustmentFollowDPDF' : False}
defaults.update(kwargs)
response = self.sendRequest('HistoricalData', securities, fields, defaults)
data = []
keys = []
for msg in response:
securityData = msg.getElement('securityData')
fieldData = securityData.getElement('fieldData')
fieldDataList = [fieldData.getValueAsElement(i) for i in range(fieldData.numValues())]
df = DataFrame()
for fld in fieldDataList:
for v in [fld.getElement(i) for i in range(fld.numElements()) if fld.getElement(i).name() != 'date']:
df.ix[fld.getElementAsDatetime('date'), str(v.name())] = v.getValue()
df.index = pd.to_datetime(df.index)
df.replace('#N/A History', np.nan, inplace=True)
keys.append(securityData.getElementAsString('security'))
data.append(df)
if len(data) == 0:
return DataFrame()
if type(securities) == str:
data = pd.concat(data, axis=1)
data.columns.name = 'Field'
else:
data = pd.concat(data, keys=keys, axis=1, names=['Security','Field'])
data.index.name = 'Date'
return data
def referenceRequest (self, securities, fields, **kwargs):
""" Equivalent to the Excel BDP Function.
If either securities or fields are provided as lists, a DataFrame
will be returned.
"""
response = self.sendRequest('ReferenceData', securities, fields, kwargs)
data = DataFrame()
for msg in response:
securityData = msg.getElement('securityData')
securityDataList = [securityData.getValueAsElement(i) for i in range(securityData.numValues())]
for sec in securityDataList:
fieldData = sec.getElement('fieldData')
fieldDataList = [fieldData.getElement(i) for i in range(fieldData.numElements())]
for fld in fieldDataList:
data.ix[sec.getElementAsString('security'), str(fld.name())] = fld.getValue()
if data.empty:
return data
else:
data.index.name = 'Security'
data.columns.name = 'Field'
return data.iloc[0,0] if ((type(securities) == str) and (type(fields) == str)) else data
def referenceRequest_override (self, securities, fields, overridesfieldsId, overridesfieldsVal, **kwargs):
""" Equivalent to the Excel BDP Function.
If either securities or fields are provided as lists, a DataFrame
will be returned.
"""
response = self.sendRequest('ReferenceData', securities, fields, overridesfieldsId, overridesfieldsVal, kwargs)
data = DataFrame()
for msg in response:
securityData = msg.getElement('securityData')
securityDataList = [securityData.getValueAsElement(i) for i in range(securityData.numValues())]
for sec in securityDataList:
fieldData = sec.getElement('fieldData')
fieldDataList = [fieldData.getElement(i) for i in range(fieldData.numElements())]
for fld in fieldDataList:
data.ix[sec.getElementAsString('security'), str(fld.name())] = fld.getValue()
if data.empty:
return data
else:
data.index.name = 'Security'
data.columns.name = 'Field'
return data.iloc[0,0] if ((type(securities) == str) and (type(fields) == str)) else data
def bulkRequest (self, securities, fields, **kwargs):
""" Equivalent to the Excel BDS Function.
If securities are provided as a list, the returned DataFrame will
have a MultiIndex.
You may pass a list of fields to a bulkRequest. An appropriate
Index will be generated, however such a DataFrame is unlikely to
be useful unless the bulk data fields contain overlapping columns.
"""
response = self.sendRequest('ReferenceData', securities, fields, kwargs)
data = []
keys = []
for msg in response:
securityData = msg.getElement('securityData')
securityDataList = [securityData.getValueAsElement(i) for i in range(securityData.numValues())]
for sec in securityDataList:
fieldData = sec.getElement('fieldData')
fieldDataList = [fieldData.getElement(i) for i in range(fieldData.numElements())]
df = DataFrame()
for fld in fieldDataList:
for v in [fld.getValueAsElement(i) for i in range(fld.numValues())]:
s = Series()
for d in [v.getElement(i) for i in range(v.numElements())]:
s[str(d.name())] = d.getValue()
df = df.append(s, ignore_index=True)
if not df.empty:
keys.append(sec.getElementAsString('security'))
data.append(df.set_index(df.columns[0]))
if len(data) == 0:
return DataFrame()
if type(securities) == str:
data = pd.concat(data, axis=1)
data.columns.name = 'Field'
else:
data = pd.concat(data, keys=keys, axis=0, names=['Security',data[0].index.name])
return data
def sendRequest (self, requestType, securities, fields, overridesfieldsId, overridesfieldsVal, elements):
""" Prepares and sends a request then blocks until it can return
the complete response.
Depending on the complexity of your request, incomplete and/or
unrelated messages may be returned as part of the response.
"""
request = self.refDataService.createRequest(requestType + 'Request')
if type(securities) == str:
securities = [securities]
if type(fields) == str:
fields = [fields]
if type(overridesfieldsId) == str:
overridesfieldsId = [overridesfieldsId]
if type(overridesfieldsVal) == str:
overridesfieldsVal = [overridesfieldsVal]
ovr = request.getElement("overrides").appendElement()
for s in securities:
request.getElement("securities").appendValue(s)
for f in fields:
request.getElement("fields").appendValue(f)
for oi in overridesfieldsId:
ovr.setElement("fieldId",str(oi))
for ov in overridesfieldsVal:
ovr.setElement("value",ov)
for k, v in elements.items():
if type(v) == datetime:
v = v.strftime('%Y%m%d')
request.set(k, v)
print(overridesfieldsId)
self.session.sendRequest(request)
response = []
while True:
event = self.session.nextEvent(100)
for msg in event:
if msg.hasElement('responseError'):
raise RequestError(msg.getElement('responseError'), 'Response Error')
if msg.hasElement('securityData'):
if msg.getElement('securityData').hasElement('fieldExceptions') and (msg.getElement('securityData').getElement('fieldExceptions').numValues() > 0):
raise RequestError(msg.getElement('securityData').getElement('fieldExceptions'), 'Field Error')
if msg.getElement('securityData').hasElement('securityError'):
raise RequestError(msg.getElement('securityData').getElement('securityError'), 'Security Error')
if msg.messageType() == requestType + 'Response':
response.append(msg)
if event.eventType() == blpapi.Event.RESPONSE:
break
return response
def __enter__ (self):
self.open()
return self
def __exit__ (self, exc_type, exc_val, exc_tb):
self.close()
def __del__ (self):
self.close()
def main(): """ Basic usage examples.
Note that if any tickers have changed since these examples were written
a RequestError will be raised.
"""
try:
blp = BLPInterface()
# ==============================
# = HistoricalRequest Examples =
#===============================
# Requesting a single security and field returns a simple DataFrame.
# print (blp.historicalRequest('BMO CN Equity', 'PX_LAST', '20141231', '20150131'))
# Requesting multiple fields returns a DataFrame with multiple columns. Dates may also be passed as a datetime.
# print (blp.historicalRequest('BNS CN Equity', ['PX_LAST', 'PX_VOLUME'], datetime(2014, 12, 31), datetime(2015, 1, 31)))
# Requesting multiple securities returns a DataFrame with a MultiIndex.
df = blp.referenceRequest_override(['C13 FP Equity'], ['MAXIMUM_DRAWDOWN_PCT','INTERVAL_PERCENT_CHANGE'],['RISK_MEASURES_TIME_FRAME','CALC_INTERVAL'],['4','2'])
print(df)
#df = blp.historicalRequest(['CM CN Equity'], ['PX_LAST'], '20141231', '20150131')
#print(df)
#df=df.iloc[:, df.columns.get_level_values(0)=='CM CN Equity']
# aa = df.iloc[:, df.columns.get_level_values(1)=='PX_LAST']
# print(aa.pct_change())
# You may force any DataFrame to include a MultiIndex by passing the arguments as lists.
# print (blp.historicalRequest(['NA CN Equity'], ['PX_LAST'], '20141231', '20150131'))
#
# # Keyword arguments are added to the request, allowing you to perform advanced queries.
# print (blp.historicalRequest('TD CN Equity', 'PCT_CHG_INSIDER_HOLDINGS', '20141231', '20150131', periodicitySelection='WEEKLY'))
blp.close()
# The BLPInterface Class can also be used as a ContextManager.
# with BLPInterface() as blp:
# =============================
# = ReferenceRequest Examples =
# =============================
# Requesting a single security/field will return the single value, not a DataFrame.
# # print (blp.referenceRequest('BBD/B CN Equity', 'GICS_SECTOR'))
#
# # Requesting multiple securities or fields will return a DataFrame.
# print (blp.referenceRequest(['CNR CN Equity', 'CP CN Equity'], ['SECURITY_NAME_REALTIME', 'LAST_PRICE']))
#
# # You may force any request to return a DataFrame by passing the arguments as lists.
# print (blp.referenceRequest(['MDA CN Equity'], ['NAME_RT']))
#
# # ========================
# # = BulkRequest Examples =
# # ========================
# # Requesting a single security and field will return a DataFrame.
# print (blp.bulkRequest('CIG CN Equity','EQY_DVD_ADJUST_FACT'))
#
# You may request multiple securities and/or fields.
# This feature is generally not useful as the resulting DataFrame is ugly.
# print (blp.bulkRequest(['CP CN Equity','CNR CN Equity'],'PG_REVENUE'))
# print (blp.bulkRequest('CIG CN Equity',['EQY_DVD_ADJUST_FACT','DVD_HIST_ALL']))
except RequestError as e:
print (e.value)
raise
if name == "main": try: main() except KeyboardInterrupt: print ("Ctrl+C pressed. Stopping...")`
But, my problem is that i can't send multi overrides, do you have idea for to adjust your code and my code ?
Thanks you for your time and your help !
I modified the SendResquest **
You cannot sent multi-overrides because Bloomberg does not accept multi-overrides. Even if you append multiple copies of the same fieldId to the overrides element Bloomberg will just ignore all but the last one.
https://data.bloomberglp.com/labs/sites/2/2014/07/blpapi-developers-guide-2.54.pdf
Hi,
I find this solution to have request with Overrides. But, i would like put the hour in my request BDH Because i want the OPEN price between hours for example 20200219 at 11:00:00 It's possible ?
Thanks you !
` import socket import itertools from datetime import datetime, date, time from collections import Counter import pandas as pd import numpy as np from pandas import Series from pandas import DataFrame
BLP_HOST = 'localhost' BLP_PORT = 8194 PROXY_HOST = '' PROXY_PORT = 5001
class RequestError(Exception): """A RequestError is raised when there is a problem with a Bloomberg API response.""" def init(self, description, value=None): self.value = value self.description = description
def __str__(self):
if self.value is not None:
return self.description + '\n' + self.value
return self.description
def _uwrap(s): """Helper function to convert a string or list into a list of unique entries.""" s = [s] if isinstance(s, str) else s return list(set(s))
def _convertDate(d): """Helper function to convert dates and datetimes into blpapi strings.""" if isinstance(d, np.datetime64): d = pd.Timestamp(d) elif isinstance(d, pd.Period): d = d.to_timestamp(freq='D')
if isinstance(d, date):
if isinstance(d, datetime) and (d.time() != time(0)):
return d.strftime('%Y-%m-%dT%H:%M:%S')
else:
return d.strftime('%Y%m%d')
return d
try:
import blpapi
# The Bloomberg API was successfully imported - Create the normal
# BLPInterface class.
DEFAULT_HOST = BLP_HOST
DEFAULT_PORT = BLP_PORT
class BLPInterface:
""" A wrapper for the Bloomberg API that returns DataFrames. This class
manages a //BLP/refdata service and therefore does not handle event
subscriptions.
All calls are blocking and responses are parsed and returned as
DataFrames where appropriate.
A RequestError is raised when an invalid security is queried. Invalid
fields will fail silently and may result in an empty DataFrame.
"""
# noinspection PyShadowingBuiltins
def __init__(self, host=BLP_HOST, port=BLP_PORT, open=True):
self.active = False
self.host = host
self.port = port
self.session = None
self.refDataService = None
if open:
self.open()
def open(self):
if not self.active:
sessionOptions = blpapi.SessionOptions()
sessionOptions.setServerHost(self.host)
sessionOptions.setServerPort(self.port)
sessionOptions.setAutoRestartOnDisconnection(True)
self.session = blpapi.Session(sessionOptions)
if (not self.session.start()) or (not self.session.openService("//blp/refdata")):
raise RequestError('Failed to start session')
self.refDataService = self.session.getService('//BLP/refdata')
self.active = True
def close(self):
if self.active:
self.session.stop()
self.active = False
def historicalRequest(self, securities, fields, startDate, endDate='', overrides=None, **kwargs):
""" Equivalent to the Excel BDH Function.
If securities are provided as a list, the returned DataFrame will
have a MultiIndex.
StartDate and endDate should be a datetime.date or YYYYMMDD string.
Datetimes or Timestamps with a non-zero time component will not be
recognized correctly by the Bloomberg API.
Useful kwargs are periodicitySelection, adjustmentNormal,
adjustmentAbnormal, adjustmentSplit, and currency.
"""
defaults = {'startDate' : startDate.replace('-', '') if isinstance(startDate, str) else startDate,
'endDate' : endDate.replace('-', '') if isinstance(endDate, str) else endDate,
'periodicityAdjustment' : 'CALENDAR',
'periodicitySelection' : 'DAILY',
'nonTradingDayFillOption' : 'NON_TRADING_WEEKDAYS',
'adjustmentNormal' : False,
'adjustmentAbnormal' : False,
'adjustmentSplit' : True,
'adjustmentFollowDPDF' : False}
defaults.update(kwargs)
usecurities = _uwrap(securities)
ufields = _uwrap(fields)
response = self.sendRequest('HistoricalData', usecurities, ufields, overrides, defaults)
data = []
keys = []
for msg in response:
securityData = msg.getElement('securityData')
fieldData = securityData.getElement('fieldData')
fieldDataList = [fieldData.getValueAsElement(i) for i in range(fieldData.numValues())]
df = DataFrame(columns=ufields)
for fld in fieldDataList:
for v in [fld.getElement(i) for i in range(fld.numElements())
if fld.getElement(i).name() != 'date']:
df.ix[fld.getElementAsDatetime('date'), str(v.name())] = v.getValue()
df.index = pd.to_datetime(df.index)
df.replace('#N/A History', np.nan, inplace=True)
keys.append(securityData.getElementAsString('security'))
data.append(df)
if len(data) == 0:
return DataFrame()
else:
data = pd.concat(data, keys=keys, axis=1, names=['Security', 'Field']).sort_index()
data.index.name = 'Date'
if isinstance(securities, str) and isinstance(fields, str):
data = data.iloc[:,0]
data.name = fields
elif isinstance(securities, str):
data.columns = data.columns.droplevel('Security')
data = data[fields]
elif isinstance(fields, str):
data.columns = data.columns.droplevel('Field')
data = data[securities]
else:
data = data[list(itertools.product(securities, fields))]
return data
def referenceRequest(self, securities, fields, overrides=None, **kwargs):
""" Equivalent to the Excel BDP Function.
If either securities or fields are provided as lists, a DataFrame
will be returned.
"""
usecurities = _uwrap(securities)
ufields = _uwrap(fields)
response = self.sendRequest('ReferenceData', usecurities, ufields, overrides, kwargs)
data = DataFrame(index=usecurities, columns=ufields)
for msg in response:
securityData = msg.getElement('securityData')
securityDataList = [securityData.getValueAsElement(i) for i in range(securityData.numValues())]
for sec in securityDataList:
fieldData = sec.getElement('fieldData')
fieldDataList = [fieldData.getElement(i) for i in range(fieldData.numElements())]
for fld in fieldDataList:
data.ix[sec.getElementAsString('security'), str(fld.name())] = fld.getValue()
if data.empty:
return DataFrame()
else:
data.index.name = 'Security'
data.columns.name = 'Field'
if isinstance(securities, str) and isinstance(fields, str):
data = data.iloc[0, 0]
elif isinstance(securities, str):
data = data.iloc[0, :][fields]
elif isinstance(fields, str):
data = data.iloc[:, 0][securities]
else:
data = data.loc[securities, fields]
return data
def bulkRequest(self, securities, fields, overrides=None, **kwargs):
""" Equivalent to the Excel BDS Function.
If securities are provided as a list, the returned DataFrame will
have a MultiIndex.
You may also pass a list of fields to a bulkRequest. An appropriate
MultiIndex will be generated, however such a DataFrame is unlikely
to be useful unless the bulk data fields contain overlapping columns.
"""
response = self.sendRequest('ReferenceData', securities, fields, overrides, kwargs)
data = []
keys = []
for msg in response:
securityData = msg.getElement('securityData')
securityDataList = [securityData.getValueAsElement(i) for i in range(securityData.numValues())]
for sec in securityDataList:
fieldData = sec.getElement('fieldData')
fieldDataList = [fieldData.getElement(i) for i in range(fieldData.numElements())]
fldData = []
fldKeys = []
for fld in fieldDataList:
df = DataFrame()
for v in [fld.getValueAsElement(i) for i in range(fld.numValues())]:
s = Series()
for d in [v.getElement(i) for i in range(v.numElements())]:
try:
s[str(d.name())] = d.getValue()
except:
# There is seriously no end to the shit getValue() can raise.
pass
# Bloomberg returns this magic number instead of NaN for certain bulk fields.
df = df.append(s.where(s != -2.4245362661989844e-14, np.nan), ignore_index=True)
try:
df = df.set_index(df.columns[0])
if not df.empty:
fldKeys.append(str(fld.name()))
fldData.append(df)
except IndexError:
pass
if fldData:
keys.append(sec.getElementAsString('security'))
data.append(pd.concat(fldData, keys=fldKeys, names=['Field']))
if data:
data = pd.concat(data, keys=keys, names=['Security'])
data.columns.name = 'Element'
else:
return DataFrame()
if isinstance(securities, str) and isinstance(fields, str):
data = data.reset_index(['Security', 'Field'], drop=True)
elif isinstance(securities, str):
data = data.reset_index('Security', drop=True)
elif isinstance(fields, str):
data = data.reset_index('Field', drop=True)
return data
def portfolioDataRequest(self, securities, fields, overrides=None, **kwargs):
response = self.sendRequest('PortfolioData', securities, fields, overrides, kwargs)
# TODO: Read exactly like bulkrequest
return response
def intradayBarRequest(self, security, startDate, endDate, **kwargs):
""" Performs an IntradayBarRequest.
IntradayBarRequests can only include a single security and will
return a predefined set of fields. The granularity of this
request can be set via the interval parameter in minutes.
To receive data, startDate and endDate must include a UTC time.
"""
defaults = {'startDateTime' : startDate,
'endDateTime' : endDate,
'eventType' : 'TRADE',
'interval' : 5,
'adjustmentNormal' : False,
'adjustmentAbnormal' : False,
'adjustmentSplit' : True,
'adjustmentFollowDPDF' : False}
defaults.update(kwargs)
response = self.sendRequest('IntradayBar', security, [], None, defaults)
data = DataFrame()
for msg in response:
tickData = msg.getElement('barData').getElement('barTickData')
tickDataList = [tickData.getValueAsElement(i) for i in range(tickData.numValues())]
for tick in tickDataList:
dt = tick.getElementAsDatetime('time').replace(tzinfo=None)
for v in [tick.getElement(i) for i in range(1, tick.numElements())]:
# Get every value as a string and cast to the apropriate type later
# This is pretty dirty but network latency dominates the runtime of this function
data.ix[dt, str(v.name())] = v.getValueAsString()
data.index.name = 'Date'
return data.apply(pd.to_numeric, errors='coerce').sort_index()
def intradayTickRequest(self, security, startDate, endDate, **kwargs):
""" Performs an IntradayTickRequest.
IntradayTickRequests can only include a single security and will
return a predefined set of fields.
To receive data, startDate and endDate must include a UTC time.
"""
defaults = {'startDateTime' : startDate,
'endDateTime' : endDate,
'eventTypes' : ['TRADE']}
defaults.update(kwargs)
response = self.sendRequest('IntradayTick', security, [], None, defaults)
data = DataFrame()
for msg in response:
tickData = msg.getElement('tickData').getElement('tickData')
tickDataList = [tickData.getValueAsElement(i) for i in range(tickData.numValues())]
for tick in tickDataList:
dt = tick.getElementAsDatetime('time').replace(tzinfo=None)
for v in [tick.getElement(i) for i in range(1, tick.numElements())]:
data.ix[dt, str(v.name())] = v.getValueAsString()
data.index.name = 'Date'
return data.apply(pd.to_numeric, errors='coerce').sort_index()
def sendRequest(self, requestType, securities, fields, overrides, elements):
""" Prepares and sends a request then blocks until it can return
the complete response.
Depending on the complexity of your request, incomplete and/or
unrelated messages may be returned as part of the response.
"""
request = self.refDataService.createRequest(requestType + 'Request')
if isinstance(securities, str):
securities = [securities]
if isinstance(fields, str):
fields = [fields]
for s in securities:
try:
request.getElement("securities").appendValue(s)
except:
request.set('security', s)
for f in fields:
request.getElement("fields").appendValue(f)
for k, v in elements.items():
if isinstance(v, list):
for i in v:
request.getElement(k).appendValue(_convertDate(i))
else:
request.set(k, _convertDate(v))
if overrides is not None:
for k, v in overrides.items():
ovr = request.getElement('overrides').appendElement()
ovr.setElement("fieldId", str(k))
ovr.setElement('value', str(_convertDate(v)))
self.session.sendRequest(request)
response = []
while True:
event = self.session.nextEvent(100)
for msg in event:
if msg.hasElement('responseError'):
raise RequestError('Response Error', str(msg.getElement('responseError')))
if msg.hasElement('securityData'):
if msg.getElement('securityData').hasElement('fieldExceptions') and\
(msg.getElement('securityData').getElement('fieldExceptions').numValues() > 0):
raise RequestError('Field Error', str(msg.getElement('securityData').getElement('fieldExceptions')))
if msg.getElement('securityData').hasElement('securityError'):
raise RequestError('Security Error', str(msg.getElement('securityData').getElement('securityError')))
if msg.messageType() == requestType + 'Response':
response.append(msg)
if event.eventType() == blpapi.Event.RESPONSE:
break
return response
def __enter__(self):
self.open()
return self
# noinspection PyUnusedLocal
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def __del__(self):
self.close()
except ImportError:
# instead.
from rqm.source import net
DEFAULT_HOST = PROXY_HOST
DEFAULT_PORT = PROXY_PORT
class BLPInterface:
""" A wrapper for the Bloomberg API that returns DataFrames. This is
the Proxy version of the BLPInterface and was created as the
current environment does not have Bloomberg access.
All requests will be forwarded to (host, port). Run BLPServer.py
on a computer to fulfil requests.
All calls are blocking and responses are parsed and returned as
DataFrames where appropriate.
"""
# noinspection PyShadowingBuiltins
def __init__(self, host=PROXY_HOST, port=PROXY_PORT, open=True):
self.active = False
self.host = host
self.port = port
self.socket = None
if open:
self.open()
def open(self):
if not self.active:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(60)
self.socket.connect((self.host, self.port))
self.active = True
def historicalRequest(self, securities, fields, startDate, endDate='', overrides=None, **kwargs):
kwargs['securities'] = securities
kwargs['fields'] = fields
kwargs['startDate'] = startDate
kwargs['endDate'] = endDate
kwargs['overrides'] = overrides
return self.sendRequest('historicalRequest', kwargs)
def referenceRequest(self, securities, fields, overrides=None, **kwargs):
kwargs['securities'] = securities
kwargs['fields'] = fields
kwargs['overrides'] = overrides
return self.sendRequest('referenceRequest', kwargs)
def bulkRequest(self, securities, fields, overrides=None, **kwargs):
kwargs['securities'] = securities
kwargs['fields'] = fields
kwargs['overrides'] = overrides
return self.sendRequest('bulkRequest', kwargs)
def intradayBarRequest(self, security, startDate, endDate, **kwargs):
kwargs['security'] = security
kwargs['startDate'] = startDate
kwargs['endDate'] = endDate
return self.sendRequest('intradayBarRequest', kwargs)
def intradayTickRequest(self, security, startDate, endDate, **kwargs):
kwargs['security'] = security
kwargs['startDate'] = startDate
kwargs['endDate'] = endDate
return self.sendRequest('intradayTickRequest', kwargs)
# noinspection PyTypeChecker
def sendRequest(self, requestType, arguments):
net.sendObject(self.socket, [requestType, arguments])
return net.receiveObject(self.socket)
def close(self):
if self.active:
self.socket.close()
self.active = False
def __enter__(self):
self.open()
return self
# noinspection PyUnusedLocal
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def __del__(self):
self.close()
def bdp(securities, fields): blp = BLPInterface() if type(fields) is dict: return overrides(securities, fields) else: return blp.referenceRequest(securities,fields)
def overrides(liste_tickers,dict_bloom):
df = []
# Incrementation des tableau en attente
c = 0
# Fields
fields_bm = dict_bloom['field']
# Fields sans overrides
fields_overrides = dict_bloom['field_overrides']
#Doublon total
doublon_total= []
for i in fields_overrides.keys():
pending = [k for k,v in Counter(fields_overrides[i][0]).items() if v>1]
if pending != []:
doublon_total.append(pending)
# On définis si c'est un appel avec ou sans overrides
if len(fields_overrides.keys()) !=0:
# --------On divise en deux le dictionnaire pour extraite les fields et les fields avec override-------------------------------
# Liste des fields avec overrides
list_fields_overrides = [i for i in fields_overrides.keys()]
# Liste des fields qui n'ont pas d'overrides
Liste_fields_whitoutoverrides= [i for i in fields_bm if i not in list_fields_overrides]
# Keys des dictionnaire
for i in fields_overrides.keys():
list_doublon = [k for k,v in Counter(fields_overrides[i][0]).items() if v>1]
# Doublons
if len(list_doublon) >= 1:
# On définis les éléments en double
overrides_duplicate = [doublon_in_list for doublon_in_list in list_doublon]
# Liste
List = []
Liste_value_whitoutoverrides = []
Liste_overrides_whitoutoverrides = []
Liste_fields_whitoverrides = []
# Liste des overrides
List = fields_overrides[i][0]
#Localise les doublons pour appeler leurs valeurs
idx = [i for i, val in enumerate(List) if val in overrides_duplicate]
# Liste Overrides
Liste_overrides_whitoutoverrides = List
Liste_overrides_whitoutoverrides = [v for i,v in enumerate(Liste_overrides_whitoutoverrides) if i not in idx]
# Liste Value
Liste_value_whitoutoverrides = fields_overrides[i][1]
Liste_value_whitoutoverrides = [v for i,v in enumerate(Liste_value_whitoutoverrides) if i not in idx]
# Appel Bloom
for x in idx:
Liste_overrides_whitoutoverrides.append(fields_overrides[i][0][x])
Liste_value_whitoutoverrides.append(fields_overrides[i][1][x])
if i in list_fields_overrides:
Liste_fields_whitoverrides.append(i)
# Appel Blom
fields = Liste_fields_whitoverrides
overrides = {Liste_overrides_whitoutoverrides[i]: Liste_value_whitoutoverrides[i] for i in range(len(Liste_overrides_whitoutoverrides))}
# df[c] = blp.referenceRequest(liste_tickers, fields,overrides=overrides)
df.append(c)
df[c] = blp.referenceRequest(liste_tickers, fields,overrides=overrides)
if c == 0:
df_bloom = df[c]
name = str(i) + str(fields_overrides[i][1][x])
df_bloom = df_bloom.rename(columns={i: name})
else:
df_bloom = pd.concat([df_bloom, df[c]], axis=1, sort=False)
name = str(i) + str(fields_overrides[i][1][x])
df_bloom = df_bloom.rename(columns={i: name})
df_bloom = df_bloom.T.drop_duplicates().T
c = c + 1
# Nettoyage des list
Liste_overrides_whitoutoverrides.remove(fields_overrides[i][0][x])
Liste_value_whitoutoverrides.remove(fields_overrides[i][1][x])
Liste_fields_whitoverrides = []
one_duplicate = 3
#Si aucun overrides en double, on fait un seul appel
elif len(list_doublon) >= 0:
fields = [i] + Liste_fields_whitoutoverrides
ovrd = fields_overrides[i][0]
val = fields_overrides[i][1]
overrides = dict(zip(ovrd, val))
if doublon_total == []:
fields = dict_bloom['field']
df_bloom = blp.referenceRequest(liste_tickers, fields,overrides=overrides)
one_duplicate = 4
else:
call = blp.referenceRequest(liste_tickers, fields,overrides=overrides)
try:
df_bloom_whitout_overrides = pd.concat([df_bloom, call], axis=1, sort=False)
one_duplicate = 2
except:
df_bloom_whitout_overrides = call
print('ij')
one_duplicate = 1
if one_duplicate == 1:
df_bloom = pd.concat([df_bloom, df_bloom_whitout_overrides], axis=1, sort=False)
df_bloom = df_bloom.T.drop_duplicates().T
elif one_duplicate == 2:
df_bloom = pd.concat([df_bloom, df_bloom_whitout_overrides], axis=1, sort=False)
df_bloom = df_bloom.T.drop_duplicates().T
elif one_duplicate == 3:
df_bloom_whitout_overrides = blp.referenceRequest(liste_tickers, Liste_fields_whitoutoverrides)
df_bloom = pd.concat([df_bloom, df_bloom_whitout_overrides], axis=1, sort=False)
df_bloom = df_bloom.T.drop_duplicates().T
elif one_duplicate == 4:
df_bloom = df_bloom
return df_bloom
blp = BLPInterface()
a = {'field': ['INTERVAL_START_VALUE'], 'field_overrides': { 'INTERVAL_START_VALUE': [['END_DATE_OVERRIDE','START_DATE_OVERRIDE'], ['20200210','20190210']]}} print(bdp(['ESH0 Index'],a))
blp.close()
`
Hello,
Thanks you for you code, but i would like to use referenceRequest with Override, i try many solution but i don't find the solution. Do you have idea for to resolve the problem ?
Thanks you for your time !