KarlQuant commited on
Commit
e95a0b7
·
verified ·
1 Parent(s): 1e76af5

Update ranker_logging.py

Browse files
Files changed (1) hide show
  1. ranker_logging.py +65 -1
ranker_logging.py CHANGED
@@ -238,7 +238,7 @@ class RankerLogger:
238
 
239
  def trade_open(self, trade_id: str, asset: str, direction: str, price: float, qty: float):
240
  """Log trade opening."""
241
- metadata = {"trade_id": trade_id, "price": price, "qty": qty}
242
  self._log(LogLevel.INFO, EventCategory.TRADE,
243
  f"TRADE OPENED | ID={trade_id} | Dir={direction} | Entry={price:.4f} | Qty={qty:.6f}",
244
  asset=asset, metadata=metadata)
@@ -332,6 +332,70 @@ class RankerLogger:
332
  "logs": entries
333
  }, f, indent=2)
334
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
 
336
  class RankerLogBridge:
337
  """
 
238
 
239
  def trade_open(self, trade_id: str, asset: str, direction: str, price: float, qty: float):
240
  """Log trade opening."""
241
+ metadata = {"trade_id": trade_id, "price": price, "qty": qty, "direction": direction}
242
  self._log(LogLevel.INFO, EventCategory.TRADE,
243
  f"TRADE OPENED | ID={trade_id} | Dir={direction} | Entry={price:.4f} | Qty={qty:.6f}",
244
  asset=asset, metadata=metadata)
 
332
  "logs": entries
333
  }, f, indent=2)
334
 
335
+ @staticmethod
336
+ def make_trade_ws_hook(ws_send_fn):
337
+ """
338
+ Factory for the on_event callback that forwards TRADE log entries to the
339
+ Executo Hub via WebSocket.
340
+
341
+ Usage in your executor space ranker:
342
+
343
+ import asyncio, json
344
+ from ranker_logging import RankerLogger
345
+
346
+ async def connect_to_hub():
347
+ # ws = your websockets/websocket-client connection to the hub
348
+ ranker_logger = RankerLogger(
349
+ name="QuasarAXRVI_V75",
350
+ on_event=RankerLogger.make_trade_ws_hook(
351
+ lambda payload: asyncio.create_task(ws.send(json.dumps(payload)))
352
+ )
353
+ )
354
+
355
+ Args:
356
+ ws_send_fn: callable(dict) → sends a dict as JSON to the hub WS publisher.
357
+ Can be a coroutine wrapper or sync function.
358
+ """
359
+ def _hook(entry: dict) -> None:
360
+ if entry.get("category") != "TRADE":
361
+ return
362
+ msg = entry.get("message", "")
363
+ meta = entry.get("metadata") or {}
364
+ ts = entry.get("timestamp", "")
365
+
366
+ if "TRADE OPENED" in msg:
367
+ payload = {
368
+ "type": "trade_opened",
369
+ "data": {
370
+ "trade_id": meta.get("trade_id"),
371
+ "asset": entry.get("asset"),
372
+ "direction": meta.get("direction", "?"),
373
+ "entry": meta.get("price"),
374
+ "qty": meta.get("qty", 0.0),
375
+ "opened_at": ts,
376
+ },
377
+ }
378
+ elif "TRADE CLOSED" in msg:
379
+ payload = {
380
+ "type": "trade_closed",
381
+ "data": {
382
+ "trade_id": meta.get("trade_id"),
383
+ "asset": entry.get("asset"),
384
+ "pnl": meta.get("pnl", 0.0),
385
+ "exit_price": meta.get("exit_price"),
386
+ "closed_at": ts,
387
+ },
388
+ }
389
+ else:
390
+ return
391
+
392
+ try:
393
+ ws_send_fn(payload)
394
+ except Exception:
395
+ pass # never let a WS error crash the ranker
396
+
397
+ return _hook
398
+
399
 
400
  class RankerLogBridge:
401
  """