{"record":{"id":"6429ccf2b2d76bca","repo":"HKUDS/Vibe-Trading","slug":"market-price-market-price-is-below-intrinsic-val","errorCode":null,"errorMessage":"market price {market_price} is below intrinsic value {lower}","messagePattern":"market price (.+?) is below intrinsic value (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/options.py","lineNumber":449,"sourceCode":"        is a property of the quote rather than a solver failure, and no\n        price-tolerance method can do better -- but a confident wrong number is\n        worse than an admitted absence.\n\n    Raises:\n        ValueError: If ``option_type`` is invalid, if ``T``, ``S`` or ``K`` is\n            non-positive, or if ``market_price`` lies outside the no-arbitrage\n            interval, which includes the intrinsic-value violation\n            ``market_price < discounted intrinsic``.\n    \"\"\"\n    option_type = normalise_option_type(option_type)\n    if T <= 0:\n        raise ValueError(f\"T must be > 0 to imply a volatility, got {T}\")\n    if S <= 0 or K <= 0:\n        raise ValueError(f\"S and K must be > 0, got S={S}, K={K}\")\n\n    lower, upper = _no_arbitrage_bounds(S, K, T, r, option_type, q)\n    if market_price < lower - tol:\n        raise ValueError(\n            f\"market price {market_price} is below intrinsic value {lower}\"\n        )\n    if market_price >= upper:\n        raise ValueError(\n            f\"market price {market_price} is at or above the no-arbitrage \"\n            f\"ceiling {upper}; no implied volatility exists\"\n        )\n\n    def identified(candidate: float) -> float:\n        \"\"\"Return the candidate only if the quote actually pins it down.\n\n        The test is whether one volatility point of movement shifts the price by\n        more than the tolerance the solve was run to. If it does not, then a\n        whole band of volatilities reprices within ``tol`` and whichever one the\n        search happens to land on is an artefact of the search, not a reading of\n        the market. Comparing vega against an absolute floor cannot express\n        this, because the threshold has to scale with ``tol``.\n","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/options.py#L431-L467","documentation":"implied_volatility first checks the quote against no-arbitrage bounds: the discounted intrinsic value is the lower bound (within tolerance tol). A market price below intrinsic is arbitrageable and cannot be matched by any volatility, so the function refuses instead of returning sigma ~ 0 or a nonsense negative vol.","triggerScenarios":"Quoting 3.0 for a 100/120 call with S=100 (intrinsic 0) is fine, but quoting 0.5 for a 100/95 call near expiry (intrinsic ~5) triggers it; also stale prices where the spot moved but the option quote did not, or a wrong dividend rate q inflating the computed lower bound.","commonSituations":"Crossed/stale quotes in market data snapshots; using the wrong interest rate or dividend yield so the computed intrinsic exceeds the quote; mixed up bid/ask sides or price multiplied by the wrong contract multiplier.","solutions":["Verify r, q, S, K, and option_type are all correct for this contract.","If the quote is stale, refresh data or skip the contract.","If the shortfall is within tolerance, raise tol — but only after confirming it is a rounding-level discrepancy."],"exampleFix":"# before\niv = implied_volatility(market_price=4.90, S=100, K=95, T=0.01, r=0.0, option_type='call', tol=1e-8)  # intrinsic ~5 -> raises\n\n# after\niv = implied_volatility(4.90, 100, 95, 0.01, 0.0, 'call', tol=0.25)  # explicit, documented slack","handlingStrategy":"validation","validationCode":"S_disc = S * math.exp(-q * T) if option_type == 'call' else K * math.exp(-r * T)\nassert market_price >= intrinsic_lower_bound - tol  # recompute or use doc'd bound","typeGuard":"def quote_above_intrinsic(price: float, S: float, K: float, put: bool) -> bool:\n    return price >= (max(0.0, K - S) if put else max(0.0, S - K)) - 1e-9","tryCatchPattern":"try:\n    iv = implied_volatility(px, S, K, T, r, option_type)\nexcept ValueError as e:\n    if 'below intrinsic' in str(e):\n        skip_quote(quote_id, reason='sub-intrinsic')\n    else:\n        raise","preventionTips":["Cross-check r and q against the contract's conventions.","Screen out sub-intrinsic quotes in the market-data layer.","Never widen tol to force a solve — investigate the quote first."],"tags":["options","implied-volatility","no-arbitrage","intrinsic-value"],"backgroundTag":"no-arbitrage-bound-violation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}