Пример #1
0
    def market_normal(self, session, after_open, before_close) -> Session:
        """
        Time intervals between market

        Args:
            session: [allday, day, am, pm, night]
            after_open: mins after open
            before_close: mins before close

        Returns:
            Session of start_time and end_time
        """
        logger = logs.get_logger(self.market_normal)

        if session not in self.exch: return SessNA
        ss = self.exch[session]

        s_time = shift_time(ss[0], int(after_open) + 1)
        e_time = shift_time(ss[-1], -int(before_close))

        request_cross = pd.Timestamp(s_time) >= pd.Timestamp(e_time)
        session_cross = pd.Timestamp(ss[0]) >= pd.Timestamp(ss[1])
        if request_cross and (not session_cross):
            logger.warning(f'end time {e_time} is earlier than {s_time} ...')
            return SessNA

        return Session(s_time, e_time)
Пример #2
0
def subscribe(tickers, flds=None, identity=None, options=None, **kwargs):
    """
    Subscribe Bloomberg realtime data

    Args:
        tickers: list of tickers
        flds: fields to subscribe, default: Last_Price, Bid, Ask
        identity: Bloomberg identity
    """
    logger = logs.get_logger(subscribe, **kwargs)
    if isinstance(tickers, str): tickers = [tickers]
    if flds is None: flds = ['Last_Price', 'Bid', 'Ask']
    if isinstance(flds, str): flds = [flds]

    sub_list = conn.blpapi.SubscriptionList()
    for ticker in tickers:
        topic = f'//blp/mktdata/{ticker}'
        cid = conn.blpapi.CorrelationId(ticker)
        logger.debug(f'Subscribing {cid} => {topic}')
        sub_list.add(topic, flds, correlationId=cid, options=options)

    try:
        conn.bbg_session(**kwargs).subscribe(sub_list, identity)
        yield
    finally:
        conn.bbg_session(**kwargs).unsubscribe(sub_list)
Пример #3
0
def latest_file(path_name, keyword='', ext='', **kwargs) -> str:
    """
    Latest modified file in folder

    Args:
        path_name: full path name
        keyword: keyword to search
        ext: file extension

    Returns:
        str: latest file name
    """
    files = all_files(path_name=path_name,
                      keyword=keyword,
                      ext=ext,
                      full_path=True)

    if not files:
        from xbbg.io import logs

        logger = logs.get_logger(latest_file,
                                 level=kwargs.pop('log', 'warning'))
        logger.debug(f'file is not found in folder: {path_name}')
        return ''

    modified_time = [os.path.getmtime(f) for f in files]
    files = [f for (dt, f) in sorted(zip(modified_time, files))]

    return files[-1]
Пример #4
0
def bbg_service(service: str, **kwargs) -> blpapi.service.Service:
    """
    Initiate service

    Args:
        service: service name
        **kwargs:
            port: port number

    Returns:
        Bloomberg service
    """
    logger = logs.get_logger(bbg_service, **kwargs)

    port = kwargs.get('port', _PORT_)
    serv_sym = f'{_CON_SYM_}/{port}{service}'

    log_info = f'Initiating service {service} ...'
    if serv_sym in globals():
        if getattr(globals()[serv_sym], '_Service__handle', None) is None:
            log_info = f'Restarting service {service} ...'
            del globals()[serv_sym]

    if serv_sym not in globals():
        logger.debug(log_info)
        bbg_session(**kwargs).openService(service)
        globals()[serv_sym] = bbg_session(**kwargs).getService(service)

    return globals()[serv_sym]
Пример #5
0
def tz_convert(dt, to_tz, from_tz=None) -> str:
    """
    Convert to tz

    Args:
        dt: date time
        to_tz: to tz
        from_tz: from tz - will be ignored if tz from dt is given

    Returns:
        str: date & time

    Examples:
        >>> dt_1 = pd.Timestamp('2018-09-10 16:00', tz='Asia/Hong_Kong')
        >>> tz_convert(dt_1, to_tz='NY')
        '2018-09-10 04:00:00-04:00'
        >>> dt_2 = pd.Timestamp('2018-01-10 16:00')
        >>> tz_convert(dt_2, to_tz='HK', from_tz='NY')
        '2018-01-11 05:00:00+08:00'
        >>> dt_3 = '2018-09-10 15:00'
        >>> tz_convert(dt_3, to_tz='NY', from_tz='JP')
        '2018-09-10 02:00:00-04:00'
    """
    logger = logs.get_logger(tz_convert, level='debug')
    f_tz, t_tz = get_tz(from_tz), get_tz(to_tz)

    from_dt = pd.Timestamp(str(dt), tz=f_tz)
    logger.debug(f'converting {str(from_dt)} from {f_tz} to {t_tz} ...')
    return str(pd.Timestamp(str(from_dt), tz=t_tz))
Пример #6
0
def bdh(tickers,
        flds=None,
        start_date=None,
        end_date='today',
        adjust=None,
        **kwargs) -> pd.DataFrame:
    """
    Bloomberg historical data

    Args:
        tickers: ticker(s)
        flds: field(s)
        start_date: start date
        end_date: end date - default today
        adjust: `all`, `dvd`, `normal`, `abn` (=abnormal), `split`, `-` or None
                exact match of above words will adjust for corresponding events
                Case 0: `-` no adjustment for dividend or split
                Case 1: `dvd` or `normal|abn` will adjust for all dividends except splits
                Case 2: `adjust` will adjust for splits and ignore all dividends
                Case 3: `all` == `dvd|split` == adjust for all
                Case 4: None == Bloomberg default OR use kwargs
        **kwargs: overrides

    Returns:
        pd.DataFrame
    """
    logger = logs.get_logger(bdh, **kwargs)

    if flds is None: flds = ['Last_Price']
    e_dt = utils.fmt_dt(end_date, fmt='%Y%m%d')
    if start_date is None:
        start_date = pd.Timestamp(e_dt) - pd.Timedelta(weeks=8)
    s_dt = utils.fmt_dt(start_date, fmt='%Y%m%d')

    request = process.create_request(
        service='//blp/refdata',
        request='HistoricalDataRequest',
        **kwargs,
    )
    process.init_request(request=request,
                         tickers=tickers,
                         flds=flds,
                         start_date=s_dt,
                         end_date=e_dt,
                         adjust=adjust,
                         **kwargs)
    logger.debug(f'Sending request to Bloomberg ...\n{request}')
    conn.send_request(request=request, **kwargs)

    res = pd.DataFrame(process.rec_events(process.process_hist, **kwargs))
    if kwargs.get('raw', False): return res
    if res.empty or any(fld not in res for fld in ['ticker', 'date']):
        return pd.DataFrame()

    return (res.set_index(['ticker', 'date']).unstack(level=0).rename_axis(
        index=None, columns=[None, None]).swaplevel(
            0, 1, axis=1).reindex(columns=utils.flatten(tickers),
                                  level=0).reindex(columns=utils.flatten(flds),
                                                   level=1))
