Issue 1361 — RecessionAlert CHARTS > Bitcoin

Offline provenance and fail-closed validation for the RecessionAlert Bitcoin contextual model suite. The selected page and adjacent hashed workbooks are inspected locally; no live request, credential, or private account data is used.

In [1]:
from pathlib import Path
import hashlib
import json
import sqlite3

root = Path.cwd()
while root != root.parent and not (root / 'data' / 'recessionalert.sqlite').exists():
    root = root.parent
spec = json.loads((root / 'research/findings/specs/recessionalert-bitcoin.json').read_text(encoding='utf-8'))
page = spec['source']['page']
db = root / 'data' / 'recessionalert.sqlite'
connection = sqlite3.connect(f'file:{db}?mode=ro', uri=True)
connection.execute('PRAGMA query_only=ON')
row = connection.execute('SELECT sha256, content_length, fetched_at, body FROM pages WHERE url=?', (page['url'],)).fetchone()
target_asset_rows = connection.execute('SELECT COUNT(*) FROM assets WHERE page_url=? OR url=?', (page['url'], page['url'])).fetchone()[0]
crawl_count = connection.execute('SELECT COUNT(*) FROM crawl_log WHERE url=?', (page['url'],)).fetchone()[0]
connection.close()
assert row is not None
page_digest = 'sha256:' + hashlib.sha256(row[3]).hexdigest()
assert page_digest == row[0] == page['sha256']
assert row[1] == page['content_length'] == 116181
assert row[2] == page['fetched_at'] == '2026-08-22T23:39:03Z'
assert target_asset_rows == 0
assert crawl_count == len(spec['source']['crawl_revision_history']) == 5
workbook_root = root / 'research/artifacts/recessionalert'
for workbook in sorted(workbook_root.glob('*.xlsx')):
    digest = 'sha256:' + hashlib.sha256(workbook.read_bytes()).hexdigest()
    assert digest == next(item for item in spec['source']['adjacent_workbook_assets']['sha256'] if item.removeprefix('sha256:') == workbook.stem)
    print('workbook_sha256', workbook.name, digest)
print('page_sha256', page_digest)
print('page_content_length', row[1])
print('page_fetched_at', row[2])
print('target_asset_rows', target_asset_rows)
print('same_url_crawl_vintages', crawl_count)
print('source_series_linked', spec['provenance']['adjacent_workbook_series_linked'])
print('article_timestamp', spec['publication_lag']['article_timestamp'])
print('publication_lag', spec['publication_lag']['release_lag_status'])
print('decision', spec['disposition'])
workbook_sha256 435d142f7e8851a740c78a3d24db6bb15930b21a861cb5520d0a494e6575dced.xlsx sha256:435d142f7e8851a740c78a3d24db6bb15930b21a861cb5520d0a494e6575dced
workbook_sha256 b3c8587608044073d3ed9246a12402a184267fae87cb147a5028e720c6e6493c.xlsx sha256:b3c8587608044073d3ed9246a12402a184267fae87cb147a5028e720c6e6493c
workbook_sha256 c01364504b43f157c9fd58752b2c8c9774318f04542f736198ce74cf4d0350d4.xlsx sha256:c01364504b43f157c9fd58752b2c8c9774318f04542f736198ce74cf4d0350d4
workbook_sha256 fc2be5f1fc2a2e38949ae566f6e8cb4699a95562975a498fb5a53510cc40d67c.xlsx sha256:fc2be5f1fc2a2e38949ae566f6e8cb4699a95562975a498fb5a53510cc40d67c
page_sha256 sha256:48ab3995ad8abafa4060fa4a72dd658607ddd205dd28dc1e040abe7ab38b2139
page_content_length 116181
page_fetched_at 2026-08-22T23:39:03Z
target_asset_rows 0
same_url_crawl_vintages 5
source_series_linked False
article_timestamp undisclosed
publication_lag unknown
decision insufficient_evidence

Disclosed rule and causal boundary

The page documents BOCA-3/4 accumulation context, technical indicators updated every 30 minutes, Mayer/Puell/Power Law formulas, and daily correction/rally probability context. Mayer thresholds are recorded exactly as disclosed, while the source explicitly says the probability model is not an actionable signal.

No source-linked numeric component series, release timestamp, common state machine, or portfolio execution map is captured. Unknown inputs remain unavailable; any future overlay requires point-in-time inputs and at least one available-bar execution lag. Same-close/lookahead is unsupported.