HKUDS/Vibe-Trading · error · ValueError
T must be > 0 to imply a volatility, got
Error message
T must be > 0 to imply a volatility, got {T} What it means
implied_volatility solves for the sigma that reproduces a market price, and with T <= 0 the option has expired or the time argument is invalid — variance scales with T, so no positive volatility can be identified (and the pricer degenerates). The function demands strictly positive time to maturity before attempting any solve.
Solutions
- Check the date arithmetic: use precise year fractions (e.g. act/365 with intraday time) and verify expiry > as_of.
- Filter out expired contracts before the implied-vol loop.
- If T is legitimately tiny, use a minimum floor like T = max(T, 1/365/24) only if your risk convention allows approximation, or price at intrinsic instead.
Example fix
# before
T = (expiry - today).days / 365.0 # 0.0 when expiry == today
iv = implied_volatility(px, S, K, T, r, 'call')
# after
T = (expiry - today).days / 365.0
if T <= 0:
skip('contract expired')
iv = implied_volatility(px, S, K, T, r, 'call') Defensive patterns
Strategy: validation
Validate before calling
assert T > 0, f'expired or invalid T={T}'
if T <= 0:
handle_expired(contract) Type guard
def has_positive_maturity(T: float) -> bool:
return isinstance(T, (int, float)) and T > 0 Try / catch
try:
iv = implied_volatility(px, S, K, T, r, option_type)
except ValueError as e:
if 'T must be > 0' in str(e):
mark_expired(contract_id)
else:
raise Prevention
- Compute year fractions with a tested day-count helper including intraday time.
- Filter expiries <= as_of before the vol sweep.
- Use timezone-aware expiry parsing.
When it happens
Trigger: Calling implied_volatility(..., T=0) or T=-0.1; computing T as (expiry - today).days / 365 when expiry is today or in the past due to a date bug or timezone offset.
Common situations: Day-count bugs where T rounds to 0 for near-dated options; expiry dates parsed with the wrong timezone making today > expiry; stale market data feeds containing already-expired contracts.
Related errors
- legs[ ] has invalid strike or qty
- legs[ ] must be an object
- legs[ ].premium must be numeric or null
- legs[ ].qty must be a non-zero integer
- legs may contain at most
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/07334108e9449b40.
Report an issue: GitHub.
Appendix: source
Thrown at agent/src/quantlib/options.py:443
``tol`` and any of them would "converge". A 20-day call struck at half
the spot prices identically to 16 decimal places for every ``sigma``
from 0.05 to 0.60, so a solver that answers there is reporting the
arbitrary endpoint of its own search, not a market volatility. This
function refuses that: it checks vega at the candidate solution and
returns ``nan`` when the price carries no volatility information. That
is a property of the quote rather than a solver failure, and no
price-tolerance method can do better -- but a confident wrong number is
worse than an admitted absence.
Raises:
ValueError: If ``option_type`` is invalid, if ``T``, ``S`` or ``K`` is
non-positive, or if ``market_price`` lies outside the no-arbitrage
interval, which includes the intrinsic-value violation
``market_price < discounted intrinsic``.
"""
option_type = normalise_option_type(option_type)
if T <= 0:
raise ValueError(f"T must be > 0 to imply a volatility, got {T}")
if S <= 0 or K <= 0:
raise ValueError(f"S and K must be > 0, got S={S}, K={K}")
lower, upper = _no_arbitrage_bounds(S, K, T, r, option_type, q)
if market_price < lower - tol:
raise ValueError(
f"market price {market_price} is below intrinsic value {lower}"
)
if market_price >= upper:
raise ValueError(
f"market price {market_price} is at or above the no-arbitrage "
f"ceiling {upper}; no implied volatility exists"
)
def identified(candidate: float) -> float:
"""Return the candidate only if the quote actually pins it down.
The test is whether one volatility point of movement shifts the price byView on GitHub (pinned to 80ffdda44c)