Docs/dolt plan clarifications #1

Merged
dennisthiessen merged 34 commits from docs/dolt-plan-clarifications into main 2026-07-23 13:27:08 +02:00
3 changed files with 68 additions and 7 deletions
Showing only changes of commit 256880899b - Show all commits
+30 -6
View File
@@ -84,8 +84,9 @@ def derive(snapshots: Iterable[Any]) -> DerivedFundamentals:
ttm_capex = _ttm(discrete["capex"], *latest) ttm_capex = _ttm(discrete["capex"], *latest)
result.ttm_fcf = None if ttm_cfo is None or ttm_capex is None else ttm_cfo - ttm_capex result.ttm_fcf = None if ttm_cfo is None or ttm_capex is None else ttm_cfo - ttm_capex
# tape = the last TAPE_LEN quarters that have a row, oldest -> newest # tape = the CONSECUTIVE run of up to TAPE_LEN quarters ending at the latest,
tape = quarters[-TAPE_LEN:] # stopping at a gap — so trend text never compares non-adjacent periods.
tape = _consecutive_suffix(quarters, TAPE_LEN)
result.metrics = { result.metrics = {
"revenue_growth_yoy": _yoy_growth_series(discrete["revenue"], selected, tape), "revenue_growth_yoy": _yoy_growth_series(discrete["revenue"], selected, tape),
"eps_growth_yoy": _yoy_growth_series(discrete["diluted_eps"], selected, tape), "eps_growth_yoy": _yoy_growth_series(discrete["diluted_eps"], selected, tape),
@@ -125,6 +126,24 @@ def _ordered_quarters(selected: dict[tuple[int, str], Any]) -> list[tuple[int, i
return sorted((fy, _FP_TO_Q[fp]) for (fy, fp) in selected) return sorted((fy, _FP_TO_Q[fp]) for (fy, fp) in selected)
def _consecutive_suffix(quarters: list[tuple[int, int]], n: int) -> list[tuple[int, int]]:
"""The run of up to n quarters ending at the latest, walking back only through
adjacent periods (stop at the first gap). Returned oldest -> newest."""
if not quarters:
return []
present = set(quarters)
run = [quarters[-1]]
cur = quarters[-1]
while len(run) < n:
prev = _prev_q(*cur)
if prev not in present:
break
run.append(prev)
cur = prev
run.reverse()
return run
# -- discrete + TTM ---------------------------------------------------------- # -- discrete + TTM ----------------------------------------------------------
def _discrete_quarters(selected: dict[tuple[int, str], Any], field_name: str) -> dict[tuple[int, int], float]: def _discrete_quarters(selected: dict[tuple[int, str], Any], field_name: str) -> dict[tuple[int, int], float]:
@@ -162,7 +181,8 @@ def _ttm(dq: dict[tuple[int, int], float], fy: int, q: int) -> float | None:
def _pct_change(cur: float | None, prior: float | None) -> float | None: def _pct_change(cur: float | None, prior: float | None) -> float | None:
if cur is None or prior is None or prior == 0: # A non-positive prior makes a YoY % meaningless (e.g. loss->profit), so null it.
if cur is None or prior is None or prior <= 0:
return None return None
return (cur / prior - 1.0) * 100.0 return (cur / prior - 1.0) * 100.0
@@ -212,7 +232,9 @@ def _leverage_series(selected, discrete, tape) -> MetricSeries:
nd = _net_debt(row) nd = _net_debt(row)
op, da = _ttm(discrete["operating_income"], fy, q), _ttm(discrete["depreciation_amortization"], fy, q) op, da = _ttm(discrete["operating_income"], fy, q), _ttm(discrete["depreciation_amortization"], fy, q)
ebitda = None if op is None or da is None else op + da ebitda = None if op is None or da is None else op + da
val = None if nd is None or not ebitda else nd / ebitda # Null when EBITDA <= 0: a negative denominator would flip polarity and a
# "lower is better" read would rank a distressed issuer as favorable.
val = None if nd is None or ebitda is None or ebitda <= 0 else nd / ebitda
pts.append(MetricPoint(_period_end(selected, fy, q), val)) pts.append(MetricPoint(_period_end(selected, fy, q), val))
return _series(pts) return _series(pts)
@@ -231,9 +253,11 @@ def _net_debt(row: Any) -> float | None:
return None return None
cash = getattr(row, "cash_and_st_investments", None) cash = getattr(row, "cash_and_st_investments", None)
debt = getattr(row, "total_debt", None) debt = getattr(row, "total_debt", None)
if cash is None and debt is None: # Require BOTH components — treating a missing side as zero would produce a
# partial, misleading value.
if cash is None or debt is None:
return None return None
return (debt or 0.0) - (cash or 0.0) # positive = net debt return debt - cash # positive = net debt
def _shares(row: Any) -> float | None: def _shares(row: Any) -> float | None:
+1 -1
View File
@@ -244,7 +244,7 @@ that scoring already reads, refreshed daily by step (c) after activation.
| EPS growth YoY | TTM diluted EPS vs prior TTM | snapshot | | EPS growth YoY | TTM diluted EPS vs prior TTM | snapshot |
| Operating margin + 4q trend | TTM operating income / revenue | snapshot | | Operating margin + 4q trend | TTM operating income / revenue | snapshot |
| FCF margin | (TTM CFO capex) / revenue | snapshot | | FCF margin | (TTM CFO capex) / revenue | snapshot |
| Net cash / net debt | cash + ST investments total debt | snapshot | | Net debt | total debt (cash + ST investments); positive = net debt | snapshot |
| Net debt / EBITDA | net debt / TTM EBITDA | snapshot | | Net debt / EBITDA | net debt / TTM EBITDA | snapshot |
| Share count Δ YoY | shares outstanding vs year ago | snapshot | | Share count Δ YoY | shares outstanding vs year ago | snapshot |
| Trailing P/E | price / TTM diluted EPS | request time | | Trailing P/E | price / TTM diluted EPS | request time |
@@ -123,6 +123,43 @@ def test_missing_period_yields_null_never_partial():
assert d.ttm_diluted_eps is None assert d.ttm_diluted_eps is None
def test_net_debt_requires_both_components():
rows = _two_years()
for r in rows: # drop debt on the latest year -> can't form net debt
if r.fiscal_year == 2026:
r.total_debt = None
d = fd.derive(rows)
assert d.metrics["net_debt"].value is None
assert d.metrics["net_debt_to_ebitda"].value is None # net debt null -> leverage null
def test_leverage_null_when_ebitda_nonpositive():
rows = _two_years()
for r in rows: # negative operating income -> TTM EBITDA <= 0
r.operating_income = -abs(r.revenue)
r.depreciation_amortization = 1
d = fd.derive(rows)
assert d.metrics["net_debt"].value == pytest.approx(100.0) # net debt still valid
assert d.metrics["net_debt_to_ebitda"].value is None # but leverage nulled
def test_tape_stops_at_a_gap():
rows = [r for r in _two_years() if not (r.fiscal_year == 2026 and r.fiscal_period == "Q1")]
d = fd.derive(rows)
hist = d.metrics["operating_margin"].history
# consecutive suffix ending at FY2026: Q2, Q3, FY (not compressed across the Q1 gap)
assert [p.period_end for p in hist] == [date(2026, 3, 31), date(2026, 6, 30), date(2026, 9, 30)]
def test_yoy_growth_null_when_prior_nonpositive():
rows = _two_years()
for r in rows: # prior-year TTM EPS becomes negative
if r.fiscal_year == 2025:
r.diluted_eps = -abs(r.diluted_eps)
d = fd.derive(rows)
assert d.metrics["eps_growth_yoy"].value is None # loss->profit is not a %
def test_amendment_selection_newest_accepted_wins(): def test_amendment_selection_newest_accepted_wins():
rows = _two_years() rows = _two_years()
# an amendment to FY2026 FY restates revenue YTD higher, accepted later # an amendment to FY2026 FY restates revenue YTD higher, accepted later