Implied forward, carry and rates
There is exactly one implied forward per (timestamp, expiration), built from put-call parity on the strikes nearest spot. It is the price the market would agree today to pay for the underlying at expiration, and every contract of that expiry inherits it. Behind it sits the continuously-compounded rate that discounts the parity spread, and out of it fall two diagnostics: the carry the market is actually pricing, and the borrow left over once you subtract a dividend estimate. Of all these quantities, one reaches the Signal language: forward-centered log-moneyness. The forward itself, the carry, the borrow, and the rate are computed for every quote but have no accessor.
The implied forward
By no-arbitrage there is one forward per expiry, never a per-strike value. Compute it from put-call parity on a clean call/put pair at the same strike near the money:
forward = K + e^(r*t) * (call_mid - put_mid)The dividend, the borrow, and the market's continuation expectation are all implied by the call-minus-put spread. Only the rate r is needed, to discount that spread back. This is why parity is the preferred method: it reads the forward straight off two option prices without ever touching a dividend model.
One strike is not enough to trust. A single wide or stale mark would move the read. So the forward is taken as an outlier-resistant median over the five strikes nearest spot, computed per expiry. Disagreement across those five strikes is mark noise or early-exercise distortion, not real per-strike borrow, so reducing them to a median throws the noise away without smearing the read out toward the wings.
The result is broadcast to every contract row of that expiry. When you read a 30-delta call and a 10-delta put on the same expiration, they share the same forward.
The fallback ladder
Parity needs a clean two-sided pair. When an expiry does not have one, the forward drops down a ladder of three methods, in order:
forward = K + e^(r*t) * (call_mid - put_mid)forward = S_adjusted * e^(r*t)forward = SThe theoretical method is the only forward path that depends on the dividend model: S_adjusted is the spot with the present value of expected dividends escrowed out. The spot fallback exists to keep the forward strictly positive so downstream logs never blow up. It fires only on rows that are unpriceable anyway. In the spot case the forward equals raw spot, which reads as "no forward information."
A leg counts as clean only if it clears every one of these:
- The mid is present and positive.
- The leg is not one-sided.
- The quote was not flagged wide-spread or zero-bid by the IV quality checks.
- The relative bid/ask spread is within about 40%.
These checks are belt and braces. Any one failing drops the leg. A priced-but-noisy mark still carries an IV, so filtering on IV presence alone would let it through and inject error into the forward. The near-ATM pairs where the forward is read sit far inside the 40% ceiling in practice, so the gate mostly bites illiquid wings, which is the point.
The risk-free rate
The rate r behind every forward is continuously-compounded, interpolated from the Treasury curve to each option's exact days to expiration. It starts from the published Treasury par yield curve at seven tenors: 1-month, 3-month, 1-year, 2-year, 5-year, 10-year, and 30-year.
Published Treasury yields are par, bond-equivalent quotes. The pricing math consumes a continuously-compounded rate. So each tenor is converted once, before any interpolation:
- Tenors at 1 year and longer (semiannual-coupon par):
r_cc = 2 * ln(1 + y/2) - Sub-1-year bills (act/365):
r_cc = (365/d) * ln(1 + y*d/365), withdthe bill's day count
For a positive yield the continuously-compounded rate lands a few basis points below the par quote. A 5% par 1-year converts to 2 * ln(1.025) = 4.939%. Every downstream rate is a continuously-compounded decimal like 0.0494, not the raw par percentage.
Rate interpolation
To get r at an arbitrary DTE, interpolate linearly between the two bracketing tenors on the continuously-compounded curve. Two edges cap the ends:
- Below 30 days, use the 1-month rate flat.
- Above 30 years, use the 30-year rate flat.
The Treasury curve publishes on bond-market days. On a day the equity market is open but the bond market is closed, a federal holiday like Columbus Day or Veterans Day, no new curve is published. The most recent prior curve is carried forward (as-of-backward). The rate is null only when there is no Treasury curve on or before the query date at all, which puts the row outside the reference-data window rather than inside a gap.
Carry and borrow
Two diagnostics fall out of the forward and the raw spot:
implied_carry = ln(forward / S) / t // uses RAW spot S
implied_borrow = r - q - implied_carryimplied_carry is the model-free net cost of carry the market is actually pricing. It uses only the forward and the raw spot, no dividend model, so it carries no dividend-estimate error. Trust it. It is the clean read of r - q - borrow as the market prices it. In the degenerate spot-fallback case the forward equals raw spot, so the log is zero and carry reads zero, which is the honest "no forward information" value.
implied_borrow is the residual after removing the dividend estimate q. Because it subtracts an estimated yield, it inherits the error in that estimate. It is only as good as the dividend model behind q. Treat carry as reliable and borrow as estimate-dependent. implied_borrow also serves as the high-carry screen for the American early-exercise gate described on the implied volatility page.
Moneyness is centered on the forward
Moneyness is log-moneyness against the implied forward, not against spot:
moneyness = log(K / forward)moneyness = 0is the strike equal to the forward: at-the-money-forward.moneyness > 0isK > forward.moneyness < 0isK < forward.
Centering on the forward instead of spot removes the systematic (r - q)*t offset that carry and dividends otherwise push into the center of the smile. On SPY around $571 spot, 30 DTE, with no ex-dividend date in the window, forward - spot is about (r - q)*t, roughly +$1.8. That is about 0.3% of spot, or two strikes at $1 spacing. Spot-centering would sit the anchor two strikes off from where the smile is actually centered; forward-centering puts it where it belongs. (This offset moves with r and q, so it depends on the dividend estimate and the interpolated rate above.)
Because moneyness is a log measure, an ATM band is a small range around 0, for example -0.03 to 0.03 for roughly plus or minus 3%. A ratio-style band like K/S from 0.95 to 1.05 matches almost nothing here, since those numbers are around 1.0 and log-moneyness lives around 0.0.
What you read
Moneyness is the only quantity on this page exposed to the Signal language. It reaches you two ways:
- As the
moneynesscolumn on a selected contract, viaoption.contract(...).moneynessorleg(...).moneyness. - As the
moneyness=selection argument onoption.iv()and the Greek accessors, wheremoneyness=0.0selects at-the-money-forward.
// Forward-centered log-moneyness of the 30-DTE 30-delta call
option.contract(dte=30, delta=0.30).moneynessPassing the selection argument reads the same axis. This selects the 30-DTE contract nearest the forward and returns its moneyness, which sits near zero:
// Select the 30-DTE contract nearest at-the-money-forward
option.contract(dte=30, moneyness=0.0).moneynessThe forward itself, implied_carry, implied_borrow, the forward method (PCP / THEO / SPOT), and the rate r have no accessor. They are computed for every quote and used internally, for moneyness centering, the carry and borrow diagnostics, and the early-exercise screen, but they are not readable through an accessor. The only place a risk-free rate surfaces at all is inside the option.rho sensitivity, as the rate the greek is computed against, not as a rate series you can read on its own.