Monte Carlo simulation is a technique that relies on random sampling to compute meaningful predictions. It is especially useful when studying systems with significant uncertainty or risk. Although statistical models often exist for modeling processes in a general way, Monte Carlo simulation provides an opportunity to examine experimental values and to study the range and tendencies of outcomes. It is also readily adaptable to extremely specific scenarios, including those in which multiple variables or processes may depend on or be influenced by each other.
Although there is not a single preferred technique for creating a Monte Carlo simulation, approaches to this task usually involve a range of inputs, randomly selected from a population/distribution with known characteristics (mean, standard deviation, skewness, etc.) After sampling the distribution for values, the simulator performs a deterministic calculation to determine an outcome based on the set of inputs specific to that iteration. Monte Carlo simulations derive their main credibility from the analyst's ability to run the same simulation hundreds or thousands of times to generate a pool of outcomes from which statistically significant conclusions can be drawn.
Using the code
The included code consists of a
Simulation class and a form which demonstrates the use of that class to solve a specific problem. Clearly, the class could be adapted or used as is to investigate other simulation scenarios. In this case, however, I have modeled outcomes useful to someone trying to decide if they have enough money to retire. Simply, the user specifies an initial investment (their savings), an expected rate of return at which those savings are invested, the historic or expected standard deviation of the investment, and an annual withdrawal rate (say, $35,000).
The example would be more accurate if it took into account other factors, for example, a variable rate of inflation. Additionally, it would be straightforward to expand the example to model multiple investments, each with its own expected rate of return and risk. The results table could sum the expected outcomes of each investment's performance and produce a combined forecasted value. However, for the sake of simplicity, I have chosen to keep the demonstration form simple and easily understood.
When inputs are entered and a request to calculate is made, a table is constructed which contains the outcome of each simulation trial (default, 2000 trials). Similarly, a table is built and displayed which contains some informational statistics which summarize the outcomes. This displays the relative year number, the account balance, and the likelihood that the investor has reached the end of their savings in a particular year. The experimental data is ripe for additional analysis, and could be expanded to include confidence intervals, or to answer slightly different but related questions.
The simulation class itself is constructed with parameters which describe the distribution to be sampled. Here, we assume the normal distribution, and describe it with a mean, mu, and a standard deviation, sigma. Clearly, other distributions may be more appropriate for specific modeling problems, for instance, a lognormal distribution or a binomial distribution. The instanced class exposes a method,
GetSimulatedValue(), which returns a single random sample value from a pool matching the specified distribution's characteristics.
The class can be instanced and the sampling method called, like so:
Simulation simulator = new Simulation(mu, sigma);
for (Int32 instance = 0; instance < 2000; instance++)
Double simValue = simulator.GetNextSimValue();
This code has not been thoroughly tested and may contain bugs. It is intended to be instructive about simulation techniques, and should not be relied upon for actual data to be used in decision-making. It has not been optimized for performance or efficiency, and the code as it is written is not particularly elegant or flexible. My goal was to make it as easy to read and understand as possible, so that others can create their own functions which implement the concepts described. That said, I do welcome constructive feedback if you see a bug or some glaring omission, or perhaps you feel I could have explained something more clearly.