|
| 1 | +from __future__ import annotations |
| 2 | + |
| 3 | +from collections.abc import Iterable |
| 4 | +from datetime import date |
| 5 | + |
| 6 | +import pandas as pd |
| 7 | +from databento_dbn import Compression |
| 8 | +from databento_dbn import SType |
| 9 | + |
| 10 | +from databento.common import API_VERSION |
| 11 | +from databento.common.constants import ADJUSTMENT_FACTORS_DATE_COLUMNS |
| 12 | +from databento.common.constants import ADJUSTMENT_FACTORS_DATETIME_COLUMNS |
| 13 | +from databento.common.http import BentoHttpAPI |
| 14 | +from databento.common.parsing import convert_date_columns |
| 15 | +from databento.common.parsing import convert_datetime_columns |
| 16 | +from databento.common.parsing import convert_ndjson_to_df |
| 17 | +from databento.common.parsing import datetime_to_string |
| 18 | +from databento.common.parsing import optional_datetime_to_string |
| 19 | +from databento.common.parsing import optional_string_to_list |
| 20 | +from databento.common.parsing import optional_symbols_list_to_list |
| 21 | + |
| 22 | + |
| 23 | +class AdjustmentFactorsHttpAPI(BentoHttpAPI): |
| 24 | + """ |
| 25 | + Provides request methods for the adjustment factors HTTP API endpoints. |
| 26 | + """ |
| 27 | + |
| 28 | + def __init__(self, key: str, gateway: str) -> None: |
| 29 | + super().__init__(key=key, gateway=gateway) |
| 30 | + self._base_url = gateway + f"/v{API_VERSION}/adjustment_factors" |
| 31 | + |
| 32 | + def get_range( |
| 33 | + self, |
| 34 | + start: pd.Timestamp | date | str | int, |
| 35 | + end: pd.Timestamp | date | str | int | None = None, |
| 36 | + symbols: Iterable[str] | str | None = None, |
| 37 | + stype_in: SType | str = "raw_symbol", |
| 38 | + countries: Iterable[str] | str | None = None, |
| 39 | + security_types: Iterable[str] | str | None = None, |
| 40 | + ) -> pd.DataFrame: |
| 41 | + """ |
| 42 | + Request a new adjustment factors time series from Databento. |
| 43 | +
|
| 44 | + Makes a `POST /adjustment_factors.get_range` HTTP request. |
| 45 | +
|
| 46 | + The `ex_date` column will be used to filter the time range and order the records. |
| 47 | + It will also be set as the index of the resulting data frame. |
| 48 | +
|
| 49 | + Parameters |
| 50 | + ---------- |
| 51 | + start : pd.Timestamp or date or str or int |
| 52 | + The start datetime of the request time range (inclusive) based on `ex_date`. |
| 53 | + Assumes UTC as timezone unless passed a tz-aware object. |
| 54 | + If an integer is passed, then this represents nanoseconds since the UNIX epoch. |
| 55 | + end : pd.Timestamp or date or str or int, optional |
| 56 | + The end datetime of the request time range (exclusive) based on `ex_date`. |
| 57 | + Assumes UTC as timezone unless passed a tz-aware object. |
| 58 | + If an integer is passed, then this represents nanoseconds since the UNIX epoch. |
| 59 | + symbols : Iterable[str] or str, optional |
| 60 | + The symbols to filter for. Takes up to 2,000 symbols per request. |
| 61 | + If more than 1 symbol is specified, the data is merged and sorted by time. |
| 62 | + If 'ALL_SYMBOLS' or `None` then will select **all** symbols. |
| 63 | + stype_in : SType or str, default 'raw_symbol' |
| 64 | + The input symbology type to resolve from. |
| 65 | + Use any of 'raw_symbol', 'nasdaq_symbol', 'isin', 'us_code'. |
| 66 | + countries : Iterable[str] or str, optional |
| 67 | + The listing countries to filter for. |
| 68 | + Takes any number of two letter ISO 3166-1 alpha-2 country codes per request. |
| 69 | + If not specified then will select **all** listing countries by default. |
| 70 | + See [CNTRY](https://databento.com/docs/standards-and-conventions/reference-data-enums#cntry) enum. |
| 71 | + security_types : Iterable[str] or str, optional |
| 72 | + The security types to filter for. |
| 73 | + Takes any number of security types per request. |
| 74 | + If not specified then will select **all** security types by default. |
| 75 | + See [SECTYPE](https://databento.com/docs/standards-and-conventions/reference-data-enums#sectype) enum. |
| 76 | +
|
| 77 | + Returns |
| 78 | + ------- |
| 79 | + pandas.DataFrame |
| 80 | + The data converted into a data frame. |
| 81 | +
|
| 82 | + """ |
| 83 | + symbols_list = optional_symbols_list_to_list(symbols, SType.RAW_SYMBOL) |
| 84 | + countries = optional_string_to_list(countries) |
| 85 | + security_types = optional_string_to_list(security_types) |
| 86 | + |
| 87 | + data: dict[str, object | None] = { |
| 88 | + "start": datetime_to_string(start), |
| 89 | + "end": optional_datetime_to_string(end), |
| 90 | + "symbols": ",".join(symbols_list), |
| 91 | + "stype_in": stype_in, |
| 92 | + "countries": ",".join(countries) if countries else None, |
| 93 | + "security_types": ",".join(security_types) if security_types else None, |
| 94 | + "compression": str(Compression.ZSTD), # Always request zstd |
| 95 | + } |
| 96 | + |
| 97 | + response = self._post( |
| 98 | + url=self._base_url + ".get_range", |
| 99 | + data=data, |
| 100 | + basic_auth=True, |
| 101 | + ) |
| 102 | + |
| 103 | + df = convert_ndjson_to_df(response.content, compressed=True) |
| 104 | + if df.empty: |
| 105 | + return df |
| 106 | + |
| 107 | + convert_datetime_columns(df, ADJUSTMENT_FACTORS_DATETIME_COLUMNS) |
| 108 | + convert_date_columns(df, ADJUSTMENT_FACTORS_DATE_COLUMNS) |
| 109 | + |
| 110 | + df.set_index("ex_date", inplace=True) |
| 111 | + df.sort_index(inplace=True) |
| 112 | + |
| 113 | + return df |
0 commit comments