Пример #7
0
def fut_ticker(gen_ticker: str, dt, freq: str, log=logs.LOG_LEVEL):
    """
    Get proper ticker from generic ticker

    Args:
        gen_ticker: generic ticker
        dt: date
        freq: futures contract frequency
        log: level of logs

    Returns:
        str: exact futures ticker
    """
    logger = logs.get_logger(fut_ticker, level=log)
    dt = pd.Timestamp(dt)
    t_info = gen_ticker.split()

    asset = t_info[-1]
    if asset in ['Index', 'Curncy', 'Comdty']:
        ticker = ' '.join(t_info[:-1])
        prefix, idx, postfix = ticker[:-1], int(ticker[-1]) - 1, asset

    elif asset == 'Equity':
        ticker = t_info[0]
        prefix, idx, postfix = ticker[:-1], int(ticker[-1]) - 1, ' '.join(t_info[1:])

    else:
        logger.error(f'unkonwn asset type for ticker: {gen_ticker}')
        return ''

    month_ext = 4 if asset == 'Comdty' else 2
    months = pd.DatetimeIndex(start=dt, periods=max(idx + month_ext, 3), freq=freq)
    logger.debug(f'pulling expiry dates for months: {months}')

    def to_fut(month):
        return prefix + const.Futures[month.strftime('%b')] + \
               month.strftime('%y')[-1] + ' ' + postfix

    fut = [to_fut(m) for m in months]
    logger.debug(f'trying futures: {fut}')
    # noinspection PyBroadException
    try:
        fut_matu = bdp(tickers=fut, flds='last_tradeable_dt', cache=True)
    except Exception as e1:
        logger.error(f'error downloading futures contracts (1st trial) {e1}:\n{fut}')
        # noinspection PyBroadException
        try:
            fut = fut[:-1]
            logger.debug(f'trying futures (2nd trial): {fut}')
            fut_matu = bdp(tickers=fut, flds='last_tradeable_dt', cache=True)
        except Exception as e2:
            logger.error(f'error downloading futures contracts (2nd trial) {e2}:\n{fut}')
            return ''

    sub_fut = fut_matu[pd.DatetimeIndex(fut_matu.value) > dt]
    logger.debug(f'futures full chain:\n{fut_matu.to_string()}')
    logger.debug(f'getting index {idx} from:\n{sub_fut.to_string()}')
    return sub_fut.ticker.values[idx]
Пример #8
0
def exch_info(ticker: str) -> pd.Series:
    """
    Exchange info for given ticker

    Args:
        ticker: ticker or exchange

    Returns:
        pd.Series

    Examples:
        >>> exch_info('SPY US Equity')
        tz        America/New_York
        allday      [04:00, 20:00]
        day         [09:30, 16:00]
        pre         [04:00, 09:30]
        post        [16:01, 20:00]
        dtype: object
        >>> exch_info('ES1 Index')
        tz        America/New_York
        allday      [18:00, 17:00]
        day         [08:00, 17:00]
        dtype: object
        >>> exch_info('Z 1 Index')
        tz         Europe/London
        allday    [01:00, 21:00]
        day       [01:00, 21:00]
        dtype: object
        >>> exch_info('TESTTICKER Corp').empty
        True
        >>> exch_info('US')
        tz        America/New_York
        allday      [04:00, 20:00]
        day         [09:30, 16:00]
        pre         [04:00, 09:30]
        post        [16:01, 20:00]
        dtype: object
    """
    logger = logs.get_logger(exch_info, level='debug')
    if ' ' not in ticker.strip():
        ticker = f'XYZ {ticker.strip()} Equity'
    info = param.load_info(cat='exch').get(
        market_info(ticker=ticker).get('exch', ''), dict())
    if ('allday' in info) and ('day' not in info):
        info['day'] = info['allday']

    if any(req not in info for req in ['tz', 'allday', 'day']):
        logger.error(f'required exchange info cannot be found in {ticker} ...')
        return pd.Series()

    for ss in ValidSessions:
        if ss not in info: continue
        info[ss] = [param.to_hour(num=s) for s in info[ss]]

    return pd.Series(info)
Пример #9
0
Файл: blp.py Проект: DT021/xbbg
def beqs(screen,
         asof=None,
         typ='PRIVATE',
         group='General',
         **kwargs) -> pd.DataFrame:
    """
    Bloomberg equity screening

    Args:
        screen: screen name
        asof: as of date
        typ: GLOBAL/B (Bloomberg) or PRIVATE/C (Custom, default)
        group: group name if screen is organized into groups

    Returns:
        pd.DataFrame
    """
    logger = logs.get_logger(beqs, **kwargs)

    service = conn.bbg_service(service='//blp/refdata', **kwargs)
    request = service.createRequest('BeqsRequest')

    request.set('screenName', screen)
    request.set('screenType',
                'GLOBAL' if typ[0].upper() in ['G', 'B'] else 'PRIVATE')
    request.set('Group', group)

    if asof:
        overrides = request.getElement('overrides')
        ovrd = overrides.appendElement()
        ovrd.setElement('fieldId', 'PiTDate')
        ovrd.setElement('value', utils.fmt_dt(asof, '%Y%m%d'))

    logger.debug(f'Sending request to Bloomberg ...\n{request}')
    conn.send_request(request=request, **kwargs)
    res = pd.DataFrame(process.rec_events(func=process.process_ref, **kwargs))
    if res.empty:
        if kwargs.get('trial', 0): return pd.DataFrame()
        else:
            return beqs(screen=screen,
                        asof=asof,
                        typ=typ,
                        group=group,
                        trial=1,
                        **kwargs)

    if kwargs.get('raw', False): return res
    cols = res.field.unique()
    return (res.set_index(['ticker', 'field']).unstack(level=1).rename_axis(
        index=None,
        columns=[None, None
                 ]).droplevel(axis=1,
                              level=0).loc[:,
                                           cols].pipe(pipeline.standard_cols))
Пример #10
0
Файл: blp.py Проект: DT021/xbbg
def bds(tickers, flds, **kwargs) -> pd.DataFrame:
    """
    Bloomberg block data

    Args:
        tickers: ticker(s)
        flds: field
        **kwargs: other overrides for query

    Returns:
        pd.DataFrame: block data
    """
    logger = logs.get_logger(bds, **kwargs)

    service = conn.bbg_service(service='//blp/refdata', **kwargs)
    request = service.createRequest('ReferenceDataRequest')

    if isinstance(tickers, str):
        data_file = storage.ref_file(ticker=tickers,
                                     fld=flds,
                                     has_date=True,
                                     ext='pkl',
                                     **kwargs)
        if files.exists(data_file):
            logger.debug(f'Loading Bloomberg data from: {data_file}')
            return pd.DataFrame(pd.read_pickle(data_file))

        process.init_request(request=request,
                             tickers=tickers,
                             flds=flds,
                             **kwargs)
        logger.debug(f'Sending request to Bloomberg ...\n{request}')
        conn.send_request(request=request, **kwargs)

        res = pd.DataFrame(
            process.rec_events(func=process.process_ref, **kwargs))
        if kwargs.get('raw', False): return res
        if res.empty or any(fld not in res for fld in ['ticker', 'field']):
            return pd.DataFrame()

        data = (res.set_index(['ticker', 'field']).droplevel(
            axis=0, level=1).rename_axis(index=None).pipe(
                pipeline.standard_cols, col_maps=kwargs.get('col_maps', None)))
        if data_file:
            logger.debug(f'Saving Bloomberg data to: {data_file}')
            files.create_folder(data_file, is_file=True)
            data.to_pickle(data_file)
        return data

    return pd.DataFrame(
        pd.concat(
            [bds(tickers=ticker, flds=flds, **kwargs) for ticker in tickers],
            sort=False))
