Assessing Renewal Options: The Reasonably Certain Threshold in Python
Decide whether renewal or termination option periods enter the lease term under the reasonably-certain threshold (ASC 842-10-30-1..3 / IFRS 16.18-19) with an economic-incentive scoring model.
Problem Statement Link to this section
The lease term is the input that sizes everything: it bounds the payment vector that seeds the present value calculation logic, it sets the amortization horizon for the right-of-use asset, and it decides how many rows the liability schedule unwinds. The judgment that fixes it is the reasonably certain threshold: an option to extend the lease, or to not exercise a termination option, is only folded into the term when the lessee is reasonably certain to take that action. This is a genuinely high bar — higher than "more likely than not" — and it is where extracted contract data meets accounting judgment. The engineering problem is to turn a set of economic-incentive factors into a defensible, repeatable decision that returns the accounting lease term. This page specifies the scoring logic and encodes it in a decimal-precision Python function ending in a terminal assertion; the raw option clauses it consumes come from an upstream extractor such as extracting renewal options with spaCy and regex.
Standard Anchor Link to this section
Both frameworks define the lease term as the non-cancellable period plus option periods the lessee is reasonably certain to exercise (or reasonably certain not to terminate). Under ASC 842-10-30-1, the lease term comprises the non-cancellable period together with periods covered by an option to extend if the lessee is reasonably certain to exercise it, periods covered by a termination option the lessee is reasonably certain not to exercise, and periods covered by an option controlled by the lessor. ASC 842-10-30-2 and 30-3 direct the lessee to consider all economic factors — contract-based, asset-based, entity-based, and market-based — that create an economic incentive to exercise.
IFRS 16.18 states the same construction of the term, and IFRS 16.19 requires the lessee to consider all relevant facts and circumstances that create an economic incentive. The application guidance in IFRS 16.B37–B40 enumerates the factors: contractual terms for optional periods compared with market rates, significant leasehold improvements expected to have value beyond the option date, costs of termination and relocation, the importance of the underlying asset to operations, and any conditionality attached to exercising. "Reasonably certain" is intentionally a high threshold — the same phrase both standards use — so borderline options are excluded, and the assessment is reconsidered only on a significant event or change in circumstances within the lessee's control.
Formula / Algorithm Specification Link to this section
The decision is a weighted assessment of economic-incentive factors. Let each factor
where
with
where
Annotated Python Snippet Link to this section
The function scores a single option period against its economic-incentive factors and returns whether it is included plus the resulting accounting lease term in months. Weights and strengths are Decimal, the threshold is explicit, and the terminal assertion proves the term reflects the inclusion decision.
from dataclasses import dataclass
from decimal import Decimal, getcontext
getcontext().prec = 28
@dataclass(frozen=True)
class Factor:
name: str
weight: Decimal # significance; weights across factors sum to 1
strength: Decimal # signed in [-1, 1]: + favors exercise, - discourages
@dataclass(frozen=True)
class OptionPeriod:
months: int
factors: tuple[Factor, ...]
def lease_term_months(non_cancellable: int, options: list[OptionPeriod],
threshold: Decimal = Decimal("0.75")) -> dict:
"""Include option periods that are 'reasonably certain'
(ASC 842-10-30-1..3 / IFRS 16.18-19, B37-B40)."""
term, included = non_cancellable, []
for idx, opt in enumerate(options):
total_w = sum((f.weight for f in opt.factors), Decimal("0"))
assert total_w == Decimal("1"), "factor weights must sum to 1"
score = sum((f.weight * f.strength for f in opt.factors), Decimal("0"))
if score >= threshold: # high bar = 'reasonably certain'
term += opt.months
included.append(idx)
return {"term_months": term, "included": included}
option = OptionPeriod(months=60, factors=(
Factor("below-market renewal rent", Decimal("0.40"), Decimal("1.0")),
Factor("significant leasehold improvements", Decimal("0.30"), Decimal("0.9")),
Factor("high relocation cost", Decimal("0.20"), Decimal("0.8")),
Factor("strategic asset", Decimal("0.10"), Decimal("0.5")),
)) # score = 0.40 + 0.27 + 0.16 + 0.05 = 0.88 >= 0.75 -> include
result = lease_term_months(non_cancellable=60, options=[option])
# One 60-month option clears the threshold, so term = 60 + 60
assert result["term_months"] == 120 and result["included"] == [0]
The score of 0.88 clears the 0.75 threshold, so the sixty-month option is folded in and the term doubles to 120 months. Lower any single strength enough — a renewal priced at market, say — and the score drops below the threshold and the option drops out, which is exactly the sensitivity an auditor probes.
Correct vs. Incorrect Threshold Application Link to this section
The recurring error is applying the wrong bar — treating "probable" or "more likely than not" as sufficient. The table contrasts a correct assessment with the common shortcuts.
| Aspect | Correct (reasonably certain) | Incorrect (common shortcut) |
|---|---|---|
| Threshold meaning | High bar, well above 50% | "More likely than not" (~50%) |
| Factors weighed | All economic incentives (B37-B40) | Renewal rent only |
| Leasehold improvements | Included if value extends past option date | Ignored |
| Reassessment trigger | Significant event within lessee control | Every reporting date |
| Lessor-controlled option | Always in the term | Excluded like a lessee option |
Gotcha / Failure Mode: Reassessing on Market Movements Alone Link to this section
A frequent defect is re-cutting the lease term every time market rents move. Both standards reassess the term only on a significant event or change in circumstances within the lessee's control — not for ordinary market drift.
Before (WRONG — reassesses on any rate change):
if market_rent_changed: # WRONG: market drift is not a trigger
term = recompute_lease_term(lease)
After (correct — reassess only on a lessee-controlled significant event):
trigger = (built_significant_improvement or exercised_or_waived_option
or business_use_changed) # ASC 842-10-35-1 / IFRS 16.20-21
if trigger:
term = recompute_lease_term(lease) # then remeasure liability at revised rate
Debug checklist when a term looks wrong:
- Confirm the threshold is high. A model tuned to ~0.5 encodes "more likely than not", not "reasonably certain".
- Check every B37-B40 factor is represented. A missing leasehold-improvement factor understates the incentive to renew.
- Include lessor-controlled options unconditionally. They are always part of the term regardless of the lessee's incentive.
- Gate reassessment on a real trigger. Market-rent movement alone does not reopen the term.
Frequently Asked Questions Link to this section
What does "reasonably certain" actually mean for a renewal option?
It is a high threshold — well above "more likely than not". A lessee includes an option period in the lease term only when economic incentives make exercise reasonably certain: a materially below-market renewal rent, significant leasehold improvements with value beyond the option date, high relocation or termination costs, or strategic reliance on the asset. Borderline cases are excluded, because both ASC 842-10-30-1 and IFRS 16.18 set the bar deliberately high.
Which factors drive the reasonably-certain assessment?
The economic-incentive factors in ASC 842-10-30-2..3 and IFRS 16.B37-B40: contractual renewal or termination pricing versus market, significant leasehold improvements expected to have value beyond the option date, the cost of termination and relocation, the importance of the underlying asset to operations, and any conditionality on exercise. All relevant factors are weighed together; renewal rent alone is not sufficient.
When is the lease term reassessed after commencement?
Only on a significant event or change in circumstances within the lessee's control — for example constructing significant leasehold improvements, a change in business use, or exercising or waiving an option. Ordinary movements in market rents do not trigger reassessment. When a trigger does occur, the term is recut and the liability is remeasured at a revised discount rate under ASC 842-10-35-1 / IFRS 16.20-21.
Related Link to this section
- Handling embedded leases in service contracts — the sibling judgment of whether a contract contains a lease at all before its term is measured.
- Lease term boundary definitions — the parent topic on non-cancellable periods, options, and term construction.
- ASC 842 and IFRS 16 core architecture and ROU models — the framework that consumes the lease term to size the liability and asset.