#!/usr/bin/env python3 """The published Python model and the page's JavaScript model must agree.""" import json, pathlib, subprocess, sys, tempfile ROOT = pathlib.Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "pipeline")) import model # noqa: E402 BASE = {"supply": 1.31e9, "vol0": 46e9, "cagr": 0.3, "gross_bps_start": 15, "gross_bps_end": 12, "capture_start": 0.36, "capture_end": 0.45, "claim": 0.75, "l1_burn_usd": 1.5e6, "l1_growth": 0.1, "issuance_start": 0.025, "issuance_end": 0.016, "ramp_years": 3, "treasury_share": 0.1, "commission": 0.057, "discount": 0.15, "exit_multiple": 25, "l1_value": 1.4e9} CASES = [BASE, {**BASE, "cagr": -0.05, "claim": 0.5, "exit_multiple": 12, "ramp_years": 1}, {**BASE, "cagr": 0.7, "capture_end": 0.6, "claim": 1.0, "discount": 0.13}, {**BASE, "vol0": 1.0, "l1_value": 0.0, "l1_burn_usd": 0.0}] def js_values(cases): code = ("const m=require(process.argv[1]);const c=JSON.parse(process.argv[2]);" "console.log(JSON.stringify(c.map(p=>{const v=m.value(p);return {price:v.price,pv:v.pv_cash,t:v.pv_terminal,y5:v.y5_volume,imp:m.impliedVolume(p,4.38)}})))") out = subprocess.run(["node", "-e", code, str(ROOT / "docs" / "model.js"), json.dumps(cases)], capture_output=True, text=True, check=True) return json.loads(out.stdout) def test_parity(): js = js_values(CASES) for p, j in zip(CASES, js): py = model.value(p) assert abs(py["price"] - j["price"]) < 1e-9 assert abs(py["pv_cash"] - j["pv"]) < 1e-4 assert abs(py["pv_terminal"] - j["t"]) < 1e-4 imp = model.implied_volume(p, 4.38) if imp is None: assert j["imp"] is None else: assert abs(imp["cagr"] - j["imp"]["cagr"]) < 1e-6 def test_hand_check(): """One year of arithmetic done by hand, so a shared bug in both engines cannot pass.""" p = {**BASE, "cagr": 0.0, "gross_bps_start": 10, "gross_bps_end": 10, "capture_start": 0.5, "capture_end": 0.5, "claim": 1.0, "l1_burn_usd": 0.0, "l1_growth": 0.0, "issuance_start": 0.0, "issuance_end": 0.0, "exit_multiple": 10, "discount": 0.0, "l1_value": 0.0, "vol0": 1e9, "supply": 1e6} # 1e9 * 10 bps * 50% = 500,000 a year for 5 years + 10x exit = 7.5M, over 1M tokens = 7.5 assert abs(model.value(p)["price"] - 7.5) < 1e-9 def test_monotonic(): low, high = dict(BASE), dict(BASE) low["cagr"], high["cagr"] = 0.1, 0.5 assert model.value(high)["price"] > model.value(low)["price"] low, high = dict(BASE), dict(BASE) low["discount"], high["discount"] = 0.2, 0.1 assert model.value(high)["price"] > model.value(low)["price"] def test_implied_roundtrip(): q = dict(BASE) imp = model.implied_volume(q, 4.38) q["cagr"] = imp["cagr"] assert abs(model.value(q)["price"] - 4.38) < 1e-6 if __name__ == "__main__": for name, fn in list(globals().items()): if name.startswith("test_"): fn() print("ok", name)