Пример #11
0
Файл: conn.py Проект: DT021/xbbg
def connect_bbg(**kwargs) -> blpapi.session.Session:
    """
    Create Bloomberg session and make connection
    """
    logger = logs.get_logger(connect_bbg, **kwargs)

    sess_opts = blpapi.SessionOptions()
    sess_opts.setServerHost('localhost')
    sess_opts.setServerPort(kwargs.get('port', _PORT_))
    session = blpapi.Session(sess_opts)
    logger.debug('Connecting to Bloomberg ...')
    if session.start(): return session
    else: raise ConnectionError('Cannot connect to Bloomberg')
Пример #12
0
def ccy_pair(local, base='USD') -> CurrencyPair:
    """
    Currency pair info

    Args:
        local: local currency
        base: base currency

    Returns:
        CurrencyPair

    Examples:
        >>> ccy_pair(local='HKD', base='USD')
        CurrencyPair(ticker='HKD Curncy', factor=1.0, power=1)
        >>> ccy_pair(local='GBp')
        CurrencyPair(ticker='GBP Curncy', factor=100, power=-1)
        >>> ccy_pair(local='USD', base='GBp')
        CurrencyPair(ticker='GBP Curncy', factor=0.01, power=1)
        >>> ccy_pair(local='XYZ', base='USD')
        CurrencyPair(ticker='', factor=1.0, power=1)
        >>> ccy_pair(local='GBP', base='GBp')
        CurrencyPair(ticker='', factor=0.01, power=1)
        >>> ccy_pair(local='GBp', base='GBP')
        CurrencyPair(ticker='', factor=100.0, power=1)
    """
    ccy_param = param.load_info(cat='ccy')
    if f'{local}{base}' in ccy_param:
        info = ccy_param[f'{local}{base}']

    elif f'{base}{local}' in ccy_param:
        info = ccy_param[f'{base}{local}']
        info['factor'] = 1. / info.get('factor', 1.)
        info['power'] = -info.get('power', 1)

    elif base.lower() == local.lower():
        info = dict(ticker='')
        info['factor'] = 1.
        if base[-1].lower() == base[-1]:
            info['factor'] /= 100.
        if local[-1].lower() == local[-1]:
            info['factor'] *= 100.

    else:
        logger = logs.get_logger(ccy_pair)
        logger.error(f'incorrect currency - local {local} / base {base}')
        return CurrencyPair(ticker='', factor=1., power=1)

    if 'factor' not in info: info['factor'] = 1.
    if 'power' not in info: info['power'] = 1
    return CurrencyPair(**info)
Пример #13
0
def save_intraday(data: pd.DataFrame, ticker: str, dt, typ='TRADE', **kwargs):
    """
    Check whether data is done for the day and save

    Args:
        data: data
        ticker: ticker
        dt: date
        typ: [TRADE, BID, ASK, BID_BEST, ASK_BEST, BEST_BID, BEST_ASK]

    Examples:
        >>> os.environ['BBG_ROOT'] = 'xbbg/tests/data'
        >>> sample = pd.read_parquet('xbbg/tests/data/aapl.parq')
        >>> save_intraday(sample, 'AAPL US Equity', '2018-11-02')
        >>> # Invalid exchange
        >>> save_intraday(sample, 'AAPL XX Equity', '2018-11-02')
        >>> # Invalid empty data
        >>> save_intraday(pd.DataFrame(), 'AAPL US Equity', '2018-11-02')
        >>> # Invalid date - too close
        >>> cur_dt = utils.cur_time()
        >>> save_intraday(sample, 'AAPL US Equity', cur_dt)
    """
    cur_dt = pd.Timestamp(dt).strftime('%Y-%m-%d')
    logger = logs.get_logger(save_intraday, level='debug')
    info = f'{ticker} / {cur_dt} / {typ}'
    data_file = bar_file(ticker=ticker, dt=dt, typ=typ)
    if not data_file: return

    if data.empty:
        logger.warning(f'data is empty for {info} ...')
        return

    exch = const.exch_info(ticker=ticker, **kwargs)
    if exch.empty: return

    end_time = pd.Timestamp(
        const.market_timing(ticker=ticker, dt=dt, timing='FINISHED',
                            **kwargs)).tz_localize(exch.tz)
    now = pd.Timestamp('now', tz=exch.tz) - pd.Timedelta('1H')

    if end_time > now:
        logger.debug(
            f'skip saving cause market close ({end_time}) < now - 1H ({now}) ...'
        )
        return

    logger.info(f'saving data to {data_file} ...')
    files.create_folder(data_file, is_file=True)
    data.to_parquet(data_file)
Пример #14
0
def market_timing(ticker, dt, timing='EOD', tz='local') -> str:
    """
    Market close time for ticker

    Args:
        ticker: ticker name
        dt: date
        timing: [EOD (default), BOD]
        tz: conversion to timezone

    Returns:
        str: date & time

    Examples:
        >>> market_timing('7267 JT Equity', dt='2018-09-10')
        '2018-09-10 14:58'
        >>> market_timing('7267 JT Equity', dt='2018-09-10', tz=timezone.TimeZone.NY)
        '2018-09-10 01:58:00-04:00'
        >>> market_timing('7267 JT Equity', dt='2018-01-10', tz='NY')
        '2018-01-10 00:58:00-05:00'
        >>> market_timing('7267 JT Equity', dt='2018-09-10', tz='SPX Index')
        '2018-09-10 01:58:00-04:00'
        >>> market_timing('8035 JT Equity', dt='2018-09-10', timing='BOD')
        '2018-09-10 09:01'
        >>> market_timing('Z 1 Index', dt='2018-09-10', timing='FINISHED')
        '2018-09-10 21:00'
        >>> market_timing('TESTTICKER Corp', dt='2018-09-10')
        ''
    """
    logger = logs.get_logger(market_timing)
    exch = pd.Series(exch_info(ticker=ticker))
    if any(req not in exch.index for req in ['tz', 'allday', 'day']):
        logger.error(f'required exchange info cannot be found in {ticker} ...')
        return ''

    mkt_time = {
        'BOD': exch.day[0],
        'FINISHED': exch.allday[-1]
    }.get(timing, exch.day[-1])

    cur_dt = pd.Timestamp(str(dt)).strftime('%Y-%m-%d')
    if tz == 'local':
        return f'{cur_dt} {mkt_time}'

    return timezone.tz_convert(f'{cur_dt} {mkt_time}',
                               to_tz=tz,
                               from_tz=exch.tz)
