Captures backend work already running on godstrument.pro but never committed: - auth.py: invite-only accounts + per-user presets (SQLite, scrypt, signed stateless sessions), mounted by hub.py at /api/* - hub.py: /api static+API handler, readonly public mode, full route spec in hello - socio-economic / market / fire / debt / crypto workers + normalize/transform - .gitignore: never commit godstrument_users.db* or auth_secret - test_fixes.py: framework-free self-check for the review fixes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
"""
|
|
world_econ.py — the cost of living. Inflation as pressure.
|
|
|
|
Pulls US CPI (consumer price index) from the Bureau of Labor Statistics (no key,
|
|
but rate-limited — so it polls rarely; CPI is monthly data anyway) and computes
|
|
the year-over-year inflation rate. Inflation is a quiet, grinding pressure — it
|
|
never trends toward zero, it just erodes. Good as a slow "tension" source in the
|
|
dark half of a set.
|
|
|
|
Emits:
|
|
/gs/econ/inflation year-over-year CPI change, percent (~0..10)
|
|
/gs/econ/cpi_mom latest month-over-month change, percent
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
import argparse
|
|
import json
|
|
import time
|
|
import urllib.request
|
|
|
|
from pythonosc.udp_client import SimpleUDPClient
|
|
|
|
URL = "https://api.bls.gov/publicAPI/v2/timeseries/data/CUUR0000SA0" # CPI-U all
|
|
UA = "Godstrument/1.0 (live instrument)"
|
|
|
|
|
|
def fetch():
|
|
req = urllib.request.Request(URL, headers={"User-Agent": UA})
|
|
with urllib.request.urlopen(req, timeout=30) as r:
|
|
rows = json.load(r)["Results"]["series"][0]["data"]
|
|
latest = rows[0]
|
|
idx = float(latest["value"])
|
|
# month-over-month (previous data point)
|
|
mom = ((idx / float(rows[1]["value"])) - 1) * 100 if len(rows) > 1 else 0.0
|
|
# year-over-year: same period one year earlier
|
|
yoy = 0.0
|
|
for row in rows:
|
|
if row["year"] == str(int(latest["year"]) - 1) and row["period"] == latest["period"]:
|
|
yoy = (idx / float(row["value"]) - 1) * 100
|
|
break
|
|
return yoy, mom, latest["periodName"] + " " + latest["year"]
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--host", default="127.0.0.1")
|
|
ap.add_argument("--port", type=int, default=9000)
|
|
ap.add_argument("--poll", type=float, default=21600.0, help="re-query every Ns (BLS is rate-limited)")
|
|
args = ap.parse_args()
|
|
|
|
client = SimpleUDPClient(args.host, args.port)
|
|
print(f"[econ] emitting /gs/econ/inflation|cpi_mom (US CPI) "
|
|
f"(re-query every {args.poll:g}s)")
|
|
|
|
yoy, mom, last = 0.0, 0.0, None
|
|
next_poll, retry = 0.0, 60.0
|
|
while True:
|
|
if time.time() >= next_poll:
|
|
try:
|
|
yoy, mom, label = fetch()
|
|
if label != last:
|
|
print(f" 📈 inflation {yoy:.2f}% YoY ({label}, {mom:+.2f}% MoM)")
|
|
last = label
|
|
next_poll, retry = time.time() + args.poll, 60.0
|
|
except Exception as e: # noqa
|
|
# back off on failure: BLS allows ~25 req/day unregistered, so a
|
|
# 10s retry-storm would exhaust the quota and lock us out all day
|
|
print(f"[econ] warn: {e}; retry in {retry:.0f}s")
|
|
next_poll = time.time() + retry
|
|
retry = min(retry * 2, args.poll)
|
|
client.send_message("/gs/econ/inflation", yoy)
|
|
client.send_message("/gs/econ/cpi_mom", mom)
|
|
time.sleep(10.0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|