Options Pricing Engine
Problem Description
Price 500,000 European options using Black-Scholes. Handle puts and calls with various strikes, expirations, volatilities, and risk-free rates.
Compute the option price and all Greeks: delta, gamma, vega, theta, and rho. All values are compared against a reference Black-Scholes implementation with a tolerance of 0.0001.
Tier System & Performance Targets
| LANGUAGE | GOLD | SILVER | BRONZE |
|---|---|---|---|
| C++ / Rust | < 400ms | < 1500ms | < 120s |
| Java | < 800ms | < 3000ms | < 120s |
| Python | < 5000ms | < 15000ms | < 120s |
Evaluation Criteria
Correctness: Each of the 6 output values per line (price, delta, gamma, vega, theta, rho) is compared individually. A value is "correct" if it is within 0.0001 of the reference. Your accuracy score is correct values / total values.
Performance: Wall-clock time to price all 500K options. Numerical stability matters for deep ITM/OTM contracts.
Input Format
Read from stdin. The first line is the number of contracts N. The next N lines each contain a comma-separated option:
S,K,T,r,sigma,TYPE
Where:
S: Spot price of the underlying (50-200)K: Strike priceT: Time to expiry in years (0.01-2.0)r: Risk-free rate (0.01-0.08)sigma: Volatility (0.1-0.6)TYPE:C(call) orP(put)
Output Format
For each option, output one line with 6 space-separated values to 6 decimal places:
PRICE DELTA GAMMA VEGA THETA RHO
Example
Input
3
100.0,100.0,0.5,0.05,0.25,C
100.0,90.0,1.0,0.03,0.30,P
120.0,110.0,0.25,0.04,0.20,C
Output
8.260015 0.590880 0.021979 27.474322 -9.409981 25.414001
5.946349 -0.273853 0.011099 33.298418 -3.994814 -33.331631
12.101627 0.846163 0.019759 14.226266 -9.268023 22.359476
Line 1: ATM call -- delta near 0.5, highest gamma. Line 2: OTM put -- negative delta and rho. Line 3: ITM call -- delta near 1, lower gamma.
Submission Rules
- Your program receives input via stdin
- Output prices and Greeks to stdout (6 decimal places)
- Program must complete within 120 seconds
- Memory usage must not exceed 2GB
- Single-file solutions only
- Java class must be named
Solution
Starter Templates
C++
#include <cstdio>
#include <cmath>
#include <cstring>
int main() {
int N;
scanf("%d", &N);
double S, K, T, r, sigma;
char type;
for (int i = 0; i < N; i++) {
scanf("%lf,%lf,%lf,%lf,%lf,%c", &S, &K, &T, &r, &sigma, &type);
// Implement Black-Scholes pricing
// Compute: price, delta, gamma, vega, theta, rho
double price = 0, delta = 0, gamma = 0, vega = 0, theta = 0, rho = 0;
printf("%.6f %.6f %.6f %.6f %.6f %.6f\n",
price, delta, gamma, vega, theta, rho);
}
return 0;
}
Python
import sys
import math
def normal_cdf(x):
return 0.5 * (1.0 + math.erf(x / math.sqrt(2.0)))
def normal_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2.0 * math.pi)
def price_option(S, K, T, r, sigma, option_type):
sqrt_T = math.sqrt(T)
d1 = (math.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * sqrt_T)
d2 = d1 - sigma * sqrt_T
# Implement Black-Scholes: compute price, delta, gamma, vega, theta, rho
return 0, 0, 0, 0, 0, 0
for line in sys.stdin:
parts = line.strip().split()
N = int(input())
for _ in range(N):
parts = input().split(',')
S = float(parts[0])
K = float(parts[1])
T = float(parts[2])
r = float(parts[3])
sigma = float(parts[4])
option_type = parts[5].strip()
price, delta, gamma, vega, theta, rho = price_option(S, K, T, r, sigma, option_type)
print(f"{price:.6f} {delta:.6f} {gamma:.6f} {vega:.6f} {theta:.6f} {rho:.6f}")
Rust
use std::io::{self, BufRead, Write, BufWriter};
fn normal_cdf(x: f64) -> f64 {
0.5 * (1.0 + libm::erf(x / std::f64::consts::SQRT_2))
}
fn main() {
let stdin = io::stdin();
let stdout = io::stdout();
let mut out = BufWriter::new(stdout.lock());
let mut lines = stdin.lock().lines();
let n: usize = lines.next().unwrap().unwrap().trim().parse().unwrap();
for _ in 0..n {
let line = lines.next().unwrap().unwrap();
let parts: Vec<&str> = line.trim().split(',').collect();
let s: f64 = parts[0].parse().unwrap();
let k: f64 = parts[1].parse().unwrap();
let t: f64 = parts[2].parse().unwrap();
let r: f64 = parts[3].parse().unwrap();
let sigma: f64 = parts[4].parse().unwrap();
let opt_type = parts[5].trim();
// Implement Black-Scholes: compute price, delta, gamma, vega, theta, rho
let (price, delta, gamma, vega, theta, rho) = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
writeln!(out, "{:.6} {:.6} {:.6} {:.6} {:.6} {:.6}",
price, delta, gamma, vega, theta, rho).unwrap();
}
}
Java
import java.util.*;
import java.io.*;
public class Solution {
static double normalCdf(double x) {
return 0.5 * (1.0 + erf(x / Math.sqrt(2.0)));
}
static double erf(double x) {
// Horner form approximation
double t = 1.0 / (1.0 + 0.3275911 * Math.abs(x));
double y = 1.0 - (((((1.061405429 * t - 1.453152027) * t)
+ 1.421413741) * t - 0.284496736) * t + 0.254829592) * t * Math.exp(-x * x);
return x >= 0 ? y : -y;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int N = Integer.parseInt(br.readLine().trim());
for (int i = 0; i < N; i++) {
String[] parts = br.readLine().trim().split(",");
double S = Double.parseDouble(parts[0]);
double K = Double.parseDouble(parts[1]);
double T = Double.parseDouble(parts[2]);
double r = Double.parseDouble(parts[3]);
double sigma = Double.parseDouble(parts[4]);
String type = parts[5].trim();
// Implement Black-Scholes: compute price, delta, gamma, vega, theta, rho
double price = 0, delta = 0, gamma = 0, vega = 0, theta = 0, rho = 0;
sb.append(String.format("%.6f %.6f %.6f %.6f %.6f %.6f%n",
price, delta, gamma, vega, theta, rho));
}
System.out.print(sb);
}
}