Пример #15
0
def bds(tickers, flds, use_port=False, **kwargs) -> pd.DataFrame:
    """
    Bloomberg block data

    Args:
        tickers: ticker(s)
        flds: field
        use_port: use `PortfolioDataRequest`
        **kwargs: other overrides for query

    Returns:
        pd.DataFrame: block data
    """
    logger = logs.get_logger(bds, **kwargs)

    part = partial(_bds_, fld=flds, logger=logger, use_port=use_port, **kwargs)
    if isinstance(tickers, str): tickers = [tickers]
    return pd.DataFrame(pd.concat(map(part, tickers), sort=False))
Пример #16
0
def bdp(tickers, flds, cache=False, **kwargs):
    """
    Get reference data and save to

    Args:
        tickers: tickers
        flds: fields to query
        cache: bool - use cache to store data
        **kwargs: overrides

    Returns:
        pd.DataFrame

    Examples:
        >>> bdp('IQ US Equity', 'Crncy', raw=True)
                 ticker  field value
        0  IQ US Equity  Crncy   USD
        >>> bdp('IQ US Equity', 'Crncy').reset_index()
                 ticker crncy
        0  IQ US Equity   USD
    """
    logger = logs.get_logger(bdp, level=kwargs.pop('log', logs.LOG_LEVEL))
    con, _ = create_connection()
    ovrds = assist.proc_ovrds(**kwargs)

    logger.info(
        f'loading reference data from Bloomberg:\n'
        f'{assist.info_qry(tickers=tickers, flds=flds)}'
    )
    data = con.ref(tickers=tickers, flds=flds, ovrds=ovrds)
    if not cache: return [data]

    qry_data = []
    for r, snap in data.iterrows():
        subset = [r]
        data_file = storage.ref_file(
            ticker=snap.ticker, fld=snap.field, ext='pkl', cache=cache, **kwargs
        )
        if data_file:
            if not files.exists(data_file): qry_data.append(data.iloc[subset])
            files.create_folder(data_file, is_file=True)
            data.iloc[subset].to_pickle(data_file)

    return qry_data
Пример #17
0
def bdp_bds_cache(func, tickers, flds, **kwargs) -> ToQuery:
    """
    Find cached `BDP` / `BDS` queries

    Args:
        func: function name - bdp or bds
        tickers: tickers
        flds: fields
        **kwargs: other kwargs

    Returns:
        ToQuery(ticker, flds, kwargs)
    """
    cache_data = []
    log_level = kwargs.get('log', logs.LOG_LEVEL)
    logger = logs.get_logger(bdp_bds_cache, level=log_level)
    has_date = kwargs.pop('has_date', func == 'bds')
    cache = kwargs.get('cache', True)

    tickers = utils.flatten(tickers)
    flds = utils.flatten(flds)
    loaded = pd.DataFrame(data=0, index=tickers, columns=flds)

    for ticker, fld in product(tickers, flds):
        data_file = storage.ref_file(
            ticker=ticker,
            fld=fld,
            has_date=has_date,
            cache=cache,
            ext='pkl',
            **{k: v
               for k, v in kwargs.items() if k not in EXC_COLS})
        if not files.exists(data_file): continue
        logger.debug(f'reading from {data_file} ...')
        cache_data.append(pd.read_pickle(data_file))
        loaded.loc[ticker, fld] = 1

    to_qry = loaded.where(loaded == 0)\
        .dropna(how='all', axis=1).dropna(how='all', axis=0)

    return ToQuery(tickers=to_qry.index.tolist(),
                   flds=to_qry.columns.tolist(),
                   cached_data=cache_data)
Пример #18
0
def send_request(request: blpapi.request.Request, **kwargs):
    """
    Send request to Bloomberg session

    Args:
        request: Bloomberg request
    """
    logger = logs.get_logger(send_request, **kwargs)
    try:
        bbg_session(**kwargs).sendRequest(request=request)
    except blpapi.InvalidStateException as e:
        logger.exception(e)

        # Delete existing connection and send again
        port = kwargs.get('port', _PORT_)
        con_sym = f'{_CON_SYM_}//{port}'
        if con_sym in globals(): del globals()[con_sym]

        # No error handler for 2nd trial
        bbg_session(**kwargs).sendRequest(request=request)
Пример #19
0
def bdp(tickers, flds, **kwargs) -> pd.DataFrame:
    """
    Bloomberg reference data

    Args:
        tickers: tickers
        flds: fields to query
        **kwargs: Bloomberg overrides

    Returns:
        pd.DataFrame
    """
    logger = logs.get_logger(bdp, **kwargs)

    if isinstance(tickers, str): tickers = [tickers]
    if isinstance(flds, str): flds = [flds]

    request = process.create_request(
        service='//blp/refdata',
        request='ReferenceDataRequest',
        **kwargs,
    )
    process.init_request(request=request, tickers=tickers, flds=flds, **kwargs)
    logger.debug(f'Sending request to Bloomberg ...\n{request}')
    conn.send_request(request=request, **kwargs)

    res = pd.DataFrame(process.rec_events(func=process.process_ref, **kwargs))
    if kwargs.get('raw', False): return res
    if res.empty or any(fld not in res for fld in ['ticker', 'field']):
        return pd.DataFrame()

    return (res.set_index(['ticker', 'field']).unstack(level=1).rename_axis(
        index=None,
        columns=[None,
                 None]).droplevel(axis=1,
                                  level=0).loc[:, res.field.unique()].pipe(
                                      pipeline.standard_cols,
                                      col_maps=kwargs.get('col_maps', None)))
Пример #20
0
def latest_file(path_name, keyword='', ext='', **kwargs) -> str:
    """
    Latest modified file in folder

    Args:
        path_name: full path name
        keyword: keyword to search
        ext: file extension

    Returns:
        str: latest file name
    """
    files = sort_by_modified(
        all_files(path_name=path_name, keyword=keyword, ext=ext, full_path=True)
    )

    if not files:
        from xbbg.io import logs

        logger = logs.get_logger(latest_file, level=kwargs.pop('log', 'warning'))
        logger.debug(f'no file in folder: {path_name}')
        return ''

    return str(files[0]).replace('\\', '/')
