11. Backtester strategy backtesting engine

The Backtester class is used to backtest operator objects.

This class’s attributes include all parameters required for backtest calculations, as well as the result data generated during the backtest. These result data are stored as ndarrays and retained for the lifetime of the object, and can be refreshed repeatedly.

This class can only be instantiated after the operator object has been created, because the Backtester class depends on the operator object to generate trading signals and execute trades. Typical usage is as follows:

operator = Operator( ... )  # 创建Operator对象
backtested = Operator.backtest( signal_count=100, share_count=10, **kwargs)  # 创建Backtester对象
# get backtest raw results:
backtested.cash_investment_array
backtested.own_cashes
...
# get backtest results as DataFrame:
result_df = backtested.value_records()
trade_log_df = backtested.trade_logs()
trade_summary_df = backtested.trade_summary()
class qteasy.backtest.Backtester(op: Operator, shares: list[str], cash_plan: CashPlan, cash_investment_array: ndarray, cash_inflation_array: ndarray, delivery_day_indicators: ndarray, cost_params: ndarray, signal_parsing_params: dict, trading_moq_params: dict, trading_delivery_params: dict, trade_price_data: ndarray, benchmark_data: Optional[Union[DataFrame, Series]] = None, evaluate_price_data: Optional[DataFrame] = None, enable_tracing: bool = False, logger: Optional[Logger] = None)[source]

The Backtester class is used to backtest an operator object. This class’s attributes include all parameters required for backtest calculations, as well as the result data generated during the backtest. These result data are stored as ndarrays and retained for the lifetime of the object, and can be refreshed repeatedly.

This class can only be instantiated after the operator object has been created, because the Backtester class depends on the operator object to generate trading signals and execute trades. Typical usage is as follows:

operator = Operator( ... )  # 创建Operator对象
backtested = Operator.backtest( signal_count=100, share_count=10, **kwargs)  # 创建Backtester对象
# get backtest raw results:
backtested.cash_investment_array
backtested.own_cashes
...
# get backtest results as DataFrame:
result_df = backtested.value_records()
trade_log_df = backtested.trade_logs()
trade_summary_df = backtested.trade_summary()
op

A trading operation object that includes the logic for generating trading signals and executing trades

Type:

Operator

clear_backtest_buffers()[source]

Clear the cached backtest results data and reset the backtest results data to an empty array so that the backtest can be recalculated.

Return type:

None

evaluate_result(indicators: str) dict[source]

Generates an evaluation report of the trading results and saves it in the self.evaluate_result attribute

Parameters:

indicators (str) – Backtest result evaluation metrics; see the qteasy.evaluate.evaluate() function for details

generate_trade_logs(save_to_file_path: Optional[str] = None) DataFrame[source]

Generate a trading log based on the backtest results. The trading log is a complete trade record file that contains the following information for each trading period.

Each trading period contains 8 rows of data, as follows:

  • 0, trade signal: the current-period trading signal for each stock

  • 1, price: the current-period trading price for each stock

  • 2, traded amounts: the current-period traded quantity for each stock; 0 if there is no trade

  • 3, cash changed: the current-period cash change amount for each stock; negative for buys and positive for sells

  • 4, trade cost: the current-period trading cost for each stock

  • 5, own amounts: the end-of-period holdings quantity for each stock

  • 6, available amounts: the end-of-period available quantity for each stock

  • 7, summary: the position value of each stock for the current period, also including summary data (cash held at the end of the current period, available cash, total asset value)

The above information is saved in the form of a DataFrame. The row index is a MultiIndex: the first/second levels are the time/strategy group indices, and the third level is the 8 data categories above. The trade log file can be saved in CSV format with the filename trade_log.csv.

Parameters:

save_to_file_path (str, optional) – If a file path is provided, save the trade log as a CSV file; the default is None.

Returns:

trade_log – trade simulation result data

Return type:

pd.DataFrame

generate_trade_summary(share_names: Optional[list[str]] = None, save_to_file_path: Optional[str] = None) DataFrame[source]

Generate the trade summary table (a more compact trade summary table that contains the key information for each trade, presented in a more human-readable way, and filters out records with no trades). The function input trade_log_df is the return value of the function generate_trade_logs().

Parameters:
  • share_names (list[str], optional) – List of trading instrument names; if None, use “N/A” as the name.

  • save_to_file_path (str, optional) – If a file path is provided, save the trade summary table as a CSV file; the default is None (do not save a file).

plot_result(plot_title: str, show_positions: bool, buy_sell_markers: bool) None[source]

Generate trading results in chart form

Parameters:
  • plot_title (str) – The chart title

  • show_positions (bool) – Whether to display position interval information. If set to True, show the position type for each interval on the return curve chart as red/green bands (green indicates holding a long position, red indicates holding a short position). The darker the color, the higher the position ratio.

  • buy_sell_markers (bool) – Whether to show buy/sell points on the return curve chart. If set to True, buy/sell points are marked on the return curve chart with small red/green arrows

Return type:

None

report_result(trade_log: Optional[str] = None, trade_summary: Optional[str] = None) str[source]

Generate a detailed report of the backtest results. The report is in plain-text format and can be printed using the print command

Parameters:
  • trade_log (str, optional) – Storage path for the trade log file. The default is None. If this path is provided, the storage path of the trade log is printed in the report

  • trade_summary (str, optional) – Storage path for the trade summary record file. The default is None. If provided, print the storage path of the trade summary record in the report.

Returns:

report_str – Backtest results report formatted for printing

Return type:

str

run() Backtester[source]

Run the backtest calculations, generate the backtest result data, and store it in the object’s attributes

save_complete_values(save_to_file_path: Optional[str] = None) Optional[str][source]

Save complete_values as a CSV file (called by qt_operator when trade_log=True)

Parameters:

save_to_file_path (str, optional) – Save path; if None, nothing is written

Returns:

Return the save path on success; otherwise return None

Return type:

str or None

trace_result_df() Optional[DataFrame][source]

Generate a record of the trading process based on the backtest results; the output is in DataFrame format

Alignment between trace rows and op_signal_index is ensured by the Operator when writing (update_trace_step uses the global signal row number). Here we only concat by strategy and then set the index to op_signal_index.

Returns:

trade_trace – trade simulation process data

Return type:

pd.DataFrame

trade_result_df() DataFrame[source]

Generate asset value records based on the backtest results; the output is in DataFrame format.

Returns:

value_history – trade simulation result data

Return type:

pd.DataFrame

trade_result_final_value()[source]

Directly and quickly compute and return the final value result of the backtest.

trade_result_max_drawdown()[source]

Directly and quickly compute and return the maximum drawdown result of the backtest.

trade_result_volatility()[source]

Directly and quickly compute and return the volatility result of the backtest.