### Install qf-lib from source Source: https://qf-lib.readthedocs.io/en/latest/installation Installs the qf-lib Python package by building it from the source code. This method requires cloning the repository and running the setup script. ```bash $ python setup.py install ``` -------------------------------- ### Install Interactive Brokers Python client Source: https://qf-lib.readthedocs.io/en/latest/installation Installs the Python client library for the Interactive Brokers TWS API. This involves downloading the TWS API, installing it, and then installing the Python client from its source directory. ```bash python setup.py install ``` -------------------------------- ### Install qf-lib using pip Source: https://qf-lib.readthedocs.io/en/latest/installation Installs the qf-lib Python package using pip. This is the recommended method for most users. ```bash $ pip install qf-lib ``` -------------------------------- ### Configure and Start Backtest Trading Session in Python Source: https://qf-lib.readthedocs.io/en/latest/tutorials/first_strategy_backtest This Python code demonstrates how to configure and initiate a backtesting trading session using qf-lib. It sets up the session parameters, including dates, ticker, frequency, and names, and then starts the trading process with the defined strategy. ```python def main(): # settings backtest_name = 'Simple MA Strategy Demo' start_date = str_to_date("2010-01-01") end_date = str_to_date("2015-03-01") ticker = DummyTicker("AAA") # configuration settings = get_demo_settings() pdf_exporter = PDFExporter(settings) excel_exporter = ExcelExporter(settings) session_builder = BacktestTradingSessionBuilder(settings, pdf_exporter, excel_exporter) session_builder.set_frequency(Frequency.DAILY) session_builder.set_backtest_name(backtest_name) session_builder.set_data_provider(daily_data_provider) ts = session_builder.build(start_date, end_date) strategy = SimpleMAStrategy(ts, ticker) CalculateAndPlaceOrdersRegularEvent.set_daily_default_trigger_time() CalculateAndPlaceOrdersRegularEvent.exclude_weekends() strategy.subscribe(CalculateAndPlaceOrdersRegularEvent) ts.start_trading() ``` -------------------------------- ### Setup Commission Model - Python Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/backtesting/trading_session/backtest_trading_session_builder Initializes and returns a commission model instance using provided keyword arguments. ```Python def _commission_model_setup(self): return self._commission_model_type(**self._commission_model_kwargs) ``` -------------------------------- ### Install Quandl Data Provider Source: https://qf-lib.readthedocs.io/en/latest/installation Installs the Quandl Data Provider for qf-lib using pip, specifying a particular version of the quandl library. ```bash $ pip install quandl==3.6.1 ``` -------------------------------- ### CSVDataProvider Initialization Example (Python) Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/csv/csv_data_provider Demonstrates how to initialize the CSVDataProvider with a path, tickers, index column, field mapping, date range, and frequency. This setup is crucial for loading and accessing CSV data correctly. ```Python start_date = str_to_date("2018-01-01") end_date = str_to_date("2022-01-01") index_column = 'Open time' field_to_price_field_dict = { 'Open': PriceField.Open, 'High': PriceField.High, 'Low': PriceField.Low, 'Close': PriceField.Close, 'Volume': PriceField.Volume, } tickers = #create your ticker here. ticker.as_string() should match file name, unless you specify ticker_col path = "C:\\data_dir" data_provider = CSVDataProvider(path, tickers, index_column, field_to_price_field_dict, start_date, end_date, Frequency.MIN_1) ``` -------------------------------- ### Install Bloomberg Data Provider Source: https://qf-lib.readthedocs.io/en/latest/installation Installs the Bloomberg Data Provider for qf-lib using pip, specifying a particular version of the blpapi library. Requires pip version 19.0 or higher on Linux. ```bash $ pip install --index-url=https://bcms.bloomberg.com/pip/simple/ blpapi==3.20.1 ``` -------------------------------- ### Get Common Start and End Dates Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.common.utils.dateutils.common_start_and_end Calculates the earliest start date and latest end date across multiple time-indexed containers, considering only valid data points. ```APIDOC ## GET /common/dateutils/common_start_and_end ### Description Finds the first and last valid dates (with a value different than NaN) for each column and then returns the latest of starting dates and the soonest ending date. If one of containers is a dataframe, then it is split into separate columns first. ### Method GET ### Endpoint /common/dateutils/common_start_and_end ### Parameters #### Query Parameters - **containers** (TimeIndexedContainer) - Required - Containers for which the common beginning and ending should be found. ### Request Example ```json { "containers": [ { "type": "TimeIndexedContainer", "data": [ {"timestamp": "2023-01-01T00:00:00Z", "value": 10}, {"timestamp": "2023-01-02T00:00:00Z", "value": 20} ] } ] } ``` ### Response #### Success Response (200) - **common_start** (datetime) - The soonest date on which data for all series is already available. - **common_end** (datetime) - The latest date on which data for all series is still available. #### Response Example ```json { "common_start": "2023-01-01T00:00:00Z", "common_end": "2023-01-02T00:00:00Z" } ``` ``` -------------------------------- ### Get Common Start and End Dates - Python Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/common/utils/dateutils/common_start_and_end Calculates the earliest start date and latest end date across provided TimeIndexedContainers (QFSeries or QFDataFrame). Handles DataFrames by processing each column individually. Returns a tuple of datetime objects representing the common start and end. ```python # Copyright 2016-present CERN – European Organization for Nuclear Research # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime from typing import Tuple from qf_lib.containers.series.qf_series import QFSeries from qf_lib.containers.dataframe.qf_dataframe import QFDataFrame from qf_lib.containers.time_indexed_container import TimeIndexedContainer [docs] def get_common_start_and_end(*containers: TimeIndexedContainer) -> Tuple[datetime, datetime]: """ Finds the first and last valid dates (with a value different than NaN) for each column and then returns the latest of starting dates and the soonest ending date. If one of containers is dataframe then it is split into separate columns first. Parameters ---------- containers containers for which the common beginning and ending should be found Returns ------- Tuple[datetime, datetime] (common_start, common_end) - (soonest date on which data for all series is already available, latest date on which data for all series is still available) """ start_dates = [] end_dates = [] for container in containers: if isinstance(container, QFDataFrame): start_date = container.apply(lambda col: col.first_valid_index()).max() start_dates.append(start_date) end_date = container.apply(lambda col: col.last_valid_index()).min() end_dates.append(end_date) elif isinstance(container, QFSeries): start_dates.append(container.first_valid_index()) end_dates.append(container.last_valid_index()) common_start = max(start_dates) common_end = min(end_dates) return common_start, common_end ``` -------------------------------- ### Get Common Start and End Dates from TimeIndexedContainers Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.common.utils.dateutils.common_start_and_end This function computes the earliest start date and latest end date for valid data across one or more TimeIndexedContainer objects. It handles DataFrames by processing each column separately. The result is a tuple containing the common start and end datetimes. ```python from qf_lib.common.utils.dateutils.common_start_and_end import get_common_start_and_end from qf_lib.containers.time_indexed_container import TimeIndexedContainer # Example usage: # Assuming 'containers' is a list or tuple of TimeIndexedContainer objects # common_start, common_end = get_common_start_and_end(containers) ``` -------------------------------- ### Set Starting Directory (Python) Source: https://qf-lib.readthedocs.io/en/latest/configuration Sets the absolute path for the starting directory, used to resolve relative paths within the QF-Lib project. This function is essential for ensuring that all path references are correctly interpreted. ```python from qf_lib.settings import Settings settings_path = ... secret_settings_path = ... settings = Settings(settings_path, secret_settings_path) ``` -------------------------------- ### Setup Orders Filter - Python Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/backtesting/trading_session/backtest_trading_session_builder Creates and returns a list of order filter instances. Each filter is initialized with a data provider and specific keyword arguments. ```Python def _orders_filter_setup(self): orders_filters = [] for orders_filter_type, kwargs in self._orders_filter_types_params: orders_filter = orders_filter_type(self._data_provider, **kwargs) orders_filters.append(orders_filter) return orders_filters ``` -------------------------------- ### Importing Volatility Forecasting Dependencies Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/common/utils/volatility/volatility_forecast This code snippet checks for the installation of the 'arch' library, which is required for advanced volatility forecasting. If 'arch' is not found, it issues a warning and exits, guiding the user on how to install the necessary dependencies. ```python import warnings try: from arch.univariate import ConstantMean, Normal from arch.univariate.volatility import VolatilityProcess is_arch_installed = True except ImportError: is_arch_installed = False from qf_lib.common.enums.frequency import Frequency from qf_lib.common.utils.miscellaneous.annualise_with_sqrt import annualise_with_sqrt from qf_lib.containers.series.log_returns_series import LogReturnsSeries from qf_lib.containers.series.qf_series import QFSeries ``` -------------------------------- ### Create Daily Backtest Trading Session Source: https://qf-lib.readthedocs.io/en/latest/tutorials/first_strategy_backtest Builds a daily trading session for backtesting a strategy with specified dates and data provider. It configures the session using demo settings and exporters. ```python def main(): ticker = DummyTicker("AAA") start_date = str_to_date("2010-01-01") end_date = str_to_date("2015-03-01") settings = get_demo_settings() pdf_exporter = PDFExporter(settings) excel_exporter = ExcelExporter(settings) session_builder = BacktestTradingSessionBuilder(settings, pdf_exporter, excel_exporter) session_builder.set_frequency(Frequency.DAILY) session_builder.set_data_provider(daily_data_provider) ts = session_builder.build(start_date, end_date) ``` -------------------------------- ### Get Supported Ticker Type Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.containers.futures.future_tickers.portara_future_ticker Returns the class of specific tickers supported by this FutureTicker. For example, it should return BloombergTicker for BloombergFutureTicker. ```python def supported_ticker_type() -> Type[Ticker]: """Returns class of specific tickers which are supported by this FutureTicker (e.g. it should return BloombergTicker for the BloombergFutureTicker etc.""" pass ``` -------------------------------- ### Initialize BloombergBeapHapiDataProvider Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/bloomberg_beap_hapi/bloomberg_beap_hapi_data_provider Initializes the BloombergBeapHapiDataProvider with settings and optional timer. It sets up the parser, reply timeout, download path, and a requests session, including mounting a BEAP adapter if the beap_lib is installed. ```python import json import os import warnings from datetime import datetime, timedelta from pathlib import Path from typing import Union, Sequence, Dict, List, Optional, Tuple from urllib.parse import urljoin from warnings import warn import pandas as pd import requests from qf_lib.common.enums.security_type import SecurityType from qf_lib.common.utils.dateutils.relative_delta import RelativeDelta from qf_lib.common.utils.dateutils.timer import Timer from qf_lib.containers.futures.future_tickers.future_ticker import FutureTicker from qf_lib.data_providers.futures_data_provider import FuturesDataProvider from qf_lib.data_providers.tickers_universe_provider import TickersUniverseProvider try: from beap_lib.beap_auth import Credentials, BEAPAdapter from beap_lib.sseclient import SSEClient is_beap_lib_installed = True except ImportError: is_beap_lib_installed = False from qf_lib.data_providers.bloomberg.exceptions import BloombergError from qf_lib.common.enums.expiration_date_field import ExpirationDateField from qf_lib.common.enums.frequency import Frequency from qf_lib.common.enums.price_field import PriceField from qf_lib.common.tickers.tickers import BloombergTicker from qf_lib.common.utils.miscellaneous.to_list_conversion import convert_to_list from qf_lib.containers.dataframe.qf_dataframe import QFDataFrame from qf_lib.containers.futures.future_tickers.bloomberg_future_ticker import BloombergFutureTicker from qf_lib.containers.qf_data_array import QFDataArray from qf_lib.containers.series.qf_series import QFSeries from qf_lib.data_providers.abstract_price_data_provider import AbstractPriceDataProvider from qf_lib.data_providers.bloomberg_beap_hapi.bloomberg_beap_hapi_fields_provider import \ BloombergBeapHapiFieldsProvider from qf_lib.data_providers.bloomberg_beap_hapi.bloomberg_beap_hapi_parser import BloombergBeapHapiParser from qf_lib.data_providers.bloomberg_beap_hapi.bloomberg_beap_hapi_request_provider import \ BloombergBeapHapiRequestsProvider from qf_lib.data_providers.bloomberg_beap_hapi.bloomberg_beap_hapi_universe_provider import \ BloombergBeapHapiUniverseProvider from qf_lib.data_providers.helpers import normalize_data_array, cast_dataframe_to_proper_type from qf_lib.settings import Settings from qf_lib.starting_dir import get_starting_dir_abs_path [docs] class BloombergBeapHapiDataProvider(AbstractPriceDataProvider, TickersUniverseProvider, FuturesDataProvider): """ Data Provider which provides financial data from Bloomberg BEAP HAPI. The settings file requires the following variables: - hapi_credentials.client_id - hapi_credentials.client_secret - hapi_credentials.expiration_date - output_directory Other optional settings parameters: - hapi_credentials.user (parameter to link the Data License to a Bloomberg Anywhere or Bloomberg Professional account; the User value can be obtained by running IAM in the Bloomberg terminal) - hapi_crenetials.sn (parameter to link the Data License to a Bloomberg Professional account; the S/N value can be obtained by running IAM in the Bloomberg terminal) """ def __init__(self, settings: Settings, reply_timeout: int = 5, timer: Optional[Timer] = None): super().__init__(timer=timer) warn( f'{self.__class__.__name__} is deprecated due to the removal of the beap_lib library. ' f'It will be replaced with a new data provider that communicates with Bloomberg DL via the REST API.', DeprecationWarning, stacklevel=2 ) self.parser = BloombergBeapHapiParser() host = 'https://api.bloomberg.com' self.reply_timeout = timedelta(minutes=reply_timeout) # reply_timeout - time in minutes output_folder = "hapi_responses" self.downloads_path = Path(get_starting_dir_abs_path()) / settings.output_directory / output_folder self.downloads_path.mkdir(parents=True, exist_ok=True) self.session = requests.Session() if is_beap_lib_installed: adapter = BEAPAdapter(Credentials.from_dict( {'client_id': settings.hapi_credentials.client_id, 'client_secret': settings.hapi_credentials.client_secret, 'expiration_date': settings.hapi_credentials.expiration_date} )) self.session.mount('https://', adapter) self.sse_client = self._get_sse_client(host, self.session) self.catalog_id = self._get_catalog_id(host) account_url = urljoin(host, f'/eap/catalogs/{self.catalog_id}/') trigger_url = urljoin(host, f"/eap/catalogs/{self.catalog_id}/triggers/prodDataStreamTrigger/") terminal_identity_user = self._get_settings_attribute(settings.hapi_credentials, "user") terminal_identity_sn = self._get_settings_attribute(settings.hapi_credentials, "sn") ``` -------------------------------- ### Get Signal Evaluation Dates - Python Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/analysis/signals_analysis/signals_plotter Calculates and returns a series of dates for signal evaluation based on specified start and end dates and signal frequency. Handles daily and more frequent signals. ```python def _get_signals_dates(self): """ returns dates of signal evaluation """ evaluation_dates = [] if self.signal_frequency == Frequency.DAILY: evaluation_dates = date_range(self.start_date, self.end_date, freq=self.signal_frequency.to_pandas_freq()) elif self.signal_frequency > Frequency.DAILY: days_dates = date_range(self.start_date, self.end_date, freq="D") signal_time_holder = [] for day in days_dates: start_time = day + MarketOpenEvent.trigger_time() end_time = day + MarketCloseEvent.trigger_time() signal_times_for_a_day = date_range(start_time, end_time, freq=self.signal_frequency.to_pandas_freq()) signal_time_holder.append(signal_times_for_a_day) evaluation_dates = signal_time_holder[0] for idx in signal_time_holder[1:]: evaluation_dates = evaluation_dates.union(idx) return evaluation_dates ``` -------------------------------- ### Settings File Structure (JSON) Source: https://qf-lib.readthedocs.io/en/latest/configuration Demonstrates the structure of JSON files used for QF-Lib configuration. Includes sample content for both general settings and sensitive secret settings. ```json { "some_setting": "value of that setting", "another_setting": "value of another setting", "some_connection_settings": { "username": "john.smith" } } ``` ```json { "some_connection_settings": { "password": "my_secret_pass" } } ``` -------------------------------- ### Get Market Stress Indicator Timeseries Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.indicators.market_stress_indicator_us Retrieves the timeseries of the market stress indicator. This method allows specifying the rolling window in years, the start and end dates for the indicator, and the step in days for the rolling window shift. ```python def get_indicator(_years_rolling : float_, _start_date : datetime_, _end_date : datetime_, _step : int = 1_) → QFSeries[source]: """Returns the timeseries of the indicator.""" # ... implementation details ... ``` -------------------------------- ### HaverDataProvider Constructor Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.data_providers.haver.haver_data_provider Initializes the HaverDataProvider with settings containing the path to the Haver database. ```python class HaverDataProvider(AbstractPriceDataProvider): def __init__(self, settings: Settings_): """Constructs a new HaverDataProvider instance.""" pass ``` -------------------------------- ### AlphaModel Initialization and Signal Generation (Python) Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/backtesting/alpha_model/alpha_model Demonstrates the initialization of an AlphaModel, which includes setting up a risk estimation factor, a data provider, and a logger. It also shows the `get_signal` method, which orchestrates the calculation of suggested exposure, fraction at risk, and ultimately creates a `Signal` object. ```python from abc import abstractmethod, ABCMeta from datetime import datetime from numpy import nan from qf_lib.backtesting.alpha_model.exposure_enum import Exposure from qf_lib.backtesting.signals.signal import Signal from qf_lib.common.enums.frequency import Frequency from qf_lib.common.enums.price_field import PriceField from qf_lib.common.tickers.tickers import Ticker from qf_lib.common.utils.logging.qf_parent_logger import qf_logger from qf_lib.common.utils.miscellaneous.average_true_range import average_true_range from qf_lib.data_providers.abstract_price_data_provider import AbstractPriceDataProvider class AlphaModel(metaclass=ABCMeta): """ Base class for all alpha models. Parameters ---------- risk_estimation_factor float value which estimates the risk level of the specific AlphaModel. Corresponds to the level at which the stop-loss should be placed. data_provider: AbstractPriceDataProvider DataProvider which provides data for the ticker. """ def __init__(self, risk_estimation_factor: float, data_provider: AbstractPriceDataProvider): self.risk_estimation_factor = risk_estimation_factor self.data_provider = data_provider self.logger = qf_logger.getChild(self.__class__.__name__) def get_signal(self, ticker: Ticker, current_exposure: Exposure, current_time: datetime, frequency: Frequency) \ -> Signal: """ Returns the Signal calculated for a specific AlphaModel and a set of data for a specified Ticker Parameters ---------- ticker: Ticker A ticker of an asset for which the Signal should be generated current_exposure: Exposure The actual exposure, based on which the AlphaModel should return its Signal. Can be different from previous Signal suggestions, but it should correspond with the current trading position current_time: datetime current time, which is afterwards recorded inside each of the Signals. The parameter is optional and if not provided, defaults to the current user time. frequency: Frequency frequency of data obtained by the data provider for signal calculation Returns ------- Signal Signal being the suggestion for the next trading period """ suggested_exposure = self.calculate_exposure(ticker, current_exposure, current_time, frequency) fraction_at_risk = self.calculate_fraction_at_risk(ticker, current_time, frequency) last_available_price = self.data_provider.get_last_available_price(ticker, frequency, current_time) signal = Signal(ticker, suggested_exposure, fraction_at_risk, last_available_price, current_time, alpha_model=self) return signal ``` -------------------------------- ### MarketStressIndicator: Get Indicator Time Series Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/indicators/market_stress_indicator_us Retrieves the time series of the market stress indicator. It fetches historical data, calculates rolling z-scores, and applies weights. Parameters include the rolling window in years, start and end dates, and a step for the rolling window. ```python def get_indicator(self, years_rolling: float, start_date: datetime, end_date: datetime, step: int = 1) -> QFSeries: """Returns the timeseries of the indicator. Parameters ------------ years_rolling: float How may years of the history is used for to evaluate the single point start_date: datetime start date of the indicator returned end_date: datetime end date of the indicator returned step: int how many day is the rolling window shifted. It aslo tells us the step of the returned indicator in days Returns ------- QFSeries Timeseries of market stress indicator """ underlying_start_date = start_date - timedelta(days=floor(years_rolling * 365 * 1.1)) data = self.data_provider.get_price(self.tickers, PriceField.Close, underlying_start_date, end_date) data = data.fillna(method='ffill') # data = data.dropna() # this line can be enabled but it will shift starting point by the years_rolling window_size = floor(252 * years_rolling) stress_indicator_tms = data.rolling_time_window( window_length=window_size, step=step, func=self._rolling_stress_indicator) stress_indicator_tms = stress_indicator_tms.loc[start_date:] return stress_indicator_tms ``` -------------------------------- ### Setup Slippage Model - Python Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/backtesting/trading_session/backtest_trading_session_builder Initializes and returns a slippage model instance. The model is configured with a data provider and specific keyword arguments. ```Python def _slippage_model_setup(self): return self._slippage_model_type(data_provider=self._data_provider, **self._slippage_model_kwargs) ``` -------------------------------- ### Initialize BloombergBeapHapiDataProvider Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/bloomberg_beap_hapi/bloomberg_beap_hapi_data_provider Initializes the BloombergBeapHapiDataProvider with necessary connection details for Bloomberg HAPI. It sets up providers for universe, fields, and requests, and handles connection status and logging. If Beap HAPI is not installed, it issues a warning and exits. ```python self.universe_hapi_provider = BloombergBeapHapiUniverseProvider(host, self.session, account_url) self.fields_hapi_provider = BloombergBeapHapiFieldsProvider(host, self.session, account_url) self.request_hapi_provider = BloombergBeapHapiRequestsProvider(host, self.session, account_url, trigger_url, terminal_identity_user, terminal_identity_sn) self.logger.info("Scheduled catalog URL: %s", account_url) self.logger.info("Scheduled trigger URL: %s", trigger_url) self.connected = True else: self.catalog_id = None self.universe_hapi_provider = None self.fields_hapi_provider = None self.request_hapi_provider = None self.connected = False warnings.warn( "No Bloomberg Beap HAPI installed. If you would like to use BloombergBeapHapiDataProvider first " "install the beap_lib with all necessary dependencies.") exit(1) ``` -------------------------------- ### Get Futures Price Data Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.containers.futures.futures_chain Retrieves a chain of prices for a given FutureTicker. This method combines data from consecutive FutureContracts, automatically managing the chaining based on the specified method. It requires specifying the desired data fields, start date, end date, and optionally the data frequency. ```python get_price(_fields : Union[PriceField, Sequence[PriceField]]_, _start_date : datetime_, _end_date : datetime_, _frequency : Frequency = Frequency.DAILY_) → Union[PricesDataFrame, PricesSeries] ``` -------------------------------- ### Get Last Available Price (Intraday Frequency) (Python) Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/abstract_price_data_provider Retrieves the last available prices for tickers with intraday frequency. This function is a precursor to more detailed intraday price handling and shares initial setup logic with its daily counterpart. Dependencies include nan, QFSeries, convert_to_list, Frequency, and datetime. ```python def _last_available_price_settable_timer_intraday(self, tickers: Union[Ticker, Sequence[Ticker]], frequency: Frequency = None, end_time: Optional[datetime] = None) -> Union[float, QFSeries]: tickers, got_single_ticker = convert_to_list(tickers, Ticker) if not tickers: ``` -------------------------------- ### Setup Backtest Monitor - Python Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/backtesting/trading_session/backtest_trading_session_builder Initializes and returns a BacktestMonitor instance. This monitor is used for tracking and reporting backtest results, utilizing provided settings and exporters. ```Python def _monitor_setup(self) -> BacktestMonitor: monitor = BacktestMonitor(self._backtest_result, self._settings, self._pdf_exporter, self._excel_exporter, self._monitor_settings, self._benchmark_tms) return monitor ``` -------------------------------- ### Instantiate BacktestTradingSessionBuilder Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.backtesting.trading_session.backtest_trading_session_builder Demonstrates how to instantiate the BacktestTradingSessionBuilder class, which requires Settings, PDFExporter, and ExcelExporter objects. ```python from qf_lib.backtesting.trading_session.backtest_trading_session_builder import BacktestTradingSessionBuilder # Assuming you have instances of Settings, PDFExporter, and ExcelExporter settings = Settings(...) pdf_exporter = PDFExporter(...) excel_exporter = ExcelExporter(...) builder = BacktestTradingSessionBuilder(settings, pdf_exporter, excel_exporter) ``` -------------------------------- ### Get Chained Futures Prices with Date and Frequency Specification Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/containers/futures/futures_chain Retrieves a continuous chain of prices for a specified future ticker. It handles the automatic chaining of consecutive future contracts based on expiry dates. The function supports specifying data fields, start and end dates, and the data frequency. ```python from datetime import datetime from qf_lib.common.enums.frequency import Frequency from qf_lib.common.enums.price_field import PriceField # Assuming 'futures_chain' is an initialized instance of FuturesChain # start_date = datetime(2023, 1, 1) # end_date = datetime(2023, 12, 31) # fields = [PriceField.CLOSE, PriceField.VOLUME] # prices_data = futures_chain.get_price(fields, start_date, end_date, Frequency.DAILY) ``` -------------------------------- ### BinanceDataProvider Class Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.data_providers.binance_dp.binance_data_provider Initializes the BinanceDataProvider with specified parameters for downloading and managing Binance data. ```APIDOC ## BinanceDataProvider Class ### Description Initializes the BinanceDataProvider, which downloads financial data from Binance within a specified date range and saves it to CSV files. This provider is suitable for both historical analysis and live trading scenarios. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Constructor Parameters - **path** (str) - Required - The directory path where the downloaded CSV files will be saved. - **filename** (str) - Required - The base name for the CSV file. A timestamp will be appended to differentiate files (e.g., "Binance_data_YYYY-MM-DD HH_MM_SS.csv"). - **tickers** (Union[Ticker, Sequence[Ticker]]) - Required - A single Ticker object or a sequence of Ticker objects to specify which assets to download data for. - **start_date** (datetime) - Required - The beginning of the data range in local time. This will be automatically converted to UTC for Binance API calls. - **end_date** (datetime) - Required - The end of the data range in local time. This will be automatically converted to UTC for Binance API calls. For live trading, this can be set to the current time. - **contract_ticker_mapper** (BinanceContractTickerMapper) - Required - An instance of BinanceContractTickerMapper that holds parameters for each ticker and maps them to broker-specific contract/ticker objects for order placement. - **frequency** (Frequency) - Optional - The time interval for the data points. Defaults to `Frequency.MIN_1` (1-minute intervals). ### Example Usage ```python from datetime import datetime from qf_lib.data_providers.binance_dp.binance_contract_ticker_mapper import BinanceContractTickerMapper from qf_lib.data_providers.binance_dp.binance_data_provider import BinanceDataProvider from qf_lib.common.enums import Frequency from qf_lib.common.ticker import Ticker # Assuming you have Ticker and BinanceContractTickerMapper objects configured tickers_to_download = Ticker("BTC-USD") contract_mapper = BinanceContractTickerMapper() data_provider = BinanceDataProvider( path="/data/binance/", filename="BTC_USD_data", tickers=tickers_to_download, start_date=datetime(2023, 1, 1), end_date=datetime(2023, 1, 31), contract_ticker_mapper=contract_mapper, frequency=Frequency.MIN_15 ) # Now you can use the data_provider to fetch data, e.g.: # prices = data_provider.get_price(tickers_to_download) ``` ``` -------------------------------- ### Portfolio Class Initialization and Attributes Source: https://qf-lib.readthedocs.io/en/latest/_autosummary/qf_lib.backtesting.portfolio.portfolio Initializes a Portfolio object and describes its key attributes for tracking cash, exposure, and open positions. Requires an AbstractPriceDataProvider and initial cash. ```python class Portfolio(_data_provider : AbstractPriceDataProvider_, _initial_cash : float_, _currency : Optional[str] = None_): """ Attributes: current_cash: Represents the free cash in the portfolio. gross_exposure_of_positions: Equals the sum of the absolute value of all positions except cash. net_liquidation: Cash value includes futures P&L + stock value + securities options value + bond value + fund value. open_positions_dict: Represents all open positions at a certain moment. """ pass ``` -------------------------------- ### Get Backtest Dates Based on Frequency Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/backtesting/fast_alpha_model_tester/fast_alpha_models_tester Retrieves a series indexed by dates for signal generation. It supports DAILY frequency by creating a date range and higher frequencies by generating time points within each day based on start and end times. It can also mark dates for closing positions. Dependencies include pandas, QFSeries, and Frequency enum. ```python def _get_backtest_dates(self) -> QFSeries: """ Returns series indexed by all dates that will be used for signal generation. Value of series == 1 it means that we need to close the position at the end of the day """ if self._frequency == Frequency.DAILY: backtest_dates = pd.date_range(self._start_date, self._end_date, freq="D") backtest_dates = QFSeries(backtest_dates.to_series()) backtest_dates[:] = 0 elif self._frequency > Frequency.DAILY: days_dates = pd.date_range(self._start_date, self._end_date, freq="D") signal_time_holder = [] for day in days_dates: start_time = day + RelativeDelta(**self._start_time) end_time = day + RelativeDelta(**self._end_time) signal_times_for_a_day = pd.date_range(start_time, end_time, freq=self._frequency.to_pandas_freq()) signal_times_for_a_day = QFSeries(signal_times_for_a_day.to_series()) signal_times_for_a_day[:] = 0 if self._close_position_at_the_end_of_day: # add additional stamp or override existing with info to close the position signal_times_for_a_day[end_time] = 1 signal_time_holder.append(signal_times_for_a_day) backtest_dates = pd.concat(signal_time_holder) return backtest_dates ``` -------------------------------- ### DocumentExporter Initialization and Directory Management Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/documents_utils/document_exporting/document_exporter Initializes the DocumentExporter with settings and provides a method to get or create output directories. It takes a settings object, uses the output_directory from settings to construct the root output directory, and creates the directory if it doesn't exist. ```python # Copyright 2016-present CERN – European Organization for Nuclear Research # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os from os.path import join from typing import Sequence from qf_lib.documents_utils.document_exporting.document import Document from qf_lib.documents_utils.document_exporting.element.front_page import FrontPage from qf_lib.documents_utils.document_exporting.element.header import HeaderElement from qf_lib.documents_utils.document_exporting.element.index import IndexElement from qf_lib.settings import Settings from qf_lib.starting_dir import get_starting_dir_abs_path class DocumentExporter: """ Abstract class for document_exporting of documents. """ def __init__(self, settings: Settings): self._output_root_dir = join(get_starting_dir_abs_path(), settings.output_directory) def get_output_dir(self, export_dir: str) -> str: """ Converts a partial path (`export_dir`) which is relative to the output root directory into a path which is relative to the current working directory. Parameters ---------- export_dir relative path (relative to the output root directory) of the directory in which the generated document should be saved Returns ------- absolute path of the directory in which the generated document should be saved """ output_dir = os.path.join(self._output_root_dir, export_dir) if not os.path.exists(output_dir): os.makedirs(output_dir) return output_dir @staticmethod def _merge_documents(documents: Sequence[Document], filename: str) -> Document: """ Merges documents into a single document. All elements inside the documents are placed in the returned document. Parameters ---------- documents a list of documents to merge filename The filename that should be applied to the resulting document. """ result = Document(filename) for document in documents: for element in document.elements: result.add_element(element) return result @classmethod def _add_table_of_contents(cls, document): # Ideally we would like to add a table of contents after the Header element. # Check if a header element is the first element. if isinstance(document.elements[0], (HeaderElement, FrontPage)): # If it is the first element then insert the table of contents after it. document.elements.insert(1, IndexElement(4)) else: # Otherwise insert it as the first element. document.elements.insert(0, IndexElement(4)) ``` -------------------------------- ### Initialize FastAlphaModelTester with Time Configuration Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/backtesting/fast_alpha_model_tester/fast_alpha_models_tester Demonstrates initializing the FastAlphaModelTester with start and end times, specifying behavior for intra-day trading frequencies. Handles configuration validation and logging. ```python self._frequency = frequency self._start_time = start_time self._end_time = end_time self._close_position_at_the_end_of_day = close_position_at_the_end_of_day # use 1min data frequency for data if signal generation is intra-day. # use Daily frequency for any other time frame self._data_frequency = Frequency.MIN_1 if self._frequency > Frequency.DAILY else Frequency.DAILY assert len(set(config.model_type for config in alpha_model_configs)) == 1, \ "All passed FastAlphaModelTesterConfig should have the same alpha model type" self._model_type = alpha_model_configs[0].model_type if self._frequency > Frequency.DAILY: assert self._start_time is not None, "Start time cannot be none for frequency higher than daily" assert self._end_time is not None, "End time cannot be none for frequency higher than daily" # add zeroed second ad microseconds to create clean bars self._start_time["second"] = 0 self._start_time["microsecond"] = 0 self._end_time["second"] = 0 self._end_time["microsecond"] = 0 else: if self._start_time is not None or self._end_time is not None: self.logger.warning("Start time and end time will be ignored for frequency lower than daily") ``` -------------------------------- ### GET /_last_available_price Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/preset_data_provider Retrieves the last available price (Close price of the latest bar) for specified tickers. Useful for getting the most recent trading information. ```APIDOC ## GET /_last_available_price ### Description Retrieves the last available price (Close price of the latest bar) for specified tickers. Useful for getting the most recent trading information. ### Method GET ### Endpoint /_last_available_price ### Parameters #### Query Parameters - **tickers** (Union[Ticker, Sequence[Ticker]]) - Required - The ticker symbol(s) for which to retrieve the last available price. - **frequency** (Optional[Frequency]) - Optional - The frequency of the data to consider. Defaults to the instance's frequency or DAILY. - **end_time** (Optional[datetime]) - Optional - The end time for searching the last available price. Defaults to the current time or the end of the last trading day. ### Request Example ```json { "tickers": ["AAPL", "GOOG"], "frequency": "DAILY" } ``` ### Response #### Success Response (200) - **float** or **PricesSeries**: The last available closing price. Returns a float if a single ticker is provided, otherwise a PricesSeries mapping tickers to their last prices. #### Response Example ```json { "AAPL": 170.50, "GOOG": 2800.75 } ``` ``` -------------------------------- ### Check if Date is Beyond End Date Based on Frequency (Python) Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/abstract_price_data_provider Compares a start date with an end date, considering a given frequency. Returns True if the start date plus the frequency's time delta is after the end date (for daily frequency) or if the adjusted start date is greater than or equal to the end date (for other frequencies). Dependencies include datetime and Frequency. ```python def _got_single_date(start_date: datetime, end_date: datetime, frequency: Frequency): return (start_date + frequency.time_delta()).date() > end_date.date() if frequency <= Frequency.DAILY else \ (start_date + frequency.time_delta() >= end_date) ``` -------------------------------- ### Initialize BinanceDataProvider Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/binance_dp/binance_data_provider Initializes the BinanceDataProvider with parameters such as file path, tickers, date range, and data frequency. It checks for the Binance library installation and raises an error if the frequency is not supported (only 1m and daily are currently supported). ```python from qf_lib.data_providers.binance_data_provider import BinanceDataProvider from qf_lib.common.tickers.tickers import Ticker from qf_lib.common.enums.frequency import Frequency from datetime import datetime # Example usage: # Assuming you have a BinanceContractTickerMapper instance and desired parameters # data_provider = BinanceDataProvider(path="/path/to/data", # filename="binance_data.csv", # tickers=Ticker("BTC-USD"), # start_date=datetime(2023, 1, 1), # end_date=datetime(2023, 1, 31), # contract_ticker_mapper=your_mapper_instance, # frequency=Frequency.MIN_1) ``` -------------------------------- ### Create Target Percentage Orders Source: https://qf-lib.readthedocs.io/en/latest/tutorials/first_strategy_backtest Generates orders to achieve target portfolio percentages for specified tickers. It supports Market Orders with DAY time-in-force and handles fractional contracts for crypto. ```python self.order_factory.target_percent_orders({DummyTicker("AAA"): 0.75}, MarketOrder(), TimeInForce.DAY) ``` -------------------------------- ### Adjust Start Date for Data Frequency Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/abstract_price_data_provider Adjusts the provided start date to align with the specified data frequency. For intraday frequencies, it rounds up to the next frequency interval. For daily frequencies, it ensures the time is set to midnight. ```python def _adjust_start_date(self, start_date: datetime, frequency: Frequency): if frequency > Frequency.DAILY: frequency_delta = to_offset(frequency.to_pandas_freq()).delta.value new_start_date = Timestamp(math.ceil(Timestamp(start_date).value / frequency_delta) * frequency_delta) \ .to_pydatetime() if new_start_date != start_date: self.logger.info(f"Adjusting the starting date to {new_start_date} from {start_date}.") else: new_start_date = start_date + RelativeDelta(hour=0, minute=0, second=0, microsecond=0) if new_start_date.date() != start_date.date(): self.logger.info(f"Adjusting the starting date to {new_start_date} from {start_date}.") return new_start_date ``` -------------------------------- ### Initialize Bloomberg Data Provider with Settings Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/bloomberg/bloomberg_data_provider Initializes the BloombergDataProvider using provided settings and an optional timer. It sets up the connection parameters (host, port) and instantiates internal data provider components if the blpapi library is available. If blpapi is not installed, it warns the user and exits. ```python from qf_lib.data_providers.bloomberg.bloomberg_data_provider import BloombergDataProvider from qf_lib.settings import Settings settings = Settings() bloomberg_data_provider = BloombergDataProvider(settings) ``` -------------------------------- ### Validate and Retrieve Latest Available Prices Source: https://qf-lib.readthedocs.io/en/latest/_modules/qf_lib/data_providers/abstract_price_data_provider Calculates the latest valid open and close prices for a sequence of tickers starting from a given date. It handles cases where prices might be missing by defaulting to the start date or NaN. ```python @staticmethod def _get_valid_latest_available_prices(start_date: datetime, tickers: Sequence[Ticker], open_prices: QFDataFrame, close_prices: QFDataFrame) -> QFSeries: latest_available_prices = [] for ticker in tickers: last_valid_open_price_date = open_prices.loc[:, ticker].last_valid_index() or start_date last_valid_close_price_date = close_prices.loc[:, ticker].last_valid_index() or start_date try: if last_valid_open_price_date > last_valid_close_price_date: price = open_prices.loc[last_valid_open_price_date, ticker] else: price = close_prices.loc[last_valid_close_price_date, ticker] except KeyError: price = nan latest_available_prices.append(price) latest_available_prices_series = PricesSeries(data=latest_available_prices, index=tickers) return latest_available_prices_series ``` -------------------------------- ### Create Intraday Backtest Trading Session Source: https://qf-lib.readthedocs.io/en/latest/tutorials/first_strategy_backtest Sets up an intraday trading session for backtesting, specifying ticker, date range, and market open/close times. It utilizes demo settings and data providers for configuration. ```python def main(): ticker = DummyTicker("AAA") start_date = str_to_date("2019-07-01") end_date = str_to_date("2019-08-31") settings = get_demo_settings() pdf_exporter = PDFExporter(settings) excel_exporter = ExcelExporter(settings) session_builder = BacktestTradingSessionBuilder(settings, pdf_exporter, excel_exporter) session_builder.set_frequency(Frequency.MIN_1) session_builder.set_data_provider(intraday_data_provider) session_builder.set_market_open_and_close_time( {"hour": 0, "minute": 0}, {"hour": 23, "minute": 59}) ts = session_builder.build(start_date, end_date) ```