# Run 1B option simulations

In this example we:

* Simulate 1,000,000,000 option price paths.
* Split the run into 2,000 independent chunks.
* Return sums and squared sums, then compute the final price and error bar locally.

A smaller run is not the same experiment if the whole point is the error bar.

### Experiment: European call option

Each path is independent, so the job does not need shared state or a distributed framework.

```python
import math
from dataclasses import dataclass

import numpy as np
from burla import remote_parallel_map

TOTAL = 1_000_000_000
N_CHUNKS = 2_000
PER_CHUNK = TOTAL // N_CHUNKS
```

### Step 1: Plan independent chunks

The chunk id becomes part of the random seed, so reruns are reproducible without shared state.

```python
@dataclass(frozen=True)
class SimulationTask:
    chunk_id: int
    n_paths: int
    params: dict

params = {"S0": 100.0, "K": 95.0, "T": 1.0, "r": 0.01, "sigma": 0.3}
tasks = [SimulationTask(i, PER_CHUNK, params) for i in range(N_CHUNKS)]

print(f"Built {len(tasks):,} chunks of {PER_CHUNK:,} paths")
```

### Step 2: Simulate on the worker

The worker is normal NumPy. It returns enough statistics to combine results exactly.

```python
def run_chunk(task: SimulationTask) -> dict:
    p = task.params
    rng = np.random.default_rng(seed=42 + task.chunk_id)
    z = rng.standard_normal(task.n_paths)
    st = p["S0"] * np.exp((p["r"] - 0.5 * p["sigma"] ** 2) * p["T"] + p["sigma"] * np.sqrt(p["T"]) * z)
    payoff = np.maximum(st - p["K"], 0.0) * np.exp(-p["r"] * p["T"])
    return {
        "chunk_id": task.chunk_id,
        "n": task.n_paths,
        "sum": float(payoff.sum()),
        "sum_sq": float((payoff ** 2).sum()),
    }
```

No simulated path comes back to the client. Only sufficient statistics do.

### Step 3: Smoke test one chunk

Run one chunk first to check memory, runtime, and output shape.

```python
test_result = remote_parallel_map(
    run_chunk,
    tasks[:1],
    func_cpu=1,
    func_ram=2,
)[0]

print(test_result)
```

### Step 4: Run and reduce locally

The result list is tiny because the workers do not return raw paths.

```python
results = remote_parallel_map(run_chunk, tasks, func_cpu=1, func_ram=2, grow=True)

total_n = sum(r["n"] for r in results)
mean = sum(r["sum"] for r in results) / total_n
var = (sum(r["sum_sq"] for r in results) / total_n) - mean ** 2
se = math.sqrt(var / total_n)

print({"price": mean, "standard_error": se, "paths": total_n})
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.burla.dev/all-examples/production-data-jobs/monte-carlo-simulation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
