Monte Carlo simulations (or methods) is the technique of applying randomness and the Law of large numbers to the solution of various scientific and engineering problems. One of its first documented uses was by Stanislaw Ulam and John von Neumann for nuclear weapon simulations after WWII [1].蒙特卡洛模拟(或蒙特卡洛方法)是一种将随机性与大数定律应用于解决各种科学和工程问题的技术。二战后,斯坦尼斯拉夫·乌拉姆(Stanislaw Ulam)和约翰·冯·诺依曼(John von Neumann)在核武器模拟中首次记录并使用了该方法 [1]。
In this post I want to provide examples of some simple uses of Monte Carlo simulations. We'll start with the classical example of calculating the value of by throwing darts.在这篇文章中,我想提供一些蒙特卡洛模拟的简单应用示例。我们将从计算圆周率 π 的经典示例开始,即投掷飞镖。
Estimating pi估算圆周率
Suppose we take a square board and inscribe a quarter of a circle into it. We then proceed to throw darts at the board and record whether each dart hits inside or outside the quarter circle. Having thrown many such darts, we calculate the ratio of the darts inside the circle to the total number thrown.假设我们取一块正方形木板,并在其中内切一个四分之一圆。然后我们开始向木板投掷飞镖,并记录每一支飞镖是落在四分之一圆之内还是之外。在投掷了大量飞镖后,我们计算落在圆内的飞镖数量与投掷总数的比值。
Assuming our darts are distributed uniformly over the square, by the Law of large numbers this ratio should approach the ratio of areas of the quarter circle to the full square .假设我们的飞镖在正方形上均匀分布,根据大数定律,该比值应趋近于四分之一圆面积 A_{circ} 与整个正方形面积 A_{square} 的比值。
With a square side length of 1, we have:设正方形边长为 1,我们有:
Therefore:因此:
Here's a visualization:以下是可视化演示:
π ≈ 3.2600 π ≈ 3.2600
Change the number of samples (dart throws) and click "Run" to regenerate. The code is very simple - here's a slightly sanitized version:更改样本数量(投掷飞镖次数)并点击“运行”以重新生成。代码非常简单——这是一个稍微精简过的版本:
const total = Number(samples.value);
let inside = 0;
for (let i = 0; i < total; i++) {
const x = Math.random();
const y = Math.random();
const inCircle = x * x + y * y <= 1;
if (inCircle) inside++;
}
estimateValue = 4 * inside / total;
You'll notice that the estimate is relatively poor - even with 1000 samples - if you click "Run" several times, some numbers will be way off mark. While this method does estimate , it's not a particularly good estimate. I find that running ~10 billion samples is necessary to estimate it to 4 digits after the decimal with reasonable reliability.你会注意到,即使有 1000 个样本,估算效果也相对较差——如果你点击多次“运行”,有些数字会偏差很大。虽然这种方法确实可以估算 π,但它并不是一个特别好的估算值。我发现需要运行约 100 亿次样本,才能以合理的可靠性将结果估算到小数点后 4 位。
In general, for independent trials like these, the typical sampling error decreases in proportion to , where N is the number of trials. This means that halving the error requires four times as many samples.通常情况下,对于这类独立试验,典型的抽样误差会随着 1/\sqrt{N} 的比例减小,其中 N 是试验次数。这意味着要将误差减半,需要四倍的样本量。
While the estimation may seem whimsical, it's an example of an important class of problems to which Monte Carlo simulation is applied: numerical integration. Our simulation estimates the area under the quarter-circle curve, which is a definite integral.虽然 π 的估算看起来有些异想天开,但它是蒙特卡洛模拟所应用的一类重要问题——数值积分——的一个例子。我们的模拟估算的是四分之一圆曲线下的面积,这正是一个定积分。
Many integrals are very difficult to solve analytically, and much research has been done in the area of numerical analysis to develop methods to calculate integrals. Monte Carlo methods are particularly useful for high-dimensional integrals, where other numerical methods can become prohibitively expensive.许多积分很难通过解析法求解,数值分析领域已经进行了大量研究来开发计算积分的方法。蒙特卡洛方法对于高维积分特别有用,因为其他数值方法在高维情况下可能会变得极其昂贵。
Combinatorial simulation - the game of SET组合模拟——SET 游戏
A common use of Monte Carlo methods is estimating complex combinatorial calculations. These often don't have analytical solutions, and enumerating all options is intractable due to the scale of the numbers involved. As an example, let's consider the game of SET. Each SET card has four attributes:蒙特卡洛方法的常见用途是估算复杂的组合计算。这些计算通常没有解析解,而且由于涉及的数字规模巨大,穷举所有选项是行不通的。以 SET 游戏为例,每张 SET 卡片有四个属性:
- Number of shapes (1, 2 or 3)形状数量(1、2 或 3)
- Color (Red, Green or Purple)颜色(红色、绿色或紫色)
- Shape type (Oval, Diamond or Squiggle)形状类型(椭圆、菱形或波浪形)
- Shading (Empty, Striped or Solid)阴影(空心、条纹或实心)
And the goal is to find a "set" - three cards that are either all different or all the same for each attribute separately. As an example, here's a hand with a single set; see if you can find it [2]:游戏目标是找到一个“set”(集合)——即三张卡片,在每个属性上要么全部不同,要么全部相同。例如,这里有一手包含一个集合的牌,看看你能不能找到它 [2]:
And the next hand doesn't have any sets:而下一手牌中没有任何集合:
Here's a question: given a freshly shuffled SET deck, what are the odds that the first 12 cards drawn will have no sets among them? This question is difficult to answer without using a computer.这里有个问题:假设一副刚洗好的 SET 牌,抽出的前 12 张牌中没有集合的几率是多少?如果不使用计算机,这个问题很难回答。
It's easy to calculate the number of ways to deal a 12-card hand from a deck of 81:计算从 81 张牌中发出一手 12 张牌的方法数很容易:
But how many of these hands have no sets? Enumerating 70 trillion SET hands and checking each one can take quite a while, and there is no straightforward counting formula to answer this question. Some clever methods can be employed to leverage symmetries and other mathematical properties of SET to cut down this search space considerably. Donald Knuth himself worked on this problem and came up with a neat program (setset-all on his programs page) that found 2,284,535,476,080 such hands. Therefore, the answer to our question is:但是,这些牌中有多少是不包含集合的呢?枚举 70 万亿手 SET 牌并逐一检查可能需要很长时间,而且没有直接的计数公式来回答这个问题。可以采用一些巧妙的方法,利用 SET 的对称性和其他数学性质来大幅缩小搜索空间。唐纳德·克努特(Donald Knuth)本人也研究过这个问题,并写出了一个简洁的程序(在他程序页面的 setset-all),得出了 2,284,535,476,080 手这样的牌。因此,我们问题的答案是:
There's a 3.23% chance that a randomly drawn hand of 12 cards from a full deck of SET will have no set in it.从一副完整的 SET 牌中随机抽取 12 张牌,其中不包含集合的几率为 3.23%。
Let's see how we can use a Monte Carlo simulation to answer this question with relatively small effort, without deep knowledge of the mathematical properties of SET that enable cutting down the search space Knuth-style. We can use the following pseudo-code:让我们看看如何使用蒙特卡洛模拟以相对较小的工作量来回答这个问题,而无需深入了解那些能够像克努特那样缩小搜索空间的数学性质。我们可以使用以下伪代码:
C = 0
run N times:
draw a random 12-card hand from a fresh deck
count sets in the hand
if no sets:
C += 1
Estimated probability = C / N
After running 10 million simulated draws, I got an answer of 0.0323, which matches the real answer very closely.在运行了 1000 万次模拟抽牌后,我得到的答案是 0.0323,这与真实答案非常吻合。
The Monte Carlo approach lets us solve rather complicated problems in a very simple way. Suppose we want to answer the same question for a hand of 15 cards; this would blow up the search space considerably - there are about 100x more ways to select 15-card hands than there are to select 12-card hands. But for a Monte Carlo simulation, we adjust one small parameter and get a very reliable [3] answer (about 0.00037, in case you were wondering).蒙特卡洛方法让我们能够以非常简单的方式解决相当复杂的问题。假设我们想回答 15 张牌的问题;这会极大地扩大搜索空间——选择 15 张牌的方法比选择 12 张牌的方法多出约 100 倍。但对于蒙特卡洛模拟,我们只需调整一个小参数,就能得到一个非常可靠 [3] 的答案(顺便提一下,大约是 0.00037)。
Retirement projection退休规划
One domain where Monte Carlo simulations are ubiquitous is projections for retirement portfolios. Suppose someone prepares to retire with a total sum of 1 million dollars in their portfolio; they'd like to be able to draw $30,000 a year from the portfolio for their living expenses. Would that work?蒙特卡洛模拟在退休投资组合预测领域应用非常广泛。假设某人准备退休,其投资组合总额为 100 万美元;他们希望每年能从投资组合中提取 3 万美元用于生活开支。这可行吗?
There's a large number of factors to take into account when analyzing this question, but for simplicity let's focus on just two: portfolio return and inflation. We can run a naive estimate, assuming average values: suppose an average yearly portfolio return of 4%, and average yearly inflation of 2% [4]在分析这个问题时需要考虑许多因素,但为简单起见,我们仅关注两个:投资组合回报率和通货膨胀。我们可以进行一次简单的估算,假设平均值:假设投资组合的年平均回报率为 4%,年平均通货膨胀率为 2% [4]。
Let's denote our portfolio return as , and inflation as . Then the real return each year is:设投资组合回报率为 r=0.04,通货膨胀率为 q=0.02。那么每年的实际回报率为:
Starting with $1,000,000, at the end of the year we'll have $1,019,600 and then draw $30,000 for living expenses [5], ending with $989,600. If we continue this way, the money runs out after ~55 years, which means that a person retiring at the age of 65 should be reasonably safe, right?以 100 万美元开始,年末我们将拥有 1,019,600 美元,然后提取 3 万美元作为生活费 [5],最终剩下 989,600 美元。如果我们继续这样下去,资金会在约 55 年后耗尽,这意味着一个 65 岁退休的人应该相当安全,对吧?
But this is very simplistic; assuming just average returns is risky, because they do a poor job of representing reality, and many factors have uncertainty. For example, the sequence of returns matters a lot; a bad year (-10%) followed by a great year (+18%) would still count as "4% on average" but produces significantly less money than two consecutive +4% years. Inflation is also unpredictable, and sometimes correlated with portfolio returns; there could be bad years of high inflation and low / volatile returns that can wreak havoc on a portfolio.但这太简单化了;仅假设平均回报率是有风险的,因为它们无法很好地代表现实,而且许多因素都存在不确定性。例如,回报的顺序非常重要;糟糕的一年(-10%)紧接着极好的一年(+18%)虽然“平均回报率为 4%”,但产生的资金远少于连续两年 4% 的增长。通货膨胀也是不可预测的,有时还与投资组合的回报相关;可能会出现高通胀和低回报/高波动性的糟糕年份,这会对投资组合造成严重破坏。
As we add factors (variance in yearly draws, mixed portfolios of stocks, bonds, real estate, life expectancy, unexpected events, changing tax laws etc.), relying on a single average estimate becomes increasingly more fraught. This is why Monte Carlo simulations are very popular in this domain: by drawing from reasonable distributions based on historical data, a Monte Carlo simulation can easily run a million different scenarios and provide estimates: for example, what are the odds of money running out before death.随着我们增加因素(年度提取额的方差、股票、债券、房地产的混合投资组合、预期寿命、意外事件、税法变更等),依赖单一的平均估算变得越来越不可靠。这就是蒙特卡洛模拟在该领域非常受欢迎的原因:通过从基于历史数据的合理分布中进行抽样,蒙特卡洛模拟可以轻松运行一百万种不同的场景并提供估算:例如,资金在去世前耗尽的几率是多少。
Here's a useful chart from a simulation I ran:这是我运行的一次模拟中得出的有用图表:
In the top chart:在顶部图表中:
- The dashed line shows the constant assumptions mentioned before: what happens when yearly return is always 4% and inflation is always 2%.虚线显示了前面提到的恒定假设:当每年回报率始终为 4% 且通胀率始终为 2% 时会发生什么。
- The shaded blue areas demonstrate the outcomes of 1,000,000 simulations where inflation and return numbers are drawn from reasonable normal distributions based on historical data. We see that in 25% of the cases, all money ran out by roughly 22 years.蓝色阴影区域展示了 100 万次模拟的结果,其中通胀和回报数字是根据历史数据从合理的正态分布中抽取的。我们看到,在 25% 的情况下,所有资金在大约 22 年内就耗尽了。
In the bottom chart:在底部图表中:
- It's even easier to see how long the funds last; if we're interested in knowing, say, what are the odds that this plan will have enough money for 30 years - the chart shows it's about 60% (since in 40% of the simulations the funds were depleted at this point).资金能维持多久一目了然;如果我们想知道,例如,该计划有足够资金维持 30 年的几率是多少——图表显示大约是 60%(因为在 40% 的模拟中,资金此时已耗尽)。
Looking a this simulation, under the current assumptions the plan sounds much riskier than the average assumption makes it appear. Assuming that a 65-y.o. person would plan for 25 years of retirement until death, the ~30% odds of not having sufficient funds for this duration of time are sobering. Perhaps a change in plans is needed (such as a more frugal lifestyle or securing additional funds in some way).观察这个模拟,在当前的假设下,该计划听起来比平均估算所显示的要危险得多。假设一位 65 岁的人计划退休后生活 25 年直至去世,那么有约 30% 的几率无法维持这段时间的资金,这令人清醒。也许需要改变计划(例如更节俭的生活方式,或以某种方式获取额外资金)。
Retirement projection is only one of may ways in which Monte Carlo simulations are used for financial and economical applications; given the high uncertainty of these domains, it's very difficult to plan using analytical calculations. Company sales projections, growth projections, stock offering prices and much more uses Monte Carlo simulations to arrive at estimates with reasonable error bars.退休预测只是蒙特卡洛模拟在金融和经济应用中的众多用途之一;鉴于这些领域的高度不确定性,仅使用解析计算进行规划非常困难。公司销售预测、增长预测、股票发行价格等都在使用蒙特卡洛模拟来得出具有合理误差范围的估算。
Code代码
All the code for the explorations in this post is available on GitHub.本文中所有探索性研究的代码都可以在 GitHub 上找到。
| [1] | While these techniques were conceptually understood much earlier, it's not surprising that their first real applications coincided with the development of the first digital computers. As we'll see later in the post, Monte Carlo simulations benefit from running large numbers of trials to get reasonable accuracy. |
| [2] | The answer is: three empty red diamonds, three solid purple ovals, three striped green squiggles. Note that for each of the 4 SET attributes, these three cards are either all the same or all different. |
| [3] | For the same number of trials, this estimate has greater relative uncertainty than the 12-card estimate, because we encounter far fewer hands without a set. |
| [4] | For the examples in this post, we'll be using real dollars, or today's value of the money. We'll assume that the $30,000 yearly draw doesn't change and will instead apply inflation to the portfolio itself. |
| [5] | More sophisticated simulations would let us control these parameters; for example, are the expense funds drawn at the beginning or end of each year, or distributed on a monthly basis? |