Spaces:
Sleeping
Sleeping
| # app.py | |
| # | |
| # Hugging Face Space β Live U.S. Debt Clock | |
| # β’ Pulls the last 40 Treasury βDebt to the Pennyβ points | |
| # β’ Derives a $/sec rate from point-0 and point-30 (or falls back to the last | |
| # two distinct points when needed) | |
| # β’ Projects the current debt from the timestamp (00:01 UTC) of the latest | |
| # record all the way to *now*βno 12-hour guard | |
| # | |
| # Endpoints | |
| # / β simple text βrunningβ check | |
| # /api/debt β JSON { startingDebt, ratePerSecond, asOf } | |
| # /api/ping β lightweight uptime probe | |
| # | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| import os, time, threading, requests | |
| from flask import Flask, jsonify | |
| app = Flask(__name__) | |
| # βββββββββββββββββββ runtime state ββββββββββββββββββββ | |
| DEBT_STATE = { | |
| "debt_at_record": 0.0, # value at latest record date | |
| "record_time": 0.0, # epoch seconds for that record date (00:01 UTC) | |
| "rate_per_sec": 0.0, # $/s derived from chosen points | |
| "last_refresh": 0.0 | |
| } | |
| # βββββββββββββββββββ config βββββββββββββββββββββββββββ | |
| HORIZON = 30 # how many records back to measure the slope | |
| API = ( | |
| "https://api.fiscaldata.treasury.gov/services/api/fiscal_service/v2/" | |
| "accounting/od/debt_to_penny" | |
| f"?fields=record_date,tot_pub_debt_out_amt&sort=-record_date&page[size]={HORIZON+10}" | |
| # 10 extra records just in case identical values need skipping | |
| ) | |
| # βββββββββββββββββββ helpers ββββββββββββββββββββββββββ | |
| def load_debt_records(): | |
| r = requests.get(API, timeout=15) | |
| r.raise_for_status() | |
| return [ | |
| (item["record_date"], float(item["tot_pub_debt_out_amt"])) | |
| for item in r.json()["data"] | |
| ] # newest first | |
| def epoch_0001utc(date_str: str) -> float: | |
| """Convert YYYY-MM-DD to seconds since epoch at 00:01 UTC of that day.""" | |
| tm = time.strptime(date_str, "%Y-%m-%d") | |
| return time.mktime(tm) + 60 # add 60 s β 00:01 UTC | |
| # βββββββββββββββββββ background refresher ββββββββββββ | |
| def refresher(): | |
| while True: | |
| try: | |
| recs = load_debt_records() # newest first | |
| (d0_date, d0_val) = recs[0] | |
| # attempt the long-horizon slope | |
| candidate = recs[HORIZON] if len(recs) > HORIZON else None | |
| if candidate and candidate[1] != d0_val: | |
| (dk_date, dk_val) = candidate # point-30 | |
| else: | |
| # fall back to previous distinct point | |
| dk_date, dk_val = next( | |
| (d for d in recs[1:] if d[1] != d0_val), | |
| (None, None) | |
| ) | |
| if dk_date is None: | |
| raise ValueError("Could not find two distinct points") | |
| t0, tk = epoch_0001utc(d0_date), epoch_0001utc(dk_date) | |
| rate = (d0_val - dk_val) / (t0 - tk) # $/s (may be negative) | |
| DEBT_STATE.update( | |
| debt_at_record = d0_val, | |
| record_time = t0, | |
| rate_per_sec = rate, | |
| last_refresh = time.time() | |
| ) | |
| print( | |
| f"[refresh] latest={d0_date} debt={d0_val:,.2f} " | |
| f"rate={rate:,.2f}$/s horizon={t0 - tk:.0f}s" | |
| ) | |
| except Exception as e: | |
| print("Debt refresh error:", e) | |
| time.sleep(300) # five-minute cycle | |
| threading.Thread(target=refresher, daemon=True).start() | |
| # βββββββββββββββββββ routes ββββββββββββββββββββββββββ | |
| def root(): | |
| return "β Debt clock running", 200 | |
| def api_debt(): | |
| now = time.time() | |
| elapsed = max(0.0, now - DEBT_STATE["record_time"]) # **no 12-h guard** | |
| current = DEBT_STATE["debt_at_record"] + DEBT_STATE["rate_per_sec"] * elapsed | |
| return jsonify( | |
| startingDebt = current, | |
| ratePerSecond = DEBT_STATE["rate_per_sec"], | |
| asOf = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(now)) | |
| ) | |
| def api_ping(): | |
| return {"status": "ok"}, 200 | |
| # βββββββββββββββββββ main ββββββββββββββββββββββββββββ | |
| if __name__ == "__main__": | |
| port = int(os.environ.get("PORT", 7860)) | |
| app.run(host="0.0.0.0", port=port) | |