Backtest a Value at Risk model against realized returns.

A Value at Risk estimate is only useful if it is actually well-calibrated against reality. This method builds a rolling, out-of-sample VaR path (each VaR estimate uses only the window_size returns preceding it, never the return it is compared against) and tests it with Kupiec’s Proportion of Failures test (is the overall breach rate consistent with alpha?) and/or Christoffersen’s independence test (are breaches spread out over time, or do they cluster together?).

For more information about the methods, see the following papers:

  • Kupiec, P.H. (1995). “Techniques for Verifying the Accuracy of Risk Measurement Models.” The Journal of Derivatives, 3(2), 73-84.
  • Christoffersen, P.F. (1998). “Evaluating Interval Forecasts.” International Economic Review, 39(4), 841-862.

Also known as: VaR validation, VaR backtest, POF test.

No programming experience? With the Finance Toolkit MCP server, AI assistants such as Claude and ChatGPT can calculate the Value at Risk Backtest for you. Just ask in plain English.

Calculate the Value at Risk Backtest in Python

The Value at Risk Backtest is available in the Risk module of the open-source Finance Toolkit. Install it with:

pip install financetoolkit -U

Then call get_var_backtest as shown below.

from financetoolkit import Toolkit

toolkit = Toolkit(["AMZN", "TSLA"], api_key="FINANCIAL_MODELING_PREP_KEY")

toolkit.risk.get_var_backtest(window_size=252)

Which returns:

  AMZN TSLA Benchmark
Kupiec Statistic 0.0817 1.6459 0.0018
P-Value 0.7749 0.1995 0.9662
Christoffersen Statistic 0.0631 0.4302 1.0847
P-Value 0.8017 0.512 0.2977

Parameters

get_var_backtest accepts the following parameters:

  • period (str, optional): The data frequency for returns (daily, weekly, quarterly, or yearly). Defaults to “daily”, since window_size is expressed in return observations of this frequency (252 only means “about one year” when period is daily).
  • distribution (str, optional): The distribution to use for the rolling VaR estimates, one of “historic”, “gaussian”, “studentt” or “evt”. Defaults to “historic”.
  • alpha (float, optional): The confidence level for the VaR estimates (e.g., 0.05 for 95% confidence). Defaults to 0.05.
  • window_size (int, optional): The rolling window size (in number of return observations) used to estimate each VaR value. Defaults to 252 (approximately one trading year of daily returns).
  • test (str, optional): Which test(s) to run, one of “kupiec”, “christoffersen” or “both”. Defaults to “both”.
  • rounding (int | None, optional): The number of decimals to round the results to. Defaults to None.

The Risk module page introduces the module, and the sidebar lists all of its functions.

Share