RayMelius Claude Sonnet 4.6 commited on
Commit
eb6b6ff
Β·
1 Parent(s): b5d1ef5

Update README: message flow chart, full deployment guide, project structure

Browse files

- ASCII architecture overview (always renders) + Mermaid message flow diagram
- Document all 10 securities with names and start prices
- Deployment: HF live demo, deploy-your-own Space (step-by-step), Docker Compose, bare Python
- CI/CD table documenting GitHub Actions workflows
- Project structure tree
- Updated features list (Suspend/Resume, unified Price Chart, mobile responsive, FIX UI)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. README.md +270 -21
README.md CHANGED
@@ -11,37 +11,286 @@ app_port: 7860
11
  # StockEx – Kafka-based Stock Exchange Simulator
12
 
13
  A real-time stock exchange simulation built with **Apache Kafka**, **Python**, and **Flask**.
 
14
 
15
- ## Architecture
 
16
 
17
- | Service | Description |
18
- |---|---|
19
- | **Matcher** | Order matching engine (price-time priority, limit/market orders) |
20
- | **MD Feeder** | Synthetic market data generator, drives order flow |
21
- | **Dashboard** | Real-time trading dashboard with SSE streaming |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  ## Features
24
 
25
- - **Live Order Book** – best bid/ask with depth
26
- - **Trade Feed** – real-time executions with SSE push
27
- - **Market Snapshot** – BBO per symbol with ticker tape
28
- - **Trade Chart** – live price/volume chart
29
- - **Price History** – OHLCV candlestick chart (1H / 8H / 1D / 1W / 1M)
30
- - **Start / End of Day** – reset prices, pause/resume simulation
31
- - **Order Management** – cancel and amend resting orders
 
 
 
 
 
 
32
 
33
  ## Securities
34
 
35
- `ALPHA` Β· `PEIR` Β· `EXAE` Β· `QUEST` Β· `NBG`
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  ## Stack
38
 
39
- - Apache Kafka (KRaft mode, no ZooKeeper)
40
- - Python 3.11 Β· Flask Β· kafka-python
41
- - SQLite (matcher persistence + OHLCV history)
42
- - Canvas API candlestick charts
43
- - Server-Sent Events for real-time UI updates
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- ## Source
46
 
