This project is archived

Qiskit Finance is no longer maintained and this documentation is no longer updated. It is kept online for reference only, and the code it describes may not work with current versions of Qiskit. See the project repository for more information.

Source code for qiskit_finance.data_providers.exchange_data_provider

# This code is part of a Qiskit project.
#
# (C) Copyright IBM 2019, 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

""" Exchange data provider. """

from typing import Union, List
import logging
import datetime
import nasdaqdatalink

from ._base_data_provider import BaseDataProvider, StockMarket
from ..exceptions import QiskitFinanceError

logger = logging.getLogger(__name__)


[docs]class ExchangeDataProvider(BaseDataProvider): """Exchange data provider. Please see: https://qiskit-community.github.io/qiskit-finance/tutorials/11_time_series.html for instructions on use, which involve obtaining a Nasdaq Data Link access token. """ def __init__( self, token: str, tickers: Union[str, List[str]], stockmarket: StockMarket = StockMarket.LONDON, start: datetime.datetime = datetime.datetime(2016, 1, 1), end: datetime.datetime = datetime.datetime(2016, 1, 30), ) -> None: """ Args: token: Nasdaq Data Link access token tickers: tickers stockmarket: LONDON, EURONEXT, or SINGAPORE start: first data point end: last data point precedes this date Raises: QiskitFinanceError: provider doesn't support given stock market """ super().__init__() self._tickers = [] # type: Union[str, List[str]] 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." raise QiskitFinanceError(msg) # This is to aid serialization; string is ok to serialize self._stockmarket = str(stockmarket.value) self._token = token self._tickers = tickers self._start = start.strftime("%Y-%m-%d") self._end = end.strftime("%Y-%m-%d")
[docs] def run(self) -> None: """ Loads data, thus enabling get_similarity_matrix and get_covariance_matrix methods in the base class. """ nasdaqdatalink.ApiConfig.api_key = self._token self._data = [] stocks_notfound = [] stocks_forbidden = [] for _, ticker_name in enumerate(self._tickers): stock_data = None name = self._stockmarket + "/" + ticker_name try: stock_data = nasdaqdatalink.get(name, start_date=self._start, end_date=self._end) except nasdaqdatalink.AuthenticationError as ex: logger.debug(ex, exc_info=True) raise QiskitFinanceError("Nasdaq Data Link invalid token.") from ex except nasdaqdatalink.LimitExceededError as ex: logger.debug(ex, exc_info=True) raise QiskitFinanceError("Nasdaq Data Link limit exceeded.") from ex except nasdaqdatalink.NotFoundError as ex: logger.debug(ex, exc_info=True) stocks_notfound.append(name) continue except nasdaqdatalink.ForbiddenError as ex: logger.debug(ex, exc_info=True) stocks_forbidden.append(name) continue except nasdaqdatalink.DataLinkError as ex: logger.debug(ex, exc_info=True) raise QiskitFinanceError(f"Nasdaq Data Link Error for '{name}'.") from ex try: self._data.append(stock_data["Close"]) except KeyError as ex: raise QiskitFinanceError(f"Cannot parse Nasdaq Data Link '{name}' output.") from ex if stocks_notfound or stocks_forbidden: err_msg = f"Stocks not found: {stocks_notfound}. " if stocks_notfound else "" if stocks_forbidden: err_msg += ( "You do not have permission to view this data. " f"Please subscribe to this database: {stocks_forbidden}" ) raise QiskitFinanceError(err_msg)