# Price an Option

*Task 4 of 4 · [Monte Carlo Methods](https://gpu.rocks/learn/monte-carlo-methods-9ea19810.md) · GPU.js Learn*

The payoff. A **European call option** is the right to buy a stock at
a fixed strike price K on a future date — worth `max(S_T − K, 0)` when the stock
finishes at `S_T`, and its fair price today is the *discounted expected
payoff*. Expectations are integrals, and you just learned to integrate by sampling.

Each thread simulates one possible market: under the standard log-normal model, a
pre-drawn normal shock `z` gives
`S_T = S0 · e^(drift + volT · z)`. Your kernel turns 16,384 shocks into
16,384 payoffs; JavaScript averages and discounts. Stock at 100, strike 105, one year out —
the Black–Scholes formula says the answer is ≈ 7.13. Your simulation should agree.

## Goal

**Goal:** complete the payoff kernel — simulate this thread's final stock
price and return the option payoff `max(S_T − strike, 0)`.

## Requirements

- Simulate the final price: `s0 * Math.exp(drift + volT * z)` (already wired)
- Return the call payoff: `Math.max(st - strike, 0)` — an option never goes negative
- Average the payoffs and discount by `Math.exp(-RATE * T)` in JavaScript

## Hint 1 — why the max?

If the stock ends below the strike you simply don't exercise — the option
expires worthless, payoff 0, never negative. Forgetting the `max` drags the
average down by every losing path (the price comes out near −1.9 instead of ≈ 7.1).

## Hint 2 — the kernel body

`return Math.max(st - strike, 0);` — `Math.max` works
inside kernels, and beats an `if` here.

## Same idea elsewhere

This is production reality: quant desks run exactly this workload on CUDA and ROCm
— millions of simulated paths per pricing call, one thread per path, then a reduction —
because exotic options have no closed form at all. You now hold the whole recipe.

## Starter code

```js
// Fair price = discounted average payoff over simulated futures.
// Stock at 100, strike 105, 3% rate, 20% volatility, 1 year to expiry.
const S0 = 100, STRIKE = 105, RATE = 0.03, SIGMA = 0.2, T = 1;

const gpu = new GPU({ mode });

const payoff = gpu.createKernel(function (normals, s0, strike, drift, volT) {
  const z = normals[this.thread.x];
  const st = s0 * Math.exp(drift + volT * z); // this thread's final stock price
  // TODO: return the call payoff — st minus strike, but never below zero.
  return st - strike;
}, { output: [16384] });

const payoffs = await payoff(normals, S0, STRIKE, (RATE - SIGMA * SIGMA / 2) * T, SIGMA * Math.sqrt(T));

let sum = 0;
for (let i = 0; i < payoffs.length; i++) sum += payoffs[i];
const price = Math.exp(-RATE * T) * (sum / payoffs.length);
console.log('Monte Carlo price:', price, '— Black–Scholes says ≈ 7.13');
```

---

Interactive version: https://gpu.rocks/learn/monte-carlo-methods-9ea19810/4

[Previous task](https://gpu.rocks/learn/monte-carlo-methods-9ea19810/3.md)
