Horizon is an important parameter in our simulations. As a reminder, we are simulating the behavior of each security via their underlying risk factors. A detailed description of the steps can be found in the white paper, but this short article is concerned with Step 6 and describes how certain parameters from the API can influence results when performing stress tests.
Specifically, how to control the behavior of the horizon timeframe of interest. Remember that we are collecting risk factors that possess invariant properties in a matrix: these can be non-overlapping returns (differences of the logarithms of closing prices) for lognormal risk factors or differences for normal ones. These differences are computed with a sampling rate %% \small \widetilde \tau_{1}%% that can be daily (%% \small\widetilde \tau_{1}=1 %%), weekly (%% \small\widetilde \tau_{1}=5 %%) and so forth.
The problem at hand is how to take the sampled risk factors above and generate simulations at a prescribed horizon %% \small \widetilde \tau_{2}%% that is a multiple of %% \small \widetilde \tau_{1}%%.
Because all risk factors are calculated by differences, they have the desirable property of additivity. Simulations at a horizon of 20 days can be obtained from 5-day interval risk factors, simply by sampling from:
$$ \small \overline{sims} = \N(\mu * \frac{\widetilde \tau_{2}}{\widetilde \tau_{1}},\Sigma^{*} *\frac{\widetilde \tau_{2}}{\widetilde \tau_{1}}) $$
and
$$ \small \frac{\widetilde \tau_{2}}{\widetilde \tau_{1}} = \frac{20}{5} = 4$$
Naturally if the horizon is not sufficiently far away, our simulated risk factors (and security PLs via pricing formulas) will have a limited range of outcomes. For example, the SP500 range of outcomes if %% \small \widetilde \tau_{1} = \small \widetilde \tau_{2} = 5 %% might be from -3.92% and 4.1%. Any requested shock outside this range would need to be extrapolated somehow from the range (we dislike extrapolations). Another solution would be to "force" the SP500 distribution to be centered at the large magnitude shock, but that would be detrimental to the transitivity properties of our engine and would affect only securities that rely directly on that risk factor (we still allow you to do that).
When our calculation engine needs to perform a stress test that is too large in magnitude for the horizon considered, there could be an unfeasible solution when posteriors are calculated (see chapter 10 of the white paper). That arises from the fact that there is no feasible probability set that generates the expected index shock because all simulated moves are smaller in magnitude. Stated differently, the shock magnitude is outside the range of simulated index moves. Therefore we need to make sure that the horizon and requested shock are compatible.
Let's make it more explicit. Assume that a 40% shock in the SP500 is being requested and that horizon=5 is being passed explicitly. It turns out that even during the GFC the SP500 never dropped that much in a week. In fact, our calculation engine might compute -3.92% and 4.1% as a feasible weekly range. Thus, we need to gradually expand the horizon so that we can make large observations within the 40% order of magnitude in the illustrative example.
Essentially our engine quickly cycles over various horizons before calculating the stress tests to make sure we will be able to observe large enough moves in the exogenous index:
$$ \small \widetilde \tau_{2}=\left[ 5, 10, \cdots , 720 \right] $$
In order to force our calculation engine to proceed with the covariance scaling above you will need to pass horizon as %%null%%. Explicit horizons provided to the API will not trigger the procedure above and will generate extrapolated results for large shocks.
The table below summarizes the various outcomes, depending on horizon parameter:
horizon | Shock observable in the Horizon? (*) | Scales Covariance | Calculates implied Horizon | Extrapolates |
%%null%% | N/A | Yes | Yes | No (**) |
Explicit: 5,10,.... | No | No | No | Yes |
Explicit: 5,10,.... | Yes | No | No | No |
(*) Is the shock inside the dynamic range calculated for the horizon?
(**) technically it might extrapolate beyond 720 days if shock magnitude still outside the dynamic range
The API will return information on the stress test solution as follows:
implied_horizon | Returns the implied horizon in days to generate a range of extreme moves in the exogenous index that contain the required shock. |
dynamic_range | This key returns the range of possible simulated returns for exogenous index at implied_horizon |
extrapolated | This key returns True/False depending if dynamic_range contains the shock being asked or not |
Example 1: horizon = %%null%%
A portfolio with 1 AAPL stock and an SP500 stress test of -20%, might have the following keys in the returning json, when horizon is passed as %%null%%:
"dynamic_range": [-0.212278541512608, 0.269172063587031],
"extrapolated": false,
"implied_horizon": 180,
Thus, our calculation engine computes an implied horizon of 6 months to produce a range of SP500 outcomes from -21.22% to 26.92% that would enable the -20% shock to be properly computed via the posterior weighting. Every other endogenous and exogenous securities would be properly priced with that posterior, preserving the transitive nature of the calculations.
Example 2: Conversely, if horizon is explicitly passed as 5, the same parameters would be:
"dynamic_range": [-0.039275218669937,0.041190087866523],
"extrapolated": true,
"implied_horizon": 5,
Meaning that SP500 simulations are kept at the 5-day horizon (implied_horizon = horizon) and are within -3.92% and 4.1%.
The expected PL for Apple in examples 1 and 2, -19.79% and -19.92% respectively, are sufficiently close. Having said that, the extrapolated solution should be avoided for portfolios with non-linear securities like options.