Пример #21
0
def fut_ticker(gen_ticker: str, dt, freq: str, **kwargs) -> str:
    """
    Get proper ticker from generic ticker

    Args:
        gen_ticker: generic ticker
        dt: date
        freq: futures contract frequency

    Returns:
        str: exact futures ticker
    """
    logger = logs.get_logger(fut_ticker, **kwargs)
    dt = pd.Timestamp(dt)
    t_info = gen_ticker.split()
    pre_dt = pd.bdate_range(end='today', periods=1)[-1]
    same_month = (pre_dt.month == dt.month) and (pre_dt.year == dt.year)

    asset = t_info[-1]
    if asset in ['Index', 'Curncy', 'Comdty']:
        ticker = ' '.join(t_info[:-1])
        prefix, idx, postfix = ticker[:-1], int(ticker[-1]) - 1, asset

    elif asset == 'Equity':
        ticker = t_info[0]
        prefix, idx, postfix = ticker[:-1], int(ticker[-1]) - 1, ' '.join(
            t_info[1:])

    else:
        logger.error(f'unkonwn asset type for ticker: {gen_ticker}')
        return ''

    month_ext = 4 if asset == 'Comdty' else 2
    months = pd.date_range(start=dt,
                           periods=max(idx + month_ext, 3),
                           freq=freq)
    logger.debug(f'pulling expiry dates for months: {months}')

    def to_fut(month):
        return prefix + const.Futures[month.strftime('%b')] + \
            month.strftime('%y')[-1 if same_month else -2:] + ' ' + postfix

    fut = [to_fut(m) for m in months]
    logger.debug(f'trying futures: {fut}')
    # noinspection PyBroadException
    try:
        fut_matu = bdp(tickers=fut, flds='last_tradeable_dt')
    except Exception as e1:
        logger.error(
            f'error downloading futures contracts (1st trial) {e1}:\n{fut}')
        # noinspection PyBroadException
        try:
            fut = fut[:-1]
            logger.debug(f'trying futures (2nd trial): {fut}')
            fut_matu = bdp(tickers=fut, flds='last_tradeable_dt')
        except Exception as e2:
            logger.error(
                f'error downloading futures contracts (2nd trial) {e2}:\n{fut}'
            )
            return ''

    if 'last_tradeable_dt' not in fut_matu:
        logger.warning(f'no futures found for {fut}')
        return ''

    fut_matu.sort_values(by='last_tradeable_dt', ascending=True, inplace=True)
    sub_fut = fut_matu[pd.DatetimeIndex(fut_matu.last_tradeable_dt) > dt]
    logger.debug(f'futures full chain:\n{fut_matu.to_string()}')
    logger.debug(f'getting index {idx} from:\n{sub_fut.to_string()}')
    return sub_fut.index.values[idx]
Пример #22
0
async def live(tickers,
               flds=None,
               info=None,
               max_cnt=0,
               options=None,
               **kwargs):
    """
    Subscribe and getting data feeds from

    Args:
        tickers: list of tickers
        flds: fields to subscribe
        info: list of keys of interests (ticker will be included)
        max_cnt: max number of data points to receive

    Yields:
        dict: Bloomberg market data

    Examples:
        >>> # async for _ in live('SPY US Equity', info=const.LIVE_INFO): pass
    """
    from collections.abc import Iterable

    logger = logs.get_logger(live, **kwargs)
    evt_typs = conn.event_types()

    if flds is None:
        s_flds = ['LAST_PRICE', 'BID', 'ASK']
    else:
        if isinstance(flds, str): flds = [flds]
        s_flds = [fld.upper() for fld in flds]

    if isinstance(info, str): info = [info]
    if isinstance(info, Iterable): info = [key.upper() for key in info]
    if info is None: info = const.LIVE_INFO

    sess = conn.bbg_session(**kwargs)
    while sess.tryNextEvent():
        pass
    with subscribe(tickers=tickers, flds=s_flds, options=options, **kwargs):
        cnt = 0
        while True and cnt <= max_cnt:
            try:
                ev = sess.tryNextEvent()
                if ev is None: continue
                if evt_typs[ev.eventType()] != 'SUBSCRIPTION_DATA': continue

                for msg, fld in product(ev, s_flds):
                    if not msg.hasElement(fld): continue
                    if msg.getElement(fld).isNull(): continue
                    yield {
                        **{
                            'TICKER': msg.correlationIds()[0].value(),
                            'FIELD': fld,
                        },
                        **{
                            str(elem.name()): process.elem_value(elem)
                            for elem in msg.asElement().elements() if (True if not info else str(elem.name(
                            )) in info)
                        },
                    }
                    if max_cnt: cnt += 1

            except ValueError as e:
                logger.debug(e)
            except KeyboardInterrupt:
                break
Пример #23
0
def bdtick(ticker,
           dt,
           session='allday',
           time_range=None,
           types=None,
           **kwargs) -> pd.DataFrame:
    """
    Bloomberg tick data

    Args:
        ticker: ticker name
        dt: date to download
        session: [allday, day, am, pm, pre, post]
        time_range: tuple of start and end time (must be converted into UTC)
                    if this is given, `dt` and `session` will be ignored
        types: str or list, one or combinations of [
            TRADE, AT_TRADE, BID, ASK, MID_PRICE,
            BID_BEST, ASK_BEST, BEST_BID, BEST_ASK,
        ]

    Returns:
        pd.DataFrame
    """
    logger = logs.get_logger(bdtick, **kwargs)

    if types is None: types = ['TRADE']
    exch = const.exch_info(ticker=ticker, **kwargs)
    if exch.empty: raise LookupError(f'Cannot find exchange info for {ticker}')

    if isinstance(time_range, (tuple, list)) and (len(time_range) == 2):
        cur_dt = pd.Timestamp(dt).strftime('%Y-%m-%d')
        time_rng = (pd.DatetimeIndex([
            f'{cur_dt} {time_range[0]}',
            f'{cur_dt} {time_range[1]}',
        ]).tz_localize(exch.tz).tz_convert(
            process.DEFAULT_TZ).tz_convert('UTC'))
    else:
        time_rng = process.time_range(dt=dt,
                                      ticker=ticker,
                                      session=session,
                                      **kwargs)

    while conn.bbg_session(**kwargs).tryNextEvent():
        pass
    request = process.create_request(
        service='//blp/refdata',
        request='IntradayTickRequest',
        settings=[
            ('security', ticker),
            ('startDateTime', time_rng[0]),
            ('endDateTime', time_rng[1]),
            ('includeConditionCodes', True),
            ('includeExchangeCodes', True),
            ('includeNonPlottableEvents', True),
            ('includeBrokerCodes', True),
            ('includeRpsCodes', True),
            ('includeTradeTime', True),
            ('includeActionCodes', True),
            ('includeIndicatorCodes', True),
        ],
        append={'eventTypes': types},
        **kwargs,
    )

    logger.debug(f'Sending request to Bloomberg ...\n{request}')
    conn.send_request(request=request)

    res = pd.DataFrame(
        process.rec_events(func=process.process_bar, typ='t', **kwargs))
    if kwargs.get('raw', False): return res
    if res.empty or ('time' not in res): return pd.DataFrame()

    return (res.set_index('time').rename_axis(
        index=None).tz_localize('UTC').tz_convert(exch.tz).pipe(
            pipeline.add_ticker, ticker=ticker).rename(
                columns={
                    'size': 'volume',
                    'type': 'typ',
                    'conditionCodes': 'cond',
                    'exchangeCode': 'exch',
                    'tradeTime': 'trd_time',
                }))
