diff --git a/qiskit_finance/data_providers/data_on_demand_provider.py b/qiskit_finance/data_providers/data_on_demand_provider.py index 12968a1..b51d970 100644 --- a/qiskit_finance/data_providers/data_on_demand_provider.py +++ b/qiskit_finance/data_providers/data_on_demand_provider.py @@ -49,29 +49,26 @@ def __init__( - If a string is provided, it can be a single ticker symbol or multiple symbols separated by semicolons or newlines. - If a list of strings is provided, each string should be a single ticker symbol. - Default is None. + Default is :code:`None`. start (datetime.datetime): Start date of the data. Defaults to January 1st, 2016. end (datetime.datetime): End date of the data. Defaults to January 30th, 2016. - verify (str | bool | None): If verify is None, certify certificates - will be used (default); - if this is False, no certificates will be checked; if this is a string, + verify (str | bool | None): If verify is `None`, runs the certificate verification (default); + if this is :code:`False`, no certificates will be checked; if this is a :code:`str`, it should be pointing - to a certificate for the HTTPS connection to NASDAQ (`dataondemand.nasdaq.com`), - either in the - form of a CA_BUNDLE file or a directory wherein to look. + to a certificate for the HTTPS connection to NASDAQ (:code:`dataondemand.nasdaq.com`), + either in the form of a :code:`CA_BUNDLE` file or a directory wherein to look. """ super().__init__() - self._tickers = None - tickers = tickers if tickers is not None else [] - if isinstance(tickers, list): - self._tickers = tickers - else: - self._tickers = tickers.replace("\n", ";").split(";") - self._n = len(self._tickers) + if tickers is None: + tickers = [] + if isinstance(tickers, str): + tickers = tickers.replace("\n", ";").split(";") + self._tickers = tickers + self._n = len(tickers) self._token = token self._start = start self._end = end @@ -79,10 +76,9 @@ def __init__( def run(self) -> None: """ - Loads data, thus enabling get_similarity_matrix and get_covariance_matrix + Loads data, thus enabling :code:`get_similarity_matrix` and :code:`get_covariance_matrix` methods in the base class. """ - http = urllib3.PoolManager(cert_reqs="CERT_REQUIRED", ca_certs=certifi.where()) url = "https://dataondemand.nasdaq.com/api/v1/quotes?" self._data = [] @@ -96,23 +92,23 @@ def run(self) -> None: "end": self._end.strftime("%Y-%m-%d'T'%H:%M:%S.%f'Z'"), "next_cursor": 0, } - encoded = url + urlencode(values) + encoded_url = f"{url}{urlencode(values)}" if self._verify is None: - response = http.request( - "POST", encoded - ) # this runs certificate verification, as per the set-up of the urllib3 + # Runs certificate verification, as per the set-up of the urllib3 + response = http.request("POST", encoded_url) else: - # this disables certificate verification (False) + # Disables certificate verification (False) # or forces the certificate path (str) - response = http.request("POST", encoded, verify=self._verify) + response = http.request("POST", encoded_url, verify=self._verify) + if response.status != 200: - logger.debug(response.data.decode("utf-8")) + error_message = response.data.decode("utf-8") + logger.debug(f"Error fetching data for {ticker}: {error_message}") stocks_error.append(ticker) continue - quotes = json.loads(response.data.decode("utf-8"))["quotes"] - price_evolution = [] - for q in quotes: - price_evolution.append(q["ask_price"]) + + quotes = json.loads(response.data.decode("utf-8")).get("quotes", []) + price_evolution = [q["ask_price"] for q in quotes] self._data.append(price_evolution) finally: http.clear() diff --git a/qiskit_finance/data_providers/exchange_data_provider.py b/qiskit_finance/data_providers/exchange_data_provider.py index 3489616..b35cee0 100644 --- a/qiskit_finance/data_providers/exchange_data_provider.py +++ b/qiskit_finance/data_providers/exchange_data_provider.py @@ -22,6 +22,12 @@ logger = logging.getLogger(__name__) +VALID_STOCKMARKETS = [ + StockMarket.LONDON, + StockMarket.EURONEXT, + StockMarket.SINGAPORE, +] + class ExchangeDataProvider(BaseDataProvider): """Exchange data provider. @@ -44,9 +50,9 @@ def __init__( token (str): Nasdaq Data Link access token. tickers (str | list[str] | None): Tickers for the data provider. - If a string is provided, it can be a single ticker symbol or multiple symbols - separated by semicolons or newlines. + separated by semicolons or new-lines. - If a list of strings is provided, each string should be a single ticker symbol. - Default is None. + Default is :code:`None`. stockmarket (StockMarket): LONDON (default), EURONEXT, or SINGAPORE start (datetime.datetime): Start date of the data. Defaults to January 1st, 2016. @@ -57,22 +63,17 @@ def __init__( QiskitFinanceError: provider doesn't support given stock market """ super().__init__() - self._tickers = None - tickers = tickers if tickers is not None else [] - if isinstance(tickers, list): - self._tickers = tickers - else: - self._tickers = tickers.replace("\n", ";").split(";") - self._n = len(self._tickers) - - if stockmarket not in [ - StockMarket.LONDON, - StockMarket.EURONEXT, - StockMarket.SINGAPORE, - ]: - msg = "ExchangeDataProvider does not support " - msg += stockmarket.value - msg += " as a stock market." + + if tickers is None: + tickers = [] + if isinstance(tickers, str): + tickers = tickers.replace("\n", ";").split(";") + + self._tickers = tickers + self._n = len(tickers) + + if stockmarket not in VALID_STOCKMARKETS: + msg = f"ExchangeDataProvider does not support {stockmarket.value} as a stock market." raise QiskitFinanceError(msg) # This is to aid serialization; string is ok to serialize diff --git a/qiskit_finance/data_providers/random_data_provider.py b/qiskit_finance/data_providers/random_data_provider.py index f2ce2c2..dfda7a8 100644 --- a/qiskit_finance/data_providers/random_data_provider.py +++ b/qiskit_finance/data_providers/random_data_provider.py @@ -40,7 +40,7 @@ def __init__( - If a string is provided, it can be a single ticker symbol or multiple symbols separated by semicolons or newlines. - If a list of strings is provided, each string should be a single ticker symbol. - Default is None, using ["TICKER1", "TICKER2"] if not provided. + Default is :code:`None`, using :code:`["TICKER1", "TICKER2"]` if not provided. start (datetime.datetime): Start date of the data. Defaults to January 1st, 2016. end (datetime.datetime): End date of the data. @@ -48,15 +48,14 @@ def __init__( seed (int | None): Random seed for reproducibility. """ super().__init__() - self._tickers = None - tickers = tickers if tickers is not None else ["TICKER1", "TICKER2"] - if isinstance(tickers, list): - self._tickers = tickers - else: - self._tickers = tickers.replace("\n", ";").split(";") + if tickers is None: + tickers = ["TICKER1", "TICKER2"] + if isinstance(tickers, str): + tickers = tickers.replace("\n", ";").split(";") - self._n = len(self._tickers) + self._tickers = tickers + self._n = len(tickers) self._start = start self._end = end self._seed = seed diff --git a/qiskit_finance/data_providers/wikipedia_data_provider.py b/qiskit_finance/data_providers/wikipedia_data_provider.py index 3994ff3..061899a 100644 --- a/qiskit_finance/data_providers/wikipedia_data_provider.py +++ b/qiskit_finance/data_providers/wikipedia_data_provider.py @@ -55,16 +55,15 @@ def __init__( Default is January 30th, 2016. """ super().__init__() - self._tickers = None - tickers = tickers if tickers is not None else [] - if isinstance(tickers, list): - self._tickers = tickers - else: - self._tickers = tickers.replace("\n", ";").split(";") - self._n = len(self._tickers) - self._token = token + if tickers is None: + tickers = [] + if isinstance(tickers, str): + tickers = tickers.replace("\n", ";").split(";") + self._tickers = tickers + self._n = len(tickers) + self._token = token self._start = start.strftime("%Y-%m-%d") self._end = end.strftime("%Y-%m-%d") self._data = [] diff --git a/qiskit_finance/data_providers/yahoo_data_provider.py b/qiskit_finance/data_providers/yahoo_data_provider.py index 5df6752..bbe5cf3 100644 --- a/qiskit_finance/data_providers/yahoo_data_provider.py +++ b/qiskit_finance/data_providers/yahoo_data_provider.py @@ -54,7 +54,7 @@ def __init__( - If a string is provided, it can be a single ticker symbol or multiple symbols separated by semicolons or newlines. - If a list of strings is provided, each string should be a single ticker symbol. - Default is None, meaning no tickers provided. + Default is :code:`None`, meaning no tickers provided. start (datetime.datetime): Start date of the data. Default is January 1st, 2016. end (datetime.datetime): End date of the data. @@ -62,15 +62,13 @@ def __init__( """ super().__init__() - self._tickers = None - tickers = tickers if tickers is not None else [] - if isinstance(tickers, list): - self._tickers = tickers - else: - self._tickers = tickers.replace("\n", ";").split(";") - - self._n = len(self._tickers) + if tickers is None: + tickers = [] + if isinstance(tickers, str): + tickers = tickers.replace("\n", ";").split(";") + self._tickers = tickers + self._n = len(tickers) self._start = start.strftime("%Y-%m-%d") self._end = end.strftime("%Y-%m-%d") self._data = []