.. _programmatic_usage: Running from Python =================== All functionality available through the Excel workflow is also accessible through Python. This lets you integrate backtests into larger scripts, notebooks, or automation pipelines. Single Backtest --------------- The ``main()`` function runs the full workflow: data loading, backtest execution, metrics, Excel report, and optional interactive dashboard. .. code-block:: python import kaxanuk.backtest_engine.backtest_engine from kaxanuk.backtest_engine.config_handlers import ExcelConfigurator from kaxanuk.backtest_engine.input_handlers.csv_input import CsvInput from kaxanuk.backtest_engine.input_handlers.csv_portfolio_input_handler import CsvPortfolioInputHandler from kaxanuk.backtest_engine.services.env_loader import load_config_env load_config_env() configurator = ExcelConfigurator(file_path="Config/backtest_engine_parameters.xlsx") configuration = configurator.get_configuration() market_data_handler = CsvInput(input_dir=configuration.input_market_data_directory) portfolio_handler = CsvPortfolioInputHandler(base_dir=configuration.input_portfolio_directory) result = kaxanuk.backtest_engine.backtest_engine.main( configuration=configuration, input_handlers=[market_data_handler], portfolio_handlers=[portfolio_handler], logger_level=configurator.get_logger_level(), launch_dashboard=True, ) if result.success: print("Final value:", result.data["final_total_portfolio_value"]) else: print("Error:", result.error) Parameter Sensitivity Analysis --------------------------------- Run multiple parameter combinations while loading market data only once. .. seealso:: Full method signatures in :ref:`api_reference`. .. code-block:: python import datetime from kaxanuk.backtest_engine.backtest import BacktestVariationRunner from kaxanuk.backtest_engine.config_handlers import ExcelConfigurator from kaxanuk.backtest_engine.data_processors.data_pipeline_executor import execute_data_pipeline from kaxanuk.backtest_engine.input_handlers.csv_input import CsvInput from kaxanuk.backtest_engine.input_handlers.csv_portfolio_input_handler import CsvPortfolioInputHandler from kaxanuk.backtest_engine.modules.comparative_report import generate_comparative_excel_report from kaxanuk.backtest_engine.backtest.orchestrators.backtest_results_summary import get_summary_dataframe from kaxanuk.backtest_engine.services.env_loader import load_config_env load_config_env() configurator = ExcelConfigurator(file_path="Config/backtest_engine_parameters.xlsx") configuration = configurator.get_configuration() pipeline_result = execute_data_pipeline( configuration=configuration, input_handlers=[CsvInput(input_dir=configuration.input_market_data_directory)], portfolio_handlers=[CsvPortfolioInputHandler(base_dir=configuration.input_portfolio_directory)], ) suite = BacktestVariationRunner(base_config=configuration, pipeline_result=pipeline_result) # Commission grid suite.add_commission_grid(commission_values=[0.0, 0.005, 0.01, 0.02, 0.05], name_prefix="commission") # Named variations suite.add_variation("baseline", commission_cents=0.01, cash_reserve_percentage=0.05) suite.add_variation("low_cost", commission_cents=0.005, cash_reserve_percentage=0.05) suite.add_variation("aggressive", commission_cents=0.005, cash_reserve_percentage=0.02) # Rolling windows suite.add_rolling_window_variations( start_date=datetime.date(2020, 1, 2), end_date=datetime.date(2024, 12, 31), window_months=12, step_months=6, name_prefix="rolling", ) results = suite.run_all() summary = get_summary_dataframe(results) print(summary[["name", "final_value", "sharpe_ratio", "annualized_return", "max_drawdown"]]) report_path = generate_comparative_excel_report( suite_results=results, output_directory=configuration.backtest_results_output_directory, report_name="sensitivity_analysis", ranking_metric="sharpe_ratio", ) Batch Testing — Multiple Portfolios -------------------------------------- Backtest several portfolios at once with optional per-portfolio parameter variations. .. seealso:: Full method signatures in :ref:`api_reference`. .. code-block:: python from kaxanuk.backtest_engine.backtest import MultiPortfolioBacktester from kaxanuk.backtest_engine.config_handlers import BatchConfigParser from kaxanuk.backtest_engine.input_handlers.csv_input import CsvInput from kaxanuk.backtest_engine.input_handlers.csv_portfolio_input_handler import CsvPortfolioInputHandler from kaxanuk.backtest_engine.backtest.orchestrators.backtest_results_summary import get_summary_dataframe from kaxanuk.backtest_engine.services.env_loader import load_config_env load_config_env() batch_config = BatchConfigParser.parse_dict({ "global_defaults": { "start_date": "2020-01-02", "end_date": "2024-12-31", "benchmark_file_name": "SPY", "commission_cents": 0.01, "cash_reserve_percentage": 0.05, "initial_capital": 100000, "market_data_input_format": "csv", "portfolio_input_format": "csv", "input_market_data_directory": "./Input/Data", "input_portfolio_directory": "./Input/Portfolios", "backtest_results_output_directory": "./Output/batch", "user_column_commission_price": "vwap", "user_column_trade_execution_price": "vwap_adjusted", "user_column_mark_to_market_price": "close_adjusted", "user_column_date": "date", }, "portfolios": [ { "name": "aapl_msft_60_40", "inline_weights": { "2020-01-02": {"AAPL": 0.60, "MSFT": 0.40}, "2022-01-03": {"AAPL": 0.55, "MSFT": 0.45}, }, }, { "name": "nvda_heavy", "inline_weights": { "2020-01-02": {"NVDA": 0.50, "AAPL": 0.30, "MSFT": 0.20}, }, "variations": [ {"name": "low_cost", "commission_cents": 0.005}, {"name": "high_cost", "commission_cents": 0.05}, ], }, ], "output": { "directory": "./Output/batch", "batch_name": "portfolio_comparison", "ranking_metric": "sharpe_ratio", }, }) backtester = MultiPortfolioBacktester( input_handlers=[CsvInput(input_dir="./Input/Data")], portfolio_handlers=[CsvPortfolioInputHandler(base_dir="./Input/Portfolios")], ) results = backtester.run(batch_config=batch_config) summary = get_summary_dataframe(results) print(summary[["name", "sharpe_ratio", "final_value"]]) backtester.generate_report(results, batch_config) backtester.generate_individual_reports(results, batch_config) Batch Testing — Directory Scan --------------------------------- Automatically discover and backtest all portfolio files in a directory. .. code-block:: python from kaxanuk.backtest_engine.backtest import MultiPortfolioBacktester from kaxanuk.backtest_engine.config_handlers import BatchConfigParser from kaxanuk.backtest_engine.input_handlers.csv_input import CsvInput from kaxanuk.backtest_engine.input_handlers.csv_portfolio_input_handler import CsvPortfolioInputHandler from kaxanuk.backtest_engine.services.env_loader import load_config_env load_config_env() batch_config = BatchConfigParser.parse_dict({ "global_defaults": { "start_date": "auto", "end_date": "auto", "benchmark_file_name": "SPY", "commission_cents": 0.01, "cash_reserve_percentage": 0.05, "initial_capital": 100000, "market_data_input_format": "csv", "portfolio_input_format": "csv", "input_market_data_directory": "./Input/Data", "input_portfolio_directory": "./Input/Portfolios", "backtest_results_output_directory": "./Output/batch_directory", "user_column_commission_price": "close_adjusted", "user_column_trade_execution_price": "close_adjusted", "user_column_mark_to_market_price": "close_adjusted", "user_column_date": "date", }, "portfolio_directory": "./Input/Portfolios", "output": { "directory": "./Output/batch_directory", "batch_name": "directory_scan", "ranking_metric": "sharpe_ratio", }, }) backtester = MultiPortfolioBacktester( input_handlers=[CsvInput(input_dir="./Input/Data")], portfolio_handlers=[CsvPortfolioInputHandler(base_dir="./Input/Portfolios")], ) results = backtester.run(batch_config) backtester.generate_report(results, batch_config)