Methodology & policies.
An index is a promise about a number. These are the promises — including the ones that are inconvenient. Methodology version 1, in force since 23 Aug 2026.
The 30-day notice rule.
The methodology is versioned and frozen per version. Any change that could move the published level is announced here, with its effective date, at least 30 days before it takes effect — and the old version stays on this page afterwards.
Why it matters: without it, a number that moves is indistinguishable from a rule that moved. Anyone who quotes v1 today should be able to check in a year what v1 meant, and see that we did not quietly redefine it underneath them.
Exception, stated so it cannot be abused: a change that corrects an outright error is a correction, not a methodology change, and follows the rule below instead. We will always say which one we think it is, and show the numbers both ways.
Corrections.
We will get a number wrong eventually. When we do:
- The correction is published on this page, with the date, what was wrong, the affected range, and the size of the effect.
- The historical tape is not silently rewritten. If a past row was wrong, the correction is appended and both values remain visible — because the tape is anchored nightly into Bitcoin and quietly editing it would break the one proof that makes it worth anything.
- If a correction moves a published index level by more than 0.5%, we say so at the top of the index page, not only here.
- Anyone can report one. There is no form and no account — the source is open and every figure resolves to a row you can check.
time.mktime() reads a struct_time as local time and
silently ignored the parsed +0000, so on a UTC+8 build host every day boundary
moved eight hours. The tape column is named snapshot_ts_utc_epoch, so anyone
grouping by true UTC computed a different row set and a different root — and would
reasonably have concluded the anchoring claim was false.
Effect: 2026-08-23 covered 7,085 rows where true UTC covers 12,301. No index level
moved; the fault was in which rows a day contained, not in any price.
Found by: an external reviewer's agent, reproducing our roots from published data alone.
Fix: boundaries now use calendar.timegm, which no host timezone can
influence. The superseded roots are kept and marked in
roots.jsonl rather than removed, and every root record now
states the boundary, the leaf rule, the sort order, the odd-node rule and the proof URL, so
none of it has to be guessed.
Sealed days, and why a rolling file was not enough.
Check it yourself in one command.
curl -sO https://compute.pangle.online/verify.py && python3 verify.py —
stdlib only, imports nothing from us, re-derives every published number from the files. It
pins each sha256, rebuilds each sealed file byte-for-byte from its own rows, rebuilds every
Merkle root and checks the chain between days. If it prints a mismatch, we are wrong, and we
would rather you found it than not. It exits non-zero so you can run it on a timer.
Every anchored day exists as its own file, written once and never again, alongside a manifest that addresses the sealed tape, the root file and the OpenTimestamps proof by sha256. Start at /data/days/index.json.
This replaced a genuine defect rather than adding a nicety. The tape was one rolling, mutable file, and a verifier who fetched a current roots file against a cached copy of the tape hashed a different set of rows and correctly concluded our claim was false. We fixed the cache headers first; that was treating the symptom. No cache lifetime can make a moving file agree with a fixed root. A sealed day cannot go stale because it cannot move, and once you have pinned it by hash, nothing a cache, a mirror or a proxy does can change what you are checking. The rolling file only has to be right about today.
If you are verifying from a script, send a User-Agent. The edge blocks the default
Python-urllib/x.y across everything except /api/ and
/llms.txt — measured, not assumed — and returns 403 with no explanation
— that string is a known scanner signature and the block is not ours to lift. Any other
value works, including one you invent. curl, python-requests and
browsers are unaffected. We would rather tell you than have you conclude the files are missing.
Reproducible and correct are two separate checks, and this is the clearest lesson anyone has handed us. The reviewer reproduced our roots faithfully — the method was documented, the arithmetic was right — and the conclusion was still wrong, because the documented method was the bug wearing a convention's clothes. Reproducibility shows the roots match the tape under a stated method. It does not show the method is the intended one. We publish both: the method in every root record, and the corrections above when the method itself was wrong.
If we stop publishing.
Most indices never say what happens if they die, which is exactly when people need to know.
- The tape and index history are CC BY 4.0 and already mirrored publicly. That licence is irrevocable — if this site disappears tomorrow, everything published up to that point stays usable by anyone.
- If publication ceases deliberately, we will announce it here 30 days ahead and leave the final dataset and its anchor proofs in place.
- If it ceases undeliberately — we run out of money, the box dies — the public mirrors and the nightly anchors are the answer. They are designed so continuity does not depend on us being around.
- We will not sell the series into a paywall retroactively. What has been published free stays free; the licence has already made that irreversible, and admitting it costs us nothing.
IOSCO self-assessment, honestly.
IOSCO's Principles for Financial Benchmarks are the global standard for how an index should be run. We are a small open project, not a regulated administrator, and we do not meet all of them. A self-assessment that admits gaps is worth more than a compliance claim nobody audited, so here is where we actually stand.
| Principle | Status | Where we actually are |
|---|---|---|
| Methodology published | Meets | Published in full, versioned, on this page and in every API response. |
| Data sufficiency — based on observable transactions | Structurally cannot | Nobody in this market publishes fill data, including us. The index is built on listed asks, and every page says so. This is the single biggest gap and it cannot be closed by effort. |
| Transparency of determination | Meets | Every figure resolves to an open row in the tape; the chaining rule is stated and the source is AGPL. |
| Changes — notice and consultation | Partly | 30-day notice is committed above. There is no formal consultation process and no stakeholder committee — there are no stakeholders yet. |
| Integrity — audit trail | Meets | Nightly Merkle roots chained and stamped into Bitcoin; reproducible by a stranger from the published CSV. See the tape. |
| Conflicts of interest | Partly | Fee is zero and stated in every API response; outbound links may carry referral tags, disclosed. We do not resell compute, so we have no book to talk. But there is no independent oversight function — it is one operator. |
| Control framework / internal oversight | Structurally cannot | No separate control function exists. Mitigation is that everything is open and externally verifiable rather than internally supervised. |
| Accountability — complaints and records | Partly | Corrections policy above and an open record. No formal complaints procedure, no retained audit files beyond the public tape. |
| Source concentration disclosed | Meets | Published live at /coverage/, including the ex-largest-feed continuity case, pre-committed. |
Read that table as a map of where to distrust us, not as a badge. The two red rows are real and we are not going to pretend otherwise: this is an index of asks, run by one operator, and it is auditable precisely because we cannot ask you to take our word for anything.
Where the data comes from and how concentrated it is: /coverage/. The index and its chaining rule: /spot/. The tape and its anchor proofs: /data/.