一个场景是所有风险因子的表现序列。历史场景是指风险因子在历史上某天的实际表现,随机场景则是计算机随机模拟生成的。通常蒙特卡洛模拟法需生成至少 1000 个随机场景,然后计算组合在每个场景下的损益,最后取 5%分位点得到组合的 VaR 值。
由于蒙特卡洛法所需要的随机场景较多,场景的生成速度非常重要。下面介绍标准计算模型、技术改进和一些更进一步的技术改进方向。
注:下面只讨论如何生成「一个」随机场景。要生成多个,简单重复即可。
1、标准模型
前面已经提到过一种随机场景生成方法:假设风险矩阵 $ \Sigma$ 为 $ N\times N$ 的半正定矩阵,其中$ N$ 为风险因子的个数。它可分解为$ \Sigma=C'C$ ,那么可以生成因子场景为:
其中$ z$ 为随机数的向量,为独立的正态分布。
这是标准的场景生成模型。但如果严格按照尚需步骤走会有以下问题:
- 需要生成中间的风险矩阵,如果风险因子$ n$ 较大,保存和计算这个风险矩阵所需要计算和内存资源较大。
- 计算$ \Sigma=C'C$ 的分解比较费时。
- 上述计算是不稳定的,这体现在两个方面:
- 当增加一个新的风险因子(持仓),上述分解需要全部重算,效率较低;
- 当增加一个新的风险因子(持仓)时,即使使用同样的随机数,上面的计算结果将截然不同,比如同一个持仓在不同组合里面计算的 VaR 将不一样。
2、技术改进
模型仍然是上面那个模型,但关键支持在于$ C$ 的生成算法。若$ \Sigma$ 是任意的半正定矩阵,我们别无它法。但需要注意这里的$ \Sigma$ 比较特殊。
假设$ n$ 个风险因子过去$ T$ 天的的收益率组成一个$ T\times N$ 的矩阵$ D$ ,其中$ T$ 为计算 VaR 的样本长度。那么有
亦即$ \frac{D}{\sqrt{T}}$ 就是上面我们所需要的一个$ C$ 。我们只需要生成满足正态分布的$ T\times 1$ 的随机数向量$ z$ ,然后$ \frac{D'z}{\sqrt{T}}$ 就是我们需要的一个场景。
这中间不需要计算风险矩阵,也不需要做半正定矩阵的分解。计算的时间复杂性从$ N^3$ 下降到$ NT$ ,空间复杂性从$ N^2$ 下降到$ NT$ ,均有数量级上的下降。比如如果风险因子数量超过 1 万,在一年的样本下,计算速度将加快 40 万倍,内存使用量少 40 倍。
抛开上面的数学,场景$ \frac{D'z}{\sqrt{T}}$ 有更直观的解释,它事实上是风险因子的历史场景的随机组合。这么理解蒙特卡洛方法,是不是简单多了?
要保存这种随机组合很简单,每个场景只需要保存$ T$ 个随机数,而且它跟风险因子的个数完全无关,这也彻底解决了上面提到的计算不稳定的情况。
当然,这种角度也有局限性。那就是无法直接对风险矩阵(也就是相关性)进行任何调整。
3、更进一步的改进方向
为了更进一步地提升效率,以及提高蒙特卡洛模拟法在不同样本期间计算的稳定性,有更进一步的改进或简化。
首先,为了提高在不同样本期间计算的稳定性,我们在最开始就生成足够长的随机字符串。第一天计算使用前$ T$ 个随机数,第二天使用从第二个随机数开始的$ T$ 个随机数,依次类推。这样计算第一天 VaR 使用的场景和计算第二天 VaR 使用的场景中有部分随机因素是重叠的,这可以大大降低由于场景变动较大带来的蒙特卡洛 VaR 不稳定的现象。
其次,我们还可以做更进一步地简化,比如随机场景不是过去样本期间所有场景的随机组合,而是其中某两个场景的组合,这样计算复杂性可进一步降低;同时,当计算第二天的 VaR 时,并不更换全部的随机场景,而是只用最新的行情数据更新少数几个场景,这样也可以降低场景生成成本。
Q. E. D.