theta

Black-76

Computes Theta of the option on a future using the Black-76 model (time decay per day).

Avg. gas

3,255

Max abs. error

1.9e-12

when |θ| < 1

Max rel. error

5e-12

when |θ| ≥ 1

Signature

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

Parameters

NameTypeDescription
futureuint128Current future price in 18-decimal fixed-point format.
strikeuint128Strike price, 18-decimal fixed-point. Precision-tuned for the no-arbitrage band against the future — 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 (discount) rate, 18-decimal fixed-point.

Returns

NameTypeDescription
thetaCallint128Call theta per day in 18-decimal fixed-point.
thetaPutint128Put theta per day in 18-decimal fixed-point.

Bounds

BoundValue
MIN_FUTURE1e-6 smallest allowed future price (1e12)
MAX_FUTURE1e15 largest allowed future price (1e33)
MAX_STSP_RATIO5× (strike must lie within [future/5, future·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.
  • Fast-path on expiration: when timeToExp == 0, returns (0, 0).
  • Composes five DeFiMath primitives — ln, sqrtTime, expPositive (the discount factor), 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, returned per day (÷365). Under Black-76 the discount factor adds a carry term to the usual time decay:

Θ=1365[rpriceerTFφ(d1)σ2T]\Theta = \frac{1}{365}\left[ r \cdot \text{price} - \frac{e^{-rT} F \, \varphi(d_1) \, \sigma}{2\sqrt{T}} \right]

The shared time-decay term e^(−rT)·F·φ(d₁)·σ / (2√T) is computed once and reused for both call and put; only the sign and the carry term r·price differ (the call and put prices differ, so their carries do too). The density φ(d₁) uses Math.exp, the discount Math.expPositive, the carry CDFs Math.stdNormCDF.

Precision follows the dual-metric rule: a relative bound of 5e-12 where |θ| ≥ 1 and an absolute bound of 1.9e-12 where |θ| < 1, at future = $1,000 — head-to-head measurements live in defimath-compare.

Errors

ErrorTrigger
FutureLowerBoundErrorfuture ≤ MIN_FUTURE
FutureUpperBoundErrorfuture ≥ MAX_FUTURE
StrikeLowerBoundErrorstrike · 5 < future
StrikeUpperBoundErrorfuture · 5 < strike
TimeToExpiryUpperBoundErrortimeToExp ≥ MAX_EXPIRATION
RateUpperBoundErrorrate ≥ MAX_RATE

Example

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

(int128 thetaCall, int128 thetaPut) = Black76.theta(
    1000e18,         // future = $1,000
    1050e18,         // strike = $1,050
    90 days,         // 90 days to expiry
    0.60e18,         // 60% annualized vol
    0.05e18          // 5% discount rate
);
// thetaCall, thetaPut per day (signed)