Speed bot v1: REST polling, MLX model, standardized across all infra. WebSocket WIP.
This commit is contained in:
62
speed_bot.py
62
speed_bot.py
@@ -18,7 +18,7 @@ MODEL = "qwen3.5:4b-mlx"
|
||||
|
||||
# ── Auth (RSA-PSS-SHA256, same as existing bot) ──
|
||||
KEY_PATH = os.path.expanduser("~/kalshi-bot/kalshi_private_key.pem")
|
||||
KEY_ID = "28d5876b"
|
||||
KEY_ID = "28d5876b-2ece-4aa3-aa17-ec96e1e706eb"
|
||||
|
||||
with open(KEY_PATH, "rb") as f:
|
||||
PK = serialization.load_pem_private_key(f.read(), password=None)
|
||||
@@ -62,6 +62,7 @@ Vote UP DOWN or SKIP. Respond ONLY with JSON: {{"vote":"UP|DOWN|SKIP","conf":0.0
|
||||
try:
|
||||
r = requests.post(f"{OLLAMA_URL}/api/generate",
|
||||
json={"model": MODEL, "prompt": prompt, "stream": False,
|
||||
"think": False,
|
||||
"options": {"temperature": 0.15, "num_predict": 40}},
|
||||
timeout=8, proxies={"http": None, "https": None})
|
||||
txt = r.json().get("response", "")
|
||||
@@ -231,33 +232,52 @@ class SpeedBot:
|
||||
|
||||
def run(self):
|
||||
self.running = True
|
||||
print(f"[speed-{self.coin}] Starting speed bot (dry_run={self.dry_run}, model={MODEL})")
|
||||
last_tick_ts = 0
|
||||
print(f"[speed-{self.coin}] Starting (dry_run={self.dry_run}, model={MODEL}, REST mode)")
|
||||
|
||||
# Warm the MLX model
|
||||
try:
|
||||
requests.post(f"{OLLAMA_URL}/api/generate",
|
||||
json={"model": MODEL, "prompt": "hi", "stream": False,
|
||||
"think": False, "keep_alive": "30m",
|
||||
"options": {"num_predict": 5}},
|
||||
timeout=30, proxies={"http": None, "https": None})
|
||||
print(f"[speed-{self.coin}] MLX model warm")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
while self.running:
|
||||
try:
|
||||
self.ws = websocket.WebSocketApp(
|
||||
KALSHI_WS,
|
||||
header=self._ws_headers(),
|
||||
on_open=self.on_open,
|
||||
on_message=self.on_message,
|
||||
on_error=self.on_error,
|
||||
on_close=self.on_close,
|
||||
)
|
||||
self.ws.run_forever(ping_interval=30, ping_timeout=10)
|
||||
# REST polling (WebSocket auth WIP)
|
||||
markets = get_open_markets()
|
||||
our_markets = [m for m in markets if self.coin in m.get("ticker", "")]
|
||||
|
||||
for mkt in our_markets[:1]: # Trade the first open market
|
||||
ticker = mkt["ticker"]
|
||||
mkt_data = get_ticker(ticker)
|
||||
mkt_data = mkt_data.get("market", mkt_data)
|
||||
price = float(mkt_data.get("last_price", 0) or mkt_data.get("yes_bid", 0) or 0)
|
||||
|
||||
if price > 0:
|
||||
self.prices.append(price)
|
||||
self.db.execute("INSERT INTO ticks VALUES (?,?,?)",
|
||||
(time.time(), price, mkt_data.get("volume", 0) or 0))
|
||||
self.db.commit()
|
||||
|
||||
# Decision check
|
||||
now = time.time()
|
||||
if now - self.last_decision >= self.decision_cooldown and len(self.prices) >= 20:
|
||||
self.last_decision = now
|
||||
self._decide(ticker, price)
|
||||
|
||||
time.sleep(5) # Poll every 5 seconds
|
||||
|
||||
except Exception as e:
|
||||
print(f"[speed-{self.coin}] Reconnecting in 5s: {e}")
|
||||
print(f"[speed-{self.coin}] Loop error: {e}")
|
||||
time.sleep(5)
|
||||
|
||||
def _ws_headers(self):
|
||||
ts = str(int(time.time() * 1000))
|
||||
path = "/trade-api/ws/v2"
|
||||
msg = f"{ts}GET{path}".encode()
|
||||
sig = base64.b64encode(hmac.HMAC(KEY, msg, hashlib.sha256).digest()).decode()
|
||||
return {
|
||||
"KALSHI-ACCESS-KEY": KEY_ID,
|
||||
"KALSHI-ACCESS-SIGNATURE": sig,
|
||||
"KALSHI-ACCESS-TIMESTAMP": ts,
|
||||
}
|
||||
return sign("GET", "/trade-api/ws/v2")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user