theta

Black-Scholes

Computes Theta of the option using the Black-Scholes model (time decay per day).

Avg. gas

3,101

Max abs. error

1.9e-12

when |θ| < 1

Max rel. error

5e-12

when |θ| ≥ 1

Signature

solidity
function theta(
    uint128 spot,
    uint128 strike,
    uint32  timeToExp,
    uint64  volatility,
    uint64  rate
) internal pure returns (int128 thetaCall, int128 thetaPut)

Parameters

NameTypeDescription
spotuint128Current spot price, 18-decimal fixed-point.
strikeuint128Strike price, 18-decimal fixed-point. Precision-tuned for the no-arbitrage band against spot — see Bounds.
timeToExpuint32Time to expiration in seconds. timeToExp == 0 is allowed (handled as expired).
volatilityuint64Annualized implied volatility, 18-decimal fixed-point (e.g. 60% → 6e17).
rateuint64Annualized risk-free rate, 18-decimal fixed-point.

Returns

NameTypeDescription
thetaCallint128Call theta per day in 18-decimal fixed-point. Typically ≤ 0 (value decays as time passes).
thetaPutint128Put theta per day in 18-decimal fixed-point.

Bounds

BoundValue
MIN_SPOT1e-6 smallest allowed spot price (1e12)
MAX_SPOT1e15 largest allowed spot price (1e33)
MAX_STSP_RATIO5× (strike must lie within [spot/5, spot·5])
MAX_EXPIRATION32 years (1,009,152,000 seconds)
MAX_RATE400% annual (4e18)

Behavior

  • Validates all five inputs against module-wide constants and reverts with a typed error on any violation.
  • Returns theta per day (the annual figure divided by 365) for both call and put, sharing the common time-decay term across the two.
  • Volatility has no explicit revert — it's bounded only by its uint64 type (max ≈ 1.84e19, i.e. ~1840% annualized). The MIN_VOL_IV / MAX_VOL_IV constants apply only to the impliedVolatility solver, not the greeks.
  • Fast-path on expiration: when timeToExp == 0, returns (0, 0).
  • Composes four DeFiMath primitives — ln, sqrtTime (specialized sqrt for years), expPositive (the discount factor e^(−rT)), exp (the density φ(d₁)), and stdNormCDF (the carry term). Its higher gas reflects that fuller composition.
  • Pure internal function; no external calls, no storage. Inlined into the caller's bytecode at compile time.

How it works

theta is the derivative of option value with respect to the passage of time. DeFiMath returns it per day — the annualized Black-Scholes theta divided by 365:

Θcall=1365[Sφ(d1)σ2TrKerTΦ(d2)]\Theta_{call} = \frac{1}{365}\left[ -\frac{S \, \varphi(d_1) \, \sigma}{2\sqrt{T}} - r K e^{-rT} \Phi(d_2) \right]
Θput=1365[Sφ(d1)σ2T+rKerTΦ(d2)]\Theta_{put} = \frac{1}{365}\left[ -\frac{S \, \varphi(d_1) \, \sigma}{2\sqrt{T}} + r K e^{-rT} \Phi(-d_2) \right]

The shared time-decay term S·φ(d₁)·σ / (2√T) is computed once and reused for both call and put; only the sign and the carry term r·K·e^(−rT)·Φ(±d₂) differ. The density φ(d₁) uses Math.exp, the discount factor e^(−rT) uses Math.expPositive, the carry CDF uses Math.stdNormCDF, and √T / ln(spot/strike) use Math.sqrtTime / Math.ln.

Precision follows the dual-metric rule: a relative bound of 5e-12 where |θ| ≥ 1 and an absolute bound of 1.9e-12 where |θ| < 1. Both are enforced at spot = $1,000 across a full sweep of strike, time, vol, and rate — head-to-head measurements live in defimath-compare.

Errors

ErrorTrigger
SpotLowerBoundErrorspot ≤ MIN_SPOT
SpotUpperBoundErrorspot ≥ MAX_SPOT
StrikeLowerBoundErrorstrike · 5 < spot
StrikeUpperBoundErrorspot · 5 < strike
TimeToExpiryUpperBoundErrortimeToExp ≥ MAX_EXPIRATION
RateUpperBoundErrorrate ≥ MAX_RATE

Example

solidity
import "defimath-lib/contracts/derivatives/BlackScholes.sol";

(int128 thetaCall, int128 thetaPut) = BlackScholes.theta(
    1000e18,         // spot = $1,000
    980e18,          // strike = $980
    60 days,         // 60 days to expiry
    0.60e18,         // 60% annualized vol
    0.05e18          // 5% risk-free rate
);
// thetaCall ≈ -0.45e18 per day (about -$0.45/day)