surgebot: read-only /feed endpoint for the /surge dashboard

CORS-open GET /feed serving the paper book (equity, counters, open,
settled, skips, informed-set meta) — paper data only, nothing mutable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jaxperro
2026-07-21 15:29:12 -04:00
parent eeeed39e22
commit 1bfc91dd6a
2 changed files with 48 additions and 0 deletions
+8
View File
@@ -12,6 +12,14 @@ primary_region = "arn"
source = "surge" source = "surge"
destination = "/data" destination = "/data"
# read-only paper feed for jaxperro.com/surge (GET /feed, CORS-open)
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
[[restart]] [[restart]]
policy = "always" policy = "always"
+40
View File
@@ -288,9 +288,49 @@ def run_conn(tag, bot):
backoff = 2 backoff = 2
def serve_feed(bot, port=8080):
"""Read-only public feed for the /surge dashboard (paper data only —
nothing here can place an order or mutate state). CORS-open."""
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
class H(BaseHTTPRequestHandler):
def log_message(self, *a):
pass
def do_GET(self):
if self.path.split("?")[0] != "/feed":
self.send_response(404)
self.end_headers()
return
with bot.lock:
st = bot.state
body = json.dumps({
"mode": "paper", "updated": int(time.time()),
"bank": BANK, "equity": round(bot.equity(), 2),
"cash": round(st["cash"], 2),
"day": st["day"], "day_stake": st["day_stake"],
"stake_pct": STAKE_PCT, "event_cap": EVENT_CAP,
"flow_usd": FLOW_USD, "window_s": WINDOW_S,
"band": BAND, "counters": st["counters"],
"informed": bot.set_meta,
"open": [{**p, "asset": a} for a, p in st["open"].items()],
"settled": st["settled"][-200:],
"skips": st["skips"][-100:]}).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Cache-Control", "no-store")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
ThreadingHTTPServer(("0.0.0.0", port), H).serve_forever()
def main(): def main():
bot = Surge() bot = Surge()
bot.load_set() bot.load_set()
threading.Thread(target=serve_feed, args=(bot,), daemon=True).start()
for tag in ("a", "b"): for tag in ("a", "b"):
threading.Thread(target=run_conn, args=(tag, bot), daemon=True).start() threading.Thread(target=run_conn, args=(tag, bot), daemon=True).start()
last_set = time.time() last_set = time.time()