47
- GitHub: [github.com/Bonum/StockEx](https://github.com/Bonum/StockEx)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  # StockEx – Kafka-based Stock Exchange Simulator
12
 
13
  A real-time stock exchange simulation built with **Apache Kafka**, **Python**, and **Flask**.
14
+ Includes a FIX 4.4 order gateway, live matching engine, SSE-streamed dashboard, and candlestick charts.
15
 
16
+ πŸ”— **Live demo:** [huggingface.co/spaces/RayMelius/StockEx](https://huggingface.co/spaces/RayMelius/StockEx)
17
+ πŸ“¦ **Source:** [github.com/Bonum/StockEx](https://github.com/Bonum/StockEx)
18
 
19
+ ---
20
+
21
+ ## Architecture Overview
22
+
23
+ ```
24
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
25
+ β”‚ Single Docker Container β”‚
26
+ β”‚ β”‚
27
+ β”‚ nginx :7860 (reverse proxy) β”‚
28
+ β”‚ / β†’ Dashboard :5000 β”‚
29
+ β”‚ /fix/ β†’ FIX UI :5002 β”‚
30
+ β”‚ β”‚
31
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
32
+ β”‚ β”‚ MD Feeder β”‚ β”‚ FIX OEG β”‚ β”‚ FIX UI Client β”‚ β”‚
33
+ β”‚ β”‚ (simulator) β”‚ β”‚ :5001 β”‚ β”‚ Flask :5002 β”‚ β”‚
34
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
35
+ β”‚ β”‚ β”‚ β”‚ FIX 4.4 β”‚
36
+ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
37
+ β”‚ β–Ό β–Ό β”‚ β”‚
38
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
39
+ β”‚ β”‚ Apache Kafka (KRaft) β”‚ β”‚ β”‚
40
+ β”‚ β”‚ orders β”‚ trades β”‚ snapshots β”‚ control β”‚ β”‚ β”‚
41
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
42
+ β”‚ β”‚ β”‚ β”‚
43
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
44
+ β”‚ β–Ό β”‚ β”‚
45
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
46
+ β”‚ β”‚ Matcher β”‚ β”‚ Dashboard Flask :5000 β”‚β—„β”€β”€β”˜ β”‚
47
+ β”‚ β”‚ Flask:6000 β”‚ β”‚ SSE + REST API β”‚ β”‚
48
+ β”‚ β”‚ SQLite DB β”‚ β”‚ SQLite OHLCV history β”‚ β”‚
49
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
50
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Message Flow
56
+
57
+ ```mermaid
58
+ flowchart TB
59
+ Browser("🌐 Browser")
60
+
61
+ subgraph Container["Docker Container"]
62
+ nginx["nginx :7860"]
63
+
64
+ subgraph Services["Python Services"]
65
+ Dashboard["Dashboard\n:5000"]
66
+ Matcher["Matcher\n:6000"]
67
+ MDF["MD Feeder"]
68
+ FIXOEG["FIX OEG\n:5001"]
69
+ FIXUI["FIX UI Client\n:5002"]
70
+ end
71
+
72
+ subgraph KafkaTopics["Apache Kafka (KRaft)"]
73
+ Ko[("orders")]
74
+ Kt[("trades")]
75
+ Ks[("snapshots")]
76
+ Kc[("control")]
77
+ end
78
+
79
+ DB[("SQLite")]
80
+ end
81
+
82
+ Browser -- "HTTP / SSE" --> nginx
83
+ nginx -- "/" --> Dashboard
84
+ nginx -- "/fix/" --> FIXUI
85
+
86
+ FIXUI -- "FIX 4.4\nNewOrderSingle" --> FIXOEG
87
+ FIXOEG -- "order" --> Ko
88
+ FIXOEG -- "ExecReport" --> FIXUI
89
+
90
+ MDF -- "synthetic orders\n& snapshots" --> Ko
91
+ MDF -- "BBO snapshots" --> Ks
92
+
93
+ Dashboard -- "start/stop\nsuspend/resume" --> Kc
94
+ Kc -- "control signal" --> MDF
95
+
96
+ Ko -- "limit / market orders" --> Matcher
97
+ Matcher -- "fills" --> Kt
98
+ Matcher -- "BBO updates" --> Ks
99
+ Matcher --- DB
100
+
101
+ Ko --> Dashboard
102
+ Kt --> Dashboard
103
+ Ks --> Dashboard
104
+ Kt -- "OHLCV\n1-min buckets" --> DB
105
+
106
+ Dashboard -- "SSE stream\n(orders/trades/snapshots)" --> Browser
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Services
112
+
113
+ | Service | Port | Description |
114
+ |---|---|---|
115
+ | **nginx** | 7860 | Reverse proxy β€” single public port |
116
+ | **Dashboard** | 5000 | Flask app, SSE streaming, session control, OHLCV history |
117
+ | **Matcher** | 6000 | Price-time priority matching engine, REST API, SQLite persistence |
118
+ | **MD Feeder** | β€” | Synthetic market data generator; responds to start/stop/suspend/resume |
119
+ | **FIX OEG** | 5001 | FIX 4.4 acceptor β€” translates FIX messages to Kafka orders |
120
+ | **FIX UI Client** | 5002 | Browser UI for sending FIX orders and viewing execution reports |
121
+
122
+ ---
123
 
124
  ## Features
125
 
126
+ - **Live Order Book** β€” best bid/ask with full depth per symbol
127
+ - **Trade Feed** β€” real-time executions pushed via Server-Sent Events
128
+ - **Market Snapshot** β€” BBO table + scrolling ticker tape
129
+ - **Price Chart** β€” candlestick + close-price line + volume bars; Live / 1H / 8H / 1D / 1W / 1M periods
130
+ - **All-Symbols View** β€” normalised % change chart comparing all securities on one axis
131
+ - **Trading Statistics** β€” per-symbol trade count, volume, value, VWAP, bar chart
132
+ - **Start / End of Day** β€” resets opening prices, starts/stops MD simulation
133
+ - **Suspend / Resume** β€” pauses order generation without ending the session
134
+ - **Order Management** β€” cancel and amend resting orders from the dashboard
135
+ - **FIX UI Client** β€” send NewOrderSingle via FIX 4.4, view execution reports at `/fix/`
136
+ - **Mobile Responsive** β€” single-column layout on phones and tablets
137
+
138
+ ---
139
 
140
  ## Securities
141
 
142
+ | Symbol | Name | Start Price |
143
+ |---|---|---|
144
+ | ALPHA | Alpha Bank | €24.95 |
145
+ | PEIR | Piraeus Bank | €18.05 |
146
+ | EXAE | Athens Exchange Group | €42.05 |
147
+ | QUEST | Quest Holdings | €12.60 |
148
+ | NBG | National Bank of Greece | €18.05 |
149
+ | ATTIKA | Attika Bank | €3.95 |
150
+ | INTKA | Intertech | €3.95 |
151
+ | LAMDA | Lamda Development | €3.95 |
152
+ | AEG | AEG | €3.95 |
153
+ | AAAK | AAAK | €3.95 |
154
+
155
+ ---
156
 
157
  ## Stack
158
 
159
+ - **Apache Kafka 3.7** (KRaft mode β€” no ZooKeeper)
160
+ - **Python 3.11** Β· Flask 2.2 Β· kafka-python 2.0
161
+ - **QuickFIX** (FIX 4.4 protocol, compiled from C++)
162
+ - **SQLite** β€” matcher order/trade persistence + OHLCV history
163
+ - **Canvas 2D API** β€” candlestick charts rendered client-side
164
+ - **Server-Sent Events** β€” real-time push to browser (no WebSocket)
165
+ - **nginx** β€” reverse proxy with `sub_filter` URL rewriting for `/fix/`
166
+
167
+ ---
168
+
169
+ ## Deployment
170
+
171
+ ### Option 1 β€” Use the live HuggingFace Space (zero setup)
172
+
173
+ Open: **https://huggingface.co/spaces/RayMelius/StockEx**
174
+
175
+ No account or installation required.
176
+
177
+ ---
178
+
179
+ ### Option 2 β€” Deploy your own HuggingFace Space
180
+
181
+ > Pushes to your GitHub `main` branch auto-deploy to HuggingFace via GitHub Actions.
182
+
183
+ **Step 1 β€” Fork the repository**
184
+
185
+ ```bash
186
+ # On GitHub: click Fork on https://github.com/Bonum/StockEx
187
+ ```
188
+
189
+ **Step 2 β€” Create a HuggingFace Space**
190
+
191
+ 1. Go to [huggingface.co/new-space](https://huggingface.co/new-space)
192
+ 2. Choose **Docker** SDK
193
+ 3. Set `App port` to `7860`
194
+ 4. Note your Space URL: `https://huggingface.co/spaces/<your-username>/StockEx`
195
+
196
+ **Step 3 β€” Get a HuggingFace write token**
197
+
198
+ 1. Go to [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
199
+ 2. Create a token with **Write** permission
200
+ 3. Copy the token (starts with `hf_…`)
201
+
202
+ **Step 4 β€” Add the token as a GitHub Secret**
203
+
204
+ 1. In your fork: **Settings β†’ Secrets and variables β†’ Actions**
205
+ 2. Click **New repository secret**
206
+ 3. Name: `HF_TOKEN` Β· Value: your token from Step 3
207
+
208
+ **Step 5 β€” Update the Space URL in the workflow** *(if your username differs)*
209
+
210
+ Edit `.github/workflows/deploy-hf.yml`:
211
+ ```yaml
212
+ git remote add huggingface https://<your-hf-username>:${HF_TOKEN}@huggingface.co/spaces/<your-hf-username>/StockEx.git
213
+ ```
214
+
215
+ **Step 6 β€” Push**
216
+
217
+ ```bash
218
+ git push origin main
219
+ ```
220
+
221
+ GitHub Actions runs the CI tests, then pushes to HuggingFace. The Space builds (~5–15 min on first run due to QuickFIX compilation) and goes live automatically on every subsequent push.
222
+
223
+ ---
224
+
225
+ ### Option 3 β€” Local with Docker Compose
226
+
227
+ **Prerequisites:** Docker Desktop
228
+
229
+ ```bash
230
+ git clone https://github.com/Bonum/StockEx.git
231
+ cd StockEx
232
+ docker-compose up
233
+ ```
234
+
235
+ | URL | Service |
236
+ |---|---|
237
+ | http://localhost:5000 | Trading Dashboard |
238
+ | http://localhost:5001 | FIX OEG (TCP, not HTTP) |
239
+ | http://localhost:5002 | FIX UI Client |
240
+ | http://localhost:6000 | Matcher REST API |
241
+
242
+ ---
243
+
244
+ ### Option 4 β€” Local without Docker
245
+
246
+ **Prerequisites:** Python 3.11+, Apache Kafka running on `localhost:9092`
247
+
248
+ ```bash
249
+ git clone https://github.com/Bonum/StockEx.git
250
+ cd StockEx
251
+ pip install kafka-python Flask requests quickfix
252
+
253
+ # In separate terminals:
254
+ export PYTHONPATH=$(pwd)
255
+ export KAFKA_BOOTSTRAP=localhost:9092
256
+ export MATCHER_URL=http://localhost:6000
257
+
258
+ python matcher/matcher.py # terminal 1
259
+ python md_feeder/mdf_simulator.py # terminal 2
260
+ python dashboard/dashboard.py # terminal 3
261
+ ```
262
+
263
+ Then open http://localhost:5000.
264
+
265
+ ---
266
+
267
+ ## CI / CD
268
+
269
+ | Trigger | Action |
270
+ |---|---|
271
+ | Push to `main` | Run matcher unit tests + Docker build check |
272
+ | Push to `main` (tests pass) | Auto-deploy to HuggingFace Spaces |
273
+ | Pull request to `main` | Run tests only |
274
+
275
+ GitHub Actions workflows: `.github/workflows/ci.yml` Β· `.github/workflows/deploy-hf.yml`
276
+
277
+ ---
278
 
279
+ ## Project Structure
280
 
281
+ ```
282
+ StockEx/
283
+ β”œβ”€β”€ matcher/ # Matching engine + SQLite persistence
284
+ β”œβ”€β”€ md_feeder/ # Synthetic market data generator
285
+ β”œβ”€β”€ dashboard/ # Flask dashboard + SSE + OHLCV history
286
+ β”‚ └── templates/ # Single-page trading UI
287
+ β”œβ”€β”€ fix_oeg/ # FIX 4.4 Order Entry Gateway
288
+ β”œβ”€β”€ fix-ui-client/ # FIX browser UI
289
+ β”œβ”€β”€ shared/ # Shared config + Kafka utils
290
+ β”œβ”€β”€ shared_data/ # securities.txt (symbol list + prices)
291
+ β”œβ”€β”€ Dockerfile # HuggingFace / single-container build
292
+ β”œβ”€β”€ docker-compose.yml # Local multi-container dev setup
293
+ β”œβ”€β”€ entrypoint.sh # Container startup (Kafka β†’ services β†’ nginx)
294
+ β”œβ”€β”€ kafka-kraft.properties
295
+ └── nginx.conf # Reverse proxy config
296
+ ```