Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SECF() implementation #50

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions pdblp/pdblp.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,20 @@ def _init_services(self):
raise ConnectionError("Could not open a //blp/exrsvc service")
self.exrService = self._session.getService("//blp/exrsvc")

opened = self._session.openService("//blp/instruments")
ev = self._session.nextEvent()
ev_name = _EVENT_DICT[ev.eventType()]
logger.info("Event Type: %s" % ev_name)
for msg in ev:
logger.info("Message Received:\n%s" % msg)
if ev.eventType() != blpapi.Event.SERVICE_STATUS:
raise RuntimeError("Expected a SERVICE_STATUS event but "
"received a %s" % ev_name)
if not opened:
logger.warning("Failed to open //blp/exrsvc")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be logger.warning("Failed to //blp/instruments")

raise ConnectionError("Could not open a //blp/instruments service")
self.instrService = self._session.getService("//blp/instruments")

return self

def _create_req(self, rtype, tickers, flds, ovrds, setvals):
Expand Down Expand Up @@ -731,6 +745,44 @@ def bsrch(self, domain):
data.append(f.getElementAsString("StringValue"))
return pd.DataFrame(data)

def secf(self, query, max_results=10, yk_filter="NONE"):
"""
This function uses the Bloomberg API to retrieve Bloomberg
SECF Data queries. Returns list of tickers.

Parameters
----------
query: string
A character string representing the desired query. Example "IBM"
max_results: int
Maximum number of results to return. Default 10.
yk_filter: string
A character string respresenting a Bloomberg yellow-key to limit
search results to. Valid values are: CMDT, EQTY, MUNI,
PRFD, CLNT, MMKT, GOVT, CORP, INDX, CURR, MTGE. Default NONE.

Returns
-------
data: list
List of bloomberg tickers from the SECF function
"""
logger = _get_logger(self.debug)
request = self.instrService.createRequest("instrumentListRequest")
request.set("query", query)
request.set("maxResults", max_results)
request.set("yellowKeyFilter", "YK_FILTER_%s" % yk_filter)
Copy link
Owner

@matthewgilbert matthewgilbert Oct 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think to be consistent with how parameters are set elsewhere in the library, this convenience string concatenation should not be done for the user, e.g. the user should pass YK_FILTER_EQTY and this line should be changed to request.set("yellowKeyFilter", yk_filter). Also while it does appear that YK_FILTER_NONE is supported but seems superfluous? I think it would be better stylistically to have yk_filter=None as a default parameter and then

if yk_filter:
    request.set("yellowKeyFilter", yk_filter)

logger.info("Sending Request:\n%s" % request)
self._session.sendRequest(request, identity=self._identity)
data = []
for msg in self._receive_events():
for r in msg.getElement("results").values():
ticker = r.getElementAsString("security")
ticker = ticker.replace('<', ' ').replace('>', '').upper()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to leave this line out. The general philosophy of pdblp is to provide a thin wrapper around blpapi and limit the data processing. If a user wants this they can do it easily enough afterwords using df.ticker.str.replace("<", "").str.replace(">", "").str.upper()

descr = r.getElementAsString("description")
if not descr.endswith('(Multiple Matches)'):
Copy link
Owner

@matthewgilbert matthewgilbert Oct 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly is the check for Multiple Matches doing? Is there a sample request you could add in the thread so I can see when this is used?

data.append(ticker)
return data

def stop(self):
"""
Close the blp session
Expand Down