Spaces:
Sleeping
Sleeping
File size: 4,803 Bytes
2c1c4d5 1320d43 d2180f1 2c1c4d5 7ac8c92 2c1c4d5 f9eb3ae 2c1c4d5 f9eb3ae 7ac8c92 d2180f1 1320d43 7ac8c92 36d8afc 1320d43 2c1c4d5 1320d43 2c1c4d5 1320d43 2c1c4d5 f9eb3ae 2c1c4d5 1320d43 f9eb3ae d2180f1 2c1c4d5 f9eb3ae 2c1c4d5 f9eb3ae 1320d43 d2180f1 1320d43 d2180f1 1320d43 d2180f1 1320d43 d2180f1 1320d43 36d8afc 2c1c4d5 d2180f1 1320d43 2c1c4d5 2fbf000 f9eb3ae 2c1c4d5 2fbf000 7ac8c92 f9eb3ae 2c1c4d5 f9eb3ae 2c1c4d5 5819bad 2c1c4d5 2fbf000 5819bad 2c1c4d5 1320d43 d2180f1 1320d43 2c1c4d5 1320d43 2c1c4d5 f9eb3ae 2c1c4d5 f9eb3ae 2c1c4d5 2c56e40 5819bad |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# 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 ββββββββββββββββββββββββββ
@app.route("/")
def root():
return "β
Debt clock running", 200
@app.route("/api/debt")
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))
)
@app.route("/api/ping")
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)
|