Пример #24
0
def bdib(ticker: str,
         dt,
         session='allday',
         typ='TRADE',
         **kwargs) -> pd.DataFrame:
    """
    Bloomberg intraday bar data

    Args:
        ticker: ticker name
        dt: date to download
        session: [allday, day, am, pm, pre, post]
        typ: [TRADE, BID, ASK, BID_BEST, ASK_BEST, BEST_BID, BEST_ASK]
        **kwargs:
            ref: reference ticker or exchange
                 used as supplement if exchange info is not defined for `ticker`
            batch: whether is batch process to download data
            log: level of logs

    Returns:
        pd.DataFrame
    """
    from xbbg.core import trials

    logger = logs.get_logger(bdib, **kwargs)

    ex_info = const.exch_info(ticker=ticker, **kwargs)
    if ex_info.empty: raise KeyError(f'Cannot find exchange info for {ticker}')

    ss_rng = process.time_range(dt=dt,
                                ticker=ticker,
                                session=session,
                                tz=ex_info.tz,
                                **kwargs)
    data_file = storage.bar_file(ticker=ticker, dt=dt, typ=typ)
    if files.exists(data_file) and kwargs.get(
            'cache', True) and (not kwargs.get('reload', False)):
        res = (pd.read_parquet(data_file).pipe(
            pipeline.add_ticker, ticker=ticker).loc[ss_rng[0]:ss_rng[1]])
        if not res.empty:
            logger.debug(f'Loading Bloomberg intraday data from: {data_file}')
            return res

    if not process.check_current(dt=dt, logger=logger, **kwargs):
        return pd.DataFrame()

    cur_dt = pd.Timestamp(dt).strftime('%Y-%m-%d')
    q_tckr = ticker
    if ex_info.get('is_fut', False):
        is_sprd = ex_info.get(
            'has_sprd', False) and (len(ticker[:-1]) != ex_info['tickers'][0])
        if not is_sprd:
            q_tckr = fut_ticker(gen_ticker=ticker, dt=dt, freq=ex_info['freq'])
            if q_tckr == '':
                logger.error(f'cannot find futures ticker for {ticker} ...')
                return pd.DataFrame()

    info_log = f'{q_tckr} / {cur_dt} / {typ}'
    trial_kw = dict(ticker=ticker, dt=dt, typ=typ, func='bdib')
    num_trials = trials.num_trials(**trial_kw)
    if num_trials >= 2:
        if kwargs.get('batch', False): return pd.DataFrame()
        logger.info(f'{num_trials} trials with no data {info_log}')
        return pd.DataFrame()

    while conn.bbg_session(**kwargs).tryNextEvent():
        pass
    time_rng = process.time_range(dt=dt,
                                  ticker=ticker,
                                  session='allday',
                                  **kwargs)
    request = process.create_request(
        service='//blp/refdata',
        request='IntradayBarRequest',
        settings=[
            ('security', ticker),
            ('eventType', typ),
            ('interval', kwargs.get('interval', 1)),
            ('startDateTime', time_rng[0]),
            ('endDateTime', time_rng[1]),
        ],
        **kwargs,
    )
    logger.debug(f'Sending request to Bloomberg ...\n{request}')
    conn.send_request(request=request, **kwargs)

    res = pd.DataFrame(process.rec_events(func=process.process_bar, **kwargs))
    if res.empty or ('time' not in res):
        logger.warning(f'No data for {info_log} ...')
        trials.update_trials(cnt=num_trials + 1, **trial_kw)
        return pd.DataFrame()

    data = (res.set_index('time').rename_axis(index=None).rename(
        columns={
            'numEvents': 'num_trds'
        }).tz_localize('UTC').tz_convert(ex_info.tz).pipe(pipeline.add_ticker,
                                                          ticker=ticker))
    if kwargs.get('cache', True):
        storage.save_intraday(data=data[ticker],
                              ticker=ticker,
                              dt=dt,
                              typ=typ,
                              **kwargs)

    return data.loc[ss_rng[0]:ss_rng[1]]
Пример #25
0
Файл: blp.py Проект: DT021/xbbg
def bdtick(ticker, dt, session='allday', types=None, **kwargs) -> pd.DataFrame:
    """
    Bloomberg tick data

    Args:
        ticker: ticker name
        dt: date to download
        session: [allday, day, am, pm, pre, post]
        types: str or list, one or combinations of [
            TRADE, AT_TRADE, BID, ASK, MID_PRICE,
            BID_BEST, ASK_BEST, BEST_BID, BEST_ASK,
        ]

    Returns:
        pd.DataFrame
    """
    logger = logs.get_logger(bdtick, **kwargs)

    exch = const.exch_info(ticker=ticker, **kwargs)
    time_rng = process.time_range(dt=dt,
                                  ticker=ticker,
                                  session=session,
                                  tz=exch.tz,
                                  **kwargs)

    service = conn.bbg_service(service='//blp/refdata', **kwargs)
    request = service.createRequest('IntradayTickRequest')

    while conn.bbg_session(**kwargs).tryNextEvent():
        pass
    if types is None: types = ['TRADE']
    if isinstance(types, str): types = [types]
    request.set('security', ticker)
    for typ in types:
        request.append('eventTypes', typ)
    request.set('startDateTime', time_rng[0])
    request.set('endDateTime', time_rng[1])
    request.set('includeConditionCodes', True)
    request.set('includeExchangeCodes', True)
    request.set('includeNonPlottableEvents', True)
    request.set('includeBrokerCodes', True)
    request.set('includeRpsCodes', True)
    request.set('includeTradeTime', True)
    request.set('includeActionCodes', True)
    request.set('includeIndicatorCodes', True)

    logger.debug(f'Sending request to Bloomberg ...\n{request}')
    conn.send_request(request=request)

    res = pd.DataFrame(
        process.rec_events(func=process.process_bar, typ='t', **kwargs))
    if kwargs.get('raw', False): return res
    if res.empty or ('time' not in res): return pd.DataFrame()

    return (res.set_index('time').rename_axis(
        index=None).tz_localize('UTC').tz_convert(exch.tz).pipe(
            pipeline.add_ticker, ticker=ticker).rename(
                columns={
                    'size': 'volume',
                    'type': 'typ',
                    'conditionCodes': 'cond',
                    'exchangeCode': 'exch',
                    'tradeTime': 'trd_time',
                }))
