File size: 4,914 Bytes
abe1744
 
 
 
 
1367f8f
abe1744
 
 
81d9c63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
---
title: K1RL QUASAR Executo Hub
emoji: πŸ›°οΈ
colorFrom: indigo
colorTo: blue
sdk: docker
pinned: false
---

# K1RL QUASAR β€” Executo Hub

**Central WebSocket hub for the K1RL QUASAR system.**  
Receives live training and voting metrics from all Asset Spaces, normalizes them, and broadcasts snapshots to the Ranker Space in real time.

---

## Architecture Role

```
Asset Space A ──┐
Asset Space B ──┼──► /ws/publish/{space_name} ──► HUB ──► /ws/subscribe ──► Ranker Space
Asset Space C β”€β”€β”˜                                   β”‚
                                                    └──► /rankings  (REST fallback)
```

The hub sits between publishers (Asset Spaces) and subscribers (Ranker Space). It is **strictly one-way** β€” the hub never writes back to publishers, and subscribers never send data to publishers.

---

## What This Space Does

- Accepts WebSocket connections from Asset Spaces on `/ws/publish/{space_name}`
- Accepts WebSocket connections from the Ranker Space on `/ws/subscribe`
- Validates and normalizes every inbound payload against a strict data model
- Stores the **latest snapshot only** per asset (no history)
- Broadcasts each update immediately to all connected subscribers
- Serves a live dashboard at `/` and a REST fallback at `/rankings`

---

## Endpoints

| Endpoint | Protocol | Direction | Description |
|---|---|---|---|
| `/ws/publish/{space_name}` | WebSocket | Asset Space β†’ Hub | Publishers send metrics here |
| `/ws/subscribe` | WebSocket | Hub β†’ Ranker | Subscribers receive broadcasts here |
| `/` | HTTP GET | β€” | Live dashboard UI |
| `/rankings` | HTTP GET | β€” | Latest snapshot for all assets |
| `/metrics/{space_name}` | HTTP GET | β€” | Latest snapshot for one asset |
| `/health` | HTTP GET | β€” | Hub health and publisher status |
| `/api/state` | HTTP GET | β€” | Full state polled by dashboard every 2s |

---

## Data Model

Only these fields are permitted through the hub. All others are **silently dropped**.

**Training**
```
training_steps    int
actor_loss        float
critic_loss       float
avn_loss          float
avn_accuracy      float  (0.0 – 1.0)
```

**Voting**
```
dominant_signal   str    ("BUY" | "SELL" | "NEUTRAL")
buy_count         int
sell_count        int
last_price        float
signal_source     str
```

---

## Accepted Publisher Message Types

Asset Spaces may send any of the following JSON message formats:

```jsonc
// Combined payload
{ "type": "metrics", "training": { ... }, "voting": { ... } }

// Training only
{ "type": "training", "data": { ... } }

// Voting only
{ "type": "voting", "data": { ... } }

// Keep-alive (silently acknowledged, no reply)
{ "type": "heartbeat" }
{ "type": "identify", "space": "space-name" }
{ "type": "ping" }
```

---

## Subscriber Message Types

Newly connected subscribers receive a full current state dump, then live updates as they arrive:

```jsonc
// Sent once on connection
{ "type": "initial_state", "snapshots": { ... }, "hub_timestamp": 1234567890.0 }

// Sent on every inbound publish
{ "type": "metrics_update", "space_name": "...", "snapshot": { ... }, "hub_timestamp": 1234567890.0 }
```

---

## AXRVI Ranking Formula

The `/rankings` and `/api/state` endpoints rank assets using:

```
signal_confidence = max(buy_count, sell_count) / (buy_count + sell_count)
score             = signal_confidence - avn_accuracy
```

Assets are sorted **descending by score**.

---

## Connecting an Asset Space

Asset Spaces connect using `log_metrics_reader.py`. The hub URL is resolved automatically from the `SPACE_ID` environment variable β€” no configuration is needed inside the asset space files.

The hardcoded target for all asset spaces is:

```
wss://karlquant-quasar-executo.hf.space/ws/publish/{space_name}
```

If the hub restarts, asset spaces **auto-reconnect within 30 seconds** via the built-in exponential back-off in `AssetSpacePublisher._run_loop`. No intervention is needed.

---

## Deploying a New Hub Version

To update the hub without triggering any asset space restarts:

1. Upload the new `websocket_hub.py` to **this Space only**
2. This Space restarts and begins accepting connections on the same URL
3. Asset spaces detect the disconnection and reconnect automatically

No changes are needed to `log_metrics_reader.py` or any asset space env vars.

---

## Files

| File | Purpose |
|---|---|
| `websocket_hub.py` | Hub server β€” FastAPI + WebSocket engine |
| `hub_dashboard.html` | Live dashboard UI served at `/` |
| `requirements.txt` | `fastapi`, `uvicorn`, `websockets` |

---

## Runtime

| Setting | Value |
|---|---|
| Default port | `7860` (override via `PORT` env var) |
| Dashboard HTML path | Override via `DASHBOARD_HTML` env var |
| Host | `0.0.0.0` |

---

## Version

`v2.0-arch-strict` β€” strict data model, event-driven broadcast, deep-copy safe ingestion pipeline.