Pricing an Asian Option using multithreaded Java

By | February 28, 2011

So I’ve been busy lately and haven’t had the time to write any new blog posts, but I can’t let all of February go past without posting anything. So I might as well write a post related to what I’m currently working on. And that would be pricing an Asian Option.

But in stead of just posting some of the MATLAB code we’re currently working on, I thought I’d do it in Java. Why Java? Well, two reasons:

  1. It’s way faster than MATLAB
  2. Since we’re all getting more and more cores in our computers I might as well do it multithreaded

Although there are faster ways of doing this than using Monte Carlo simulations, that’s what I’ve gone for. Had I gone for a stochastic calculus solution it would be sort of pointless doing a multithreaded implementation, right?

I don’t guarantee any of the results, as I might have easily screwed up some of the formulas (I’m still learning this stuff..)

So without further ado, here’s the code:

  1. package asianoption;
  2.  
  3. import java.text.DecimalFormat;
  4. import java.util.Random;
  5. import java.util.concurrent.ConcurrentHashMap;
  6. import java.util.concurrent.ConcurrentMap;
  7. import java.util.concurrent.CountDownLatch;
  8.  
  9. /**
  10.  * @author Christian Felde (cfelde AT cfelde DOT com)
  11.  *
  12.  * Copyrighted me, no guaranties given..
  13.  */
  14. public class PriceAsianOption implements Runnable {
  15. private final CountDownLatch latch;
  16. private final ConcurrentMap<String, Double> results;
  17. private final double T, r, vol, dt, S0, K;
  18. private final int sims, threads;
  19.  
  20. public static void main(String... args) throws InterruptedException {
  21. double T = 1.0; // 1 year terminal time
  22. double r = 0.02; // 2% annual risk free rate
  23. double vol = 0.4; // 40% annual volatility
  24. double dt = 1.0/250.0; // Time step of one day (given 250 trading days)
  25. double S0 = 100.0; // Initial stock price
  26. double K = 100.0; // Option strike price
  27.  
  28. // Define number of concurrent simulations
  29. // and number of simulation pr thread.
  30. int threadCount = Runtime.getRuntime().availableProcessors();
  31. int simsPrThread = 100000;
  32.  
  33. System.out.print("Running " + threadCount + " threads ");
  34. System.out.println("with " + simsPrThread + " sims in each thread..");
  35.  
  36. DecimalFormat formatter = new DecimalFormat("#.######");
  37. PriceAsianOption pao = new PriceAsianOption(T, r, vol, dt,
  38. S0, K, threadCount, simsPrThread);
  39. System.out.println("Option price: "
  40. + formatter.format(pao.getPrice()));
  41. }
  42.  
  43. public PriceAsianOption(double T, double r, double vol, double dt,
  44. double S0, double K, int threadCount, int simsPrThread) {
  45. results = new ConcurrentHashMap<String, Double>();
  46.  
  47. // Set up latch
  48. latch = new CountDownLatch(threadCount);
  49. this.threads = threadCount;
  50.  
  51. // Global read vars
  52. this.T = T;
  53. this.r = r;
  54. this.vol = vol;
  55. this.dt = dt;
  56. this.S0 = S0;
  57. this.K = K;
  58. this.sims = simsPrThread;
  59. }
  60.  
  61. /**
  62.   * Calculate the price of an asian option using
  63.   * multi threaded Monte Carlo simulations
  64.   *
  65.   * @return Asian option price
  66.   */
  67. public double getPrice() throws InterruptedException {
  68. long start = System.currentTimeMillis();
  69. for (int i = 0; i < threads; i++) {
  70. new Thread(this).start();
  71. }
  72.  
  73. latch.await();
  74. long end = System.currentTimeMillis();
  75.  
  76. System.out.println("Run time in millis: " + (end-start));
  77.  
  78. DecimalFormat formatter = new DecimalFormat("#.######");
  79. double result = 0.0;
  80. for (String name : results.keySet()) {
  81. System.out.println(name + ": "
  82. + formatter.format(results.get(name)));
  83. result += results.get(name);
  84. }
  85.  
  86. return result/threads;
  87. }
  88.  
  89. /**
  90.   * This is where we run the monte carlo sims..
  91.   */
  92. public void run() {
  93. Random random = new Random();
  94.  
  95. // For the purpose of being efficient, let's define our constants
  96. // outside the main loop
  97. double a = (r - (0.5*Math.pow(vol, 2)))*dt;
  98. double b = vol*Math.sqrt(dt);
  99.  
  100. double result = 0.0;
  101. for (int i = 0; i < sims; i++) {
  102. double avgPrice = 0.0;
  103. int steps = 0;
  104. double lastPrice = S0;
  105. for (double t = dt; t <= T; t += dt) {
  106. // This is our Geometric Brownian motion..
  107. lastPrice = lastPrice*Math.exp(a
  108. + (b*random.nextGaussian()));
  109. avgPrice += lastPrice;
  110. steps++;
  111. }
  112. avgPrice = avgPrice/steps; // This is the average stock price
  113. result += Math.max(0, avgPrice-K);
  114. }
  115. result = result/sims; // This is the mean forward option price
  116. result = result*Math.exp(-r*T); // Now it's discounted..
  117.  
  118. results.put(Thread.currentThread().getName(), result);
  119.  
  120. latch.countDown();
  121. }
  122. }

On my 2 year old dual core MacBook Pro this is the output I get when running it:

Running 2 threads with 100000 sims in each thread..
Run time in millis: 4463
Thread-0: 9.590498
Thread-1: 9.614967
Option price: 9.602732

Hope you find it helpful 🙂

 

4 thoughts on “Pricing an Asian Option using multithreaded Java

  1. Vikas Gupta

    Hi.

    Nice Blog!! I suggest instead of storing the values in the current thread you could use Future Callable implementation. I guess it would be much Clearer.

    Thank,
    Vikas

    1. Christian Felde

      Thanks for the comment, and yes, absolutely room for design improvements but hopefully it serves as a decent example 😉

  2. Derek

    Hi,

    Very impressive. May I ask what method you use for pricing the options?

    1. Christian Felde

      Just Monte Carlo with a simple GBM.

Comments are closed.