Download engine/units.py from s-ttp/crucible: direct link, hf CLI and curl.
- Browser
- Download file 11.3 kB
-
https://huggingface.co/spaces/s-ttp/crucible/resolve/main/engine/units.py
- Command line
-
hf download hf://spaces/s-ttp/crucible/engine/units.py
-
curl -L -o units.py https://huggingface.co/spaces/s-ttp/crucible/resolve/main/engine/units.py
11.3 kB
| """One canonical representation and one formatting path for every rate-like value. | |
| The defect this module exists to make impossible: the same canonical number, a model-implied | |
| 12-month return of 0.2375, rendered as "+23.8%" on the cover and "+0.2%" in the synthesis | |
| paragraph, because one call site multiplied by 100 before appending "%" and the other did not. | |
| Nothing in the code declared which convention a field used, so each renderer guessed. | |
| Rules | |
| ----- | |
| * Every rate-like field declares its storage unit in ``FIELD_UNITS``. The unit is never inferred | |
| from the variable name at a call site. | |
| * A rate-like value is rendered only through ``format_percent`` / ``Pct``. Appending a literal | |
| "%" to a bare float is forbidden and is caught by ``scan_source_for_adhoc_percent``. | |
| * ``parse_percent(format_percent(x)) ≈ x`` for every storage unit, which is what lets the final | |
| render audit read a displayed string back and compare it with the canonical value. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from dataclasses import dataclass | |
| # ── storage units ───────────────────────────────────────────────────────────────────── | |
| DECIMAL_FRACTION = "DECIMAL_FRACTION" # 0.2375 means 23.75% | |
| PERCENT_NUMBER = "PERCENT_NUMBER" # 23.75 means 23.75% | |
| BASIS_POINTS = "BASIS_POINTS" # 2375 means 23.75% | |
| RATIO = "RATIO" # 1.35 means 1.35x — NOT a percentage | |
| UNITS = (DECIMAL_FRACTION, PERCENT_NUMBER, BASIS_POINTS, RATIO) | |
| _TO_DECIMAL = {DECIMAL_FRACTION: 1.0, PERCENT_NUMBER: 0.01, BASIS_POINTS: 0.0001} | |
| class UnitError(ValueError): | |
| """A rate-like value was used without a declared, convertible unit.""" | |
| # ── the declared storage semantics of every rate-like field ─────────────────────────── | |
| # Adding a rate-like field without an entry here is a test failure, not a silent default. | |
| FIELD_UNITS = { | |
| # returns | |
| "expected_return": DECIMAL_FRACTION, | |
| "low_estimate": DECIMAL_FRACTION, | |
| "high_estimate": DECIMAL_FRACTION, | |
| "headline_return": DECIMAL_FRACTION, | |
| "model_implied_return": DECIMAL_FRACTION, | |
| "pm_return": DECIMAL_FRACTION, | |
| "scenario_ev": DECIMAL_FRACTION, | |
| "bear_return": DECIMAL_FRACTION, | |
| "neutral_return": DECIMAL_FRACTION, | |
| "bull_return": DECIMAL_FRACTION, | |
| "value_implied": DECIMAL_FRACTION, | |
| "upside": DECIMAL_FRACTION, | |
| "downside": DECIMAL_FRACTION, | |
| "discount_to_price": DECIMAL_FRACTION, | |
| "premium_to_price": DECIMAL_FRACTION, | |
| "return_3m": DECIMAL_FRACTION, | |
| "return_12m": DECIMAL_FRACTION, | |
| # growth | |
| "eps_growth": DECIMAL_FRACTION, | |
| "analyst_upside": DECIMAL_FRACTION, | |
| "margin_trend": DECIMAL_FRACTION, | |
| "rev_growth": DECIMAL_FRACTION, | |
| "revenue_growth": DECIMAL_FRACTION, | |
| "fcf_growth": DECIMAL_FRACTION, | |
| "terminal_growth": DECIMAL_FRACTION, | |
| "consensus_growth": DECIMAL_FRACTION, | |
| # margins | |
| "op_margin_current": DECIMAL_FRACTION, | |
| "op_margin_predicted": DECIMAL_FRACTION, | |
| "operating_margin": DECIMAL_FRACTION, | |
| "operating_margin_ttm": DECIMAL_FRACTION, | |
| "operating_margin_forward_12m": DECIMAL_FRACTION, | |
| "operating_margin_story_maturity": DECIMAL_FRACTION, | |
| "net_margin": DECIMAL_FRACTION, | |
| "net_margin_forward_implied": DECIMAL_FRACTION, | |
| "gross_margin": DECIMAL_FRACTION, | |
| "fcf_margin": DECIMAL_FRACTION, | |
| "margin_change": DECIMAL_FRACTION, | |
| # yields, rates | |
| "dividend_yield": DECIMAL_FRACTION, | |
| "fcf_yield": DECIMAL_FRACTION, | |
| "sales_yield": DECIMAL_FRACTION, | |
| "earnings_yield": DECIMAL_FRACTION, | |
| "risk_free_rate": DECIMAL_FRACTION, | |
| "equity_risk_premium": DECIMAL_FRACTION, | |
| "discount_rate": DECIMAL_FRACTION, | |
| "cost_of_equity": DECIMAL_FRACTION, | |
| "wacc": DECIMAL_FRACTION, | |
| "tax_rate": DECIMAL_FRACTION, | |
| "effective_tax_rate": DECIMAL_FRACTION, | |
| "roe": DECIMAL_FRACTION, | |
| "roic": DECIMAL_FRACTION, | |
| "nim": DECIMAL_FRACTION, | |
| "cet1": DECIMAL_FRACTION, | |
| "market_share": DECIMAL_FRACTION, | |
| # probabilities and confidence | |
| "p_bear": DECIMAL_FRACTION, | |
| "p_neutral": DECIMAL_FRACTION, | |
| "p_bull": DECIMAL_FRACTION, | |
| "probability": DECIMAL_FRACTION, | |
| "confidence": DECIMAL_FRACTION, | |
| "beat_rate": DECIMAL_FRACTION, | |
| "direction_accuracy": DECIMAL_FRACTION, | |
| "rank_correlation": RATIO, # a correlation is not a percentage | |
| # risk | |
| "volatility": DECIMAL_FRACTION, | |
| "drawdown": DECIMAL_FRACTION, | |
| "max_drawdown": DECIMAL_FRACTION, | |
| "tracking_error": DECIMAL_FRACTION, | |
| # surprise | |
| "avg_surprise": PERCENT_NUMBER, # providers report surprise as a percent number | |
| "surprise_pct": PERCENT_NUMBER, | |
| # spreads | |
| "spread_bps": BASIS_POINTS, | |
| "credit_spread_bps": BASIS_POINTS, | |
| # multiples — ratios, never rendered with a percent sign | |
| "pe_forward": RATIO, | |
| "pe_trailing": RATIO, | |
| "peg_forward": RATIO, | |
| "ev_ebitda": RATIO, | |
| "price_to_book": RATIO, | |
| "debt_to_equity": RATIO, | |
| } | |
| def unit_of(field, default=None): | |
| """The declared storage unit of a field. Raises rather than guessing when undeclared.""" | |
| u = FIELD_UNITS.get(field, default) | |
| if u is None: | |
| raise UnitError(f"field '{field}' has no declared storage unit — add it to FIELD_UNITS") | |
| return u | |
| def to_decimal(value, unit=DECIMAL_FRACTION): | |
| """Convert any declared rate unit to a decimal fraction.""" | |
| if value is None: | |
| return None | |
| if unit == RATIO: | |
| raise UnitError("a RATIO is not a percentage and has no decimal-fraction form") | |
| try: | |
| f = _TO_DECIMAL[unit] | |
| except KeyError: | |
| raise UnitError(f"unknown storage unit {unit!r}") from None | |
| return float(value) * f | |
| # ── the one percentage type ─────────────────────────────────────────────────────────── | |
| class Pct: | |
| """A rate, held as a decimal fraction whatever unit it arrived in.""" | |
| decimal: float | |
| def of(cls, value, unit=DECIMAL_FRACTION): | |
| d = to_decimal(value, unit) | |
| return None if d is None else cls(float(d)) | |
| def of_field(cls, field, value): | |
| return cls.of(value, unit_of(field)) | |
| def as_decimal(self): | |
| return self.decimal | |
| def as_percent_number(self): | |
| return self.decimal * 100.0 | |
| def as_basis_points(self): | |
| return self.decimal * 10000.0 | |
| def format_percent(self, decimals=1, sign=False): | |
| return format_percent(self.decimal, decimals=decimals, sign=sign) | |
| def format_basis_points(self, decimals=0): | |
| return f"{self.decimal * 10000.0:,.{decimals}f} bps" | |
| def format_ratio(self, decimals=4): | |
| return f"{self.decimal:.{decimals}f}" | |
| def __str__(self): | |
| return self.format_percent() | |
| def format_percent(value, decimals=1, sign=False, unit=DECIMAL_FRACTION, none="n/a"): | |
| """The only way a percentage becomes user-visible text. | |
| ``format_percent(0.2375, sign=True) == "+23.8%"``. Passing a percent number by mistake is not | |
| silently accepted: declare the unit instead — ``format_percent(23.75, unit=PERCENT_NUMBER)``. | |
| """ | |
| if isinstance(value, Pct): | |
| value, unit = value.decimal, DECIMAL_FRACTION | |
| if value is None: | |
| return none | |
| d = to_decimal(value, unit) * 100.0 | |
| if sign: | |
| # a value that rounds to zero prints without a misleading direction | |
| if round(d, decimals) == 0: | |
| return f"{0.0:.{decimals}f}%" | |
| return f"{d:+.{decimals}f}%" | |
| return f"{d:.{decimals}f}%" | |
| def format_pp(value, decimals=1, sign=True, unit=DECIMAL_FRACTION, none="n/a"): | |
| """A difference between two percentages, rendered in percentage points.""" | |
| if isinstance(value, Pct): | |
| value, unit = value.decimal, DECIMAL_FRACTION | |
| if value is None: | |
| return none | |
| d = to_decimal(value, unit) * 100.0 | |
| return f"{d:+.{decimals}f} pp" if sign else f"{d:.{decimals}f} pp" | |
| def format_ratio(value, decimals=2, suffix="x", none="n/a"): | |
| """A multiple. Never carries a percent sign.""" | |
| if value is None: | |
| return none | |
| return f"{float(value):.{decimals}f}{suffix}" | |
| _PCT_RE = re.compile(r"([+-]?\d{1,3}(?:,\d{3})*(?:\.\d+)?)\s*%") | |
| _BPS_RE = re.compile(r"([+-]?\d{1,3}(?:,\d{3})*(?:\.\d+)?)\s*bps", re.I) | |
| # ── deterministic ranges ────────────────────────────────────────────────────────────── | |
| class RangeClaim: | |
| """A numeric interval derived from registered endpoint claims, never invented in prose.""" | |
| lower: float | |
| upper: float | |
| semantic_type: str = DECIMAL_FRACTION | |
| claim_id: str | None = None | |
| lower_claim: str | None = None | |
| upper_claim: str | None = None | |
| label: str = "" | |
| def from_endpoints(cls, a, b, semantic_type=DECIMAL_FRACTION, **kw): | |
| """Order-independent: the caller supplies two endpoint values, not a pre-sorted pair.""" | |
| if a is None or b is None: | |
| return None | |
| lo, hi = (a, b) if a <= b else (b, a) | |
| return cls(float(lo), float(hi), semantic_type, **kw) | |
| def magnitude(self): | |
| """The interval of absolute sizes — what "11–14% below price" states.""" | |
| a, b = abs(self.lower), abs(self.upper) | |
| return (min(a, b), max(a, b)) | |
| def format_percent_range(self, decimals=0, absolute=False): | |
| lo, hi = self.magnitude() if absolute else (self.lower, self.upper) | |
| u = self.semantic_type | |
| return f"{format_percent(lo, decimals, unit=u)}–{format_percent(hi, decimals, unit=u)}".replace("%–", "–") | |
| def format_currency_range(self, decimals=2, symbol="$"): | |
| lo, hi = (self.lower, self.upper) | |
| return f"{symbol}{lo:,.{decimals}f}–{symbol}{hi:,.{decimals}f}" | |
| def contains(self, value, tol=0.005): | |
| return value is not None and (self.lower - tol) <= value <= (self.upper + tol) | |
| _RANGE_PCT_RE = re.compile(r"(\d{1,3}(?:\.\d+)?)\s*[–-]\s*(\d{1,3}(?:\.\d+)?)\s*%") | |
| _RANGE_CUR_RE = re.compile(r"\$(\d[\d,]*(?:\.\d+)?)\s*[–-]\s*\$?(\d[\d,]*(?:\.\d+)?)") | |
| # ── guard against the defect returning ──────────────────────────────────────────────── | |
| _ADHOC = re.compile(r"""\{[^{}]*?:[+ ]?[,]?\.\d+f\}\s*%""") | |
| def scan_source_for_adhoc_percent(source, allow_marker="# pct-ok"): | |
| """Report f-string sites that append a literal '%' to a formatted float. | |
| Such a site re-implements ``format_percent`` and is where the unit convention silently | |
| diverges. A line may opt out with a trailing ``# pct-ok`` marker when the value is genuinely | |
| already a percent number from an external source. | |
| """ | |
| hits = [] | |
| for i, line in enumerate(source.splitlines(), 1): | |
| if allow_marker in line: | |
| continue | |
| if _ADHOC.search(line): | |
| hits.append((i, line.strip())) | |
| return hits | |