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.
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.
See also
Full method signatures in API Reference.
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.
See also
Full method signatures in API Reference.
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.
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)