Пример #26
0
def bds(tickers, flds, cache=False, **kwargs):
    """
    Download block data from Bloomberg

    Args:
        tickers: ticker(s)
        flds: field(s)
        cache: whether read from cache
        **kwargs: other overrides for query
          -> raw: raw output from `pdbdp` library, default False

    Returns:
        pd.DataFrame: block data

    Examples:
        >>> import os
        >>>
        >>> pd.options.display.width = 120
        >>> s_dt, e_dt = '20180301', '20181031'
        >>> dvd = bds(
        ...     'NVDA US Equity', 'DVD_Hist_All',
        ...     DVD_Start_Dt=s_dt, DVD_End_Dt=e_dt, raw=True,
        ... )
        >>> dvd.loc[:, ['ticker', 'name', 'value']].head(8)
                   ticker                name         value
        0  NVDA US Equity       Declared Date    2018-08-16
        1  NVDA US Equity             Ex-Date    2018-08-29
        2  NVDA US Equity         Record Date    2018-08-30
        3  NVDA US Equity        Payable Date    2018-09-21
        4  NVDA US Equity     Dividend Amount          0.15
        5  NVDA US Equity  Dividend Frequency       Quarter
        6  NVDA US Equity       Dividend Type  Regular Cash
        7  NVDA US Equity       Declared Date    2018-05-10
        >>> dvd = bds(
        ...     'NVDA US Equity', 'DVD_Hist_All',
        ...     DVD_Start_Dt=s_dt, DVD_End_Dt=e_dt,
        ... )
        >>> dvd.reset_index().loc[:, ['ticker', 'ex_date', 'dividend_amount']]
                   ticker     ex_date  dividend_amount
        0  NVDA US Equity  2018-08-29             0.15
        1  NVDA US Equity  2018-05-23             0.15
        >>> if not os.environ.get('BBG_ROOT', ''):
        ...     os.environ['BBG_ROOT'] = f'{files.abspath(__file__, 1)}/tests/data'
        >>> idx_kw = dict(End_Dt='20181220', cache=True)
        >>> idx_wt = bds('DJI Index', 'Indx_MWeight_Hist', **idx_kw)
        >>> idx_wt.round(2).tail().reset_index(drop=True)
          index_member  percent_weight
        0         V UN            3.82
        1        VZ UN            1.63
        2       WBA UW            2.06
        3       WMT UN            2.59
        4       XOM UN            2.04
        >>> idx_wt = bds('DJI Index', 'Indx_MWeight_Hist', **idx_kw)
        >>> idx_wt.round(2).head().reset_index(drop=True)
          index_member  percent_weight
        0      AAPL UW            4.65
        1       AXP UN            2.84
        2        BA UN            9.29
        3       CAT UN            3.61
        4      CSCO UW            1.26
    """
    logger = logs.get_logger(bds, level=kwargs.pop('log', logs.LOG_LEVEL))
    has_date = kwargs.pop('has_date', True)
    con, _ = create_connection()
    ovrds = assist.proc_ovrds(**kwargs)

    logger.info(
        f'loading block data from Bloomberg:\n'
        f'{assist.info_qry(tickers=tickers, flds=flds)}'
    )
    data = con.bulkref(tickers=tickers, flds=flds, ovrds=ovrds)
    if not cache: return [data]

    qry_data = []
    for (ticker, fld), grp in data.groupby(['ticker', 'field']):
        data_file = storage.ref_file(
            ticker=ticker, fld=fld, has_date=has_date, ext='pkl', cache=cache, **kwargs
        )
        if data_file:
            if not files.exists(data_file): qry_data.append(grp)
            files.create_folder(data_file, is_file=True)
            grp.reset_index(drop=True).to_pickle(data_file)

    return qry_data
Пример #27
0
Файл: blp.py Проект: DT021/xbbg
def live(tickers,
         flds='Last_Price',
         max_cnt=None,
         json=False,
         **kwargs) -> dict:
    """
    Subscribe and getting data feeds from

    Args:
        tickers: list of tickers
        flds: fields to subscribe
        max_cnt: max number of data points to receive
        json: if data is required to convert to json

    Yields:
        dict: Bloomberg market data
    """
    logger = logs.get_logger(live, **kwargs)

    def get_value(element):
        """
        Get value from element

        Args:
            element: Bloomberg element

        Returns:
            dict
        """
        conv = [conn.blpapi.name.Name]
        if json: conv += [pd.Timestamp, datetime.time, datetime.date]
        if element.isNull(): return None
        value = element.getValue()
        if isinstance(value, np.bool_): return bool(value)
        if isinstance(value, tuple(conv)): return str(value)
        return value

    if isinstance(flds, str): flds = [flds]
    s_flds = [fld.upper() for fld in flds]
    with subscribe(tickers=tickers, flds=s_flds, **kwargs):
        cnt = 0
        while True if max_cnt is None else cnt < max_cnt:
            try:
                ev = conn.bbg_session(**kwargs).nextEvent(500)
                if conn.event_types()[ev.eventType()] != 'SUBSCRIPTION_DATA':
                    continue
                for msg in ev:
                    for fld in s_flds:
                        if not msg.hasElement(fld): continue
                        if msg.getElement(fld).isNull(): continue
                        ticker = msg.correlationIds()[0].value()
                        values = {
                            **{
                                'TICKER': ticker
                            },
                            **{
                                str(elem.name()): get_value(elem)
                                for elem in msg.asElement().elements()
                            }
                        }
                        yield {
                            key: value
                            for key, value in values.items()
                            if value not in [np.nan, pd.NaT, None] or (
                                isinstance(value, str) and value.strip())
                        }
                        cnt += 1
            except ValueError as e:
                logger.debug(e)
            except KeyboardInterrupt:
                break
Пример #28
0
def bdib(ticker, dt, typ='TRADE', batch=False, log=logs.LOG_LEVEL) -> pd.DataFrame:
    """
    Download intraday data and save to cache

    Args:
        ticker: ticker name
        dt: date to download
        typ: [TRADE, BID, ASK, BID_BEST, ASK_BEST, BEST_BID, BEST_ASK]
        batch: whether is batch process to download data
        log: level of logs

    Returns:
        pd.DataFrame
    """
    from xbbg.core import missing

    logger = logs.get_logger(bdib, level=log)

    t_1 = pd.Timestamp('today').date() - pd.Timedelta('1D')
    whole_day = pd.Timestamp(dt).date() < t_1
    if (not whole_day) and batch:
        logger.warning(f'querying date {t_1} is too close, ignoring download ...')
        return pd.DataFrame()

    cur_dt = pd.Timestamp(dt).strftime('%Y-%m-%d')
    asset = ticker.split()[-1]
    info_log = f'{ticker} / {cur_dt} / {typ}'

    if asset in ['Equity', 'Curncy', 'Index', 'Comdty']:
        exch = const.exch_info(ticker=ticker)
        if exch.empty: return pd.DataFrame()
    else:
        logger.error(f'unknown asset type: {asset}')
        return pd.DataFrame()

    time_fmt = '%Y-%m-%dT%H:%M:%S'
    time_idx = pd.DatetimeIndex([
        f'{cur_dt} {exch.allday[0]}', f'{cur_dt} {exch.allday[-1]}']
    ).tz_localize(exch.tz).tz_convert(DEFAULT_TZ).tz_convert('UTC')
    if time_idx[0] > time_idx[1]: time_idx -= pd.TimedeltaIndex(['1D', '0D'])

    q_tckr = ticker
    if exch.get('is_fut', False):
        if 'freq' not in exch:
            logger.error(f'[freq] missing in info for {info_log} ...')

        is_sprd = exch.get('has_sprd', False) and (len(ticker[:-1]) != exch['tickers'][0])
        if not is_sprd:
            q_tckr = fut_ticker(gen_ticker=ticker, dt=dt, freq=exch['freq'])
            if q_tckr == '':
                logger.error(f'cannot find futures ticker for {ticker} ...')
                return pd.DataFrame()

    info_log = f'{q_tckr} / {cur_dt} / {typ}'
    miss_kw = dict(ticker=ticker, dt=dt, typ=typ, func='bdib')
    cur_miss = missing.current_missing(**miss_kw)
    if cur_miss >= 2:
        if batch: return pd.DataFrame()
        logger.info(f'{cur_miss} trials with no data {info_log}')
        return pd.DataFrame()

    logger.info(f'loading data from Bloomberg: {info_log} ...')
    con, _ = create_connection()
    data = con.bdib(
        ticker=q_tckr, event_type=typ, interval=1,
        start_datetime=time_idx[0].strftime(time_fmt),
        end_datetime=time_idx[1].strftime(time_fmt),
    )

    if not isinstance(data, pd.DataFrame):
        raise ValueError(f'unknown output format: {type(data)}')

    if data.empty:
        logger.warning(f'no data for {info_log} ...')
        missing.update_missing(**miss_kw)
        return pd.DataFrame()

    data = data.tz_localize('UTC').tz_convert(exch.tz)
    storage.save_intraday(data=data, ticker=ticker, dt=dt, typ=typ)

    return pd.DataFrame() if batch else assist.format_intraday(data=data, ticker=ticker)
Пример #29
0
def bdh(tickers, flds, start_date, end_date='today', adjust=None, **kwargs):
    """
    Bloomberg historical data

    Args:
        tickers: ticker(s)
        flds: field(s)
        start_date: start date
        end_date: end date - default today
        adjust: `all`, `dvd`, `normal`, `abn` (=abnormal), `split`, `-` or None
                exact match of above words will adjust for corresponding events
                Case 0: `-` no adjustment for dividend or split
                Case 1: `dvd` or `normal|abn` will adjust for all dividends except splits
                Case 2: `adjust` will adjust for splits and ignore all dividends
                Case 3: `all` == `dvd|split` == adjust for all
                Case 4: None == Bloomberg default OR use kwargs
        **kwargs: overrides

    Returns:
        pd.DataFrame

    Examples:
        >>> bdh(
        ...     tickers='VIX Index', flds=['High', 'Low', 'Last_Price'],
        ...     start_date='2018-02-05', end_date='2018-02-07',
        ... ).round(2).transpose().rename_axis((None, None))
                              2018-02-05  2018-02-06  2018-02-07
        VIX Index High             38.80       50.30       31.64
                  Low              16.80       22.42       21.17
                  Last_Price       37.32       29.98       27.73
        >>> bdh(
        ...     tickers='AAPL US Equity', flds='Px_Last',
        ...     start_date='20140605', end_date='20140610', adjust='-'
        ... ).round(2)
        ticker     AAPL US Equity
        field             Px_Last
        2014-06-05         647.35
        2014-06-06         645.57
        2014-06-09          93.70
        2014-06-10          94.25
        >>> bdh(
        ...     tickers='AAPL US Equity', flds='Px_Last',
        ...     start_date='20140606', end_date='20140609',
        ...     CshAdjNormal=False, CshAdjAbnormal=False, CapChg=False,
        ... ).round(2)
        ticker     AAPL US Equity
        field             Px_Last
        2014-06-06         645.57
        2014-06-09          93.70
    """
    logger = logs.get_logger(bdh, level=kwargs.pop('log', logs.LOG_LEVEL))

    # Dividend adjustments
    if isinstance(adjust, str) and adjust:
        if adjust == 'all':
            kwargs['CshAdjNormal'] = True
            kwargs['CshAdjAbnormal'] = True
            kwargs['CapChg'] = True
        else:
            kwargs['CshAdjNormal'] = 'normal' in adjust or 'dvd' in adjust
            kwargs['CshAdjAbnormal'] = 'abn' in adjust or 'dvd' in adjust
            kwargs['CapChg'] = 'split' in adjust

    con, _ = create_connection()
    elms = assist.proc_elms(**kwargs)
    ovrds = assist.proc_ovrds(**kwargs)

    if isinstance(tickers, str): tickers = [tickers]
    if isinstance(flds, str): flds = [flds]
    s_dt = utils.fmt_dt(start_date, fmt='%Y%m%d')
    e_dt = utils.fmt_dt(end_date, fmt='%Y%m%d')

    logger.info(
        f'loading historical data from Bloomberg:\n'
        f'{assist.info_qry(tickers=tickers, flds=flds)}'
    )

    return con.bdh(
        tickers=tickers, flds=flds, elms=elms, ovrds=ovrds,
        start_date=s_dt, end_date=e_dt,
    ).rename_axis(None)
Пример #30
0
    def wrapper(*args, **kwargs):

        scope = utils.func_scope(func=func)
        param = inspect.signature(func).parameters
        port = kwargs.pop('port', _PORT_)
        timeout = kwargs.pop('timeout', _TIMEOUT_)
        restart = kwargs.pop('restart', False)
        all_kw = {
            k: args[n] if n < len(args) else v.default
            for n, (k, v) in enumerate(param.items()) if k != 'kwargs'
        }
        all_kw.update(kwargs)
        log_level = kwargs.get('log', logs.LOG_LEVEL)

        for to_list in ['tickers', 'flds']:
            conv = all_kw.get(to_list, None)
            if hasattr(conv, 'tolist'):
                all_kw[to_list] = getattr(conv, 'tolist')()
            if isinstance(conv, str):
                all_kw[to_list] = [conv]

        cached_data = []
        if scope in ['xbbg.blp.bdp', 'xbbg.blp.bds']:
            to_qry = cached.bdp_bds_cache(func=func.__name__, **all_kw)
            cached_data += to_qry.cached_data

            if not (to_qry.tickers and to_qry.flds):
                if not cached_data: return pd.DataFrame()
                res = pd.concat(cached_data, sort=False).reset_index(drop=True)
                if not all_kw.get('raw', False):
                    res = assist.format_output(data=res,
                                               source=func.__name__,
                                               col_maps=all_kw.get(
                                                   'col_maps', dict()))
                return res

            all_kw['tickers'] = to_qry.tickers
            all_kw['flds'] = to_qry.flds

        if scope in ['xbbg.blp.bdib']:
            data_file = storage.hist_file(
                ticker=all_kw['ticker'],
                dt=all_kw['dt'],
                typ=all_kw['typ'],
            )
            if files.exists(data_file):
                logger = logs.get_logger(func, level=log_level)
                if all_kw.get('batch', False): return
                logger.debug(f'reading from {data_file} ...')
                return assist.format_intraday(data=pd.read_parquet(data_file),
                                              **all_kw)

        _, new = create_connection(port=port, timeout=timeout, restart=restart)
        res = func(
            **
            {k: v
             for k, v in all_kw.items() if k not in ['raw', 'col_maps']})
        if new: delete_connection()

        if scope.startswith('xbbg.blp.') and isinstance(res, list):
            final = cached_data + res
            if not final: return pd.DataFrame()
            res = pd.DataFrame(pd.concat(final, sort=False))

        if (scope in ['xbbg.blp.bdp', 'xbbg.blp.bds']) \
                and (not all_kw.get('raw', False)):
            res = assist.format_output(
                data=res.reset_index(drop=True),
                source=func.__name__,
                col_maps=all_kw.get('col_maps', dict()),
            )

        return res