- Script: --seed-chart flag writes OHLCV candles into dashboard_history.db
- Dashboard: auto-seeds from ohlcv/*.json on first run if DB is empty
- Dashboard: /history/symbols endpoint for pre-populating chart dropdown
- Frontend: loads available symbols on page load for pre-session chart display
- Fix HISTORY_DB default path after shared_data -> shared/data merge
- 1W shows ~5 daily candles, 1M shows ~20 daily candles with real prices
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add real ATHEX/NYSE/Euronext prices, OHLCV data for RL agent, merge shared_data into shared/data
- Dashboard: remove direct SSE broadcast from _generate_and_broadcast(),
let Kafka consumer handle it (was causing every insight to appear twice)
- CH trade consumer: match matcher's field names (buy_id/sell_id) instead
of buy_order_id/sell_order_id, so trades are actually attributed to members
- Notebook: support both Kaggle (dataset) and Colab (Drive) checkpoints,
set SAVE_STEPS=10
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix HF 410: always use router.huggingface.co for all models
api-inference.huggingface.co is deprecated (HTTP 410).
All three services (ai_analyst, ch_ai_trader, dashboard) now
route every model through router.huggingface.co.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add navigation links between Dashboard and Clearing House
- Dashboard header: green "Clearing House" button linking to /ch/
- Clearing House nav: "← Main Dashboard" link back to /
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add clearing house simulation with 10 members (USR01-USR10)
- New clearing_house/ Flask service (port 5004) with dedicated dark-themed portal
- SQLite persistence: member capital, holdings, daily trade counters, settlements
- Members start with €100,000; must trade ≥10 securities per trading day
- Password = member ID (e.g. USR01 logs in with password USR01)
- Real users log in to trade manually; AI (LLM via Groq→HF→Ollama) simulates unoccupied members
- Trade attribution via Kafka trades consumer — detects USRxx- cl_ord_id prefix
- EOD settlement triggered by dashboard session end; calculates unrealized P&L
- Leaderboard at /ch/ with real-time auto-refresh and Human/AI badges
- Member portfolio view: holdings, order entry, trade history, settlement history
- Integrated into nginx (/ch/), entrypoint.sh, docker-compose, and HF Dockerfile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix HF inference URL routing for org/model format models
The condition '/ in m.split(\"/\")[0]' was always False (split removes
the slash), so only RayMelius/ models used the direct inference API —
all other org/model names (Qwen/, meta-llama/, etc.) hit the router
and got 400 'not supported by any provider'.
Fix: use direct inference API for any model containing a slash.
Also: replace Qwen/Qwen2.5-7B-Instruct-1M with Qwen/Qwen2.5-7B-Instruct
in the HF model list (-1M variant not available on inference API).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add dynamic LLM provider/model selection to AI Analyst
- ai_analyst: add Groq support, _active_provider/_active_model globals,
refactored call_llm routing (Ollama → Groq → HF auto fallback),
handle Kafka 'set_llm' control message to switch provider at runtime
- dashboard: /ai/select now publishes set_llm to Kafka control topic so
the AI Analyst service picks up provider changes immediately
- dashboard + index.html: sync LLM selector UI (provider/model dropdowns,
badge, SSE llm_config event) to latest working version
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Groq as primary LLM provider (free, 14k req/day)
The -1M variant is not supported by user's enabled providers.
Qwen/Qwen2.5-7B-Instruct (standard) already has 140 successful
requests in the account — confirmed working.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix AI Analyst: align model default, actionable provider-not-enabled error
- dashboard.py: change HF_MODEL default from Qwen2.5-3B to Qwen2.5-7B-Instruct-1M
(matches docker-compose ai_analyst service)
- Detect 400 model_not_supported / provider errors and return a clear message
with link to huggingface.co/settings/inference-providers
- /ai/debug: add "fix" field with provider setup instructions when 400 occurs
- docker-compose: add HF_TOKEN + HF_MODEL env vars to dashboard service
- index.html: error insights shown in red; status header turns red on error
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Detect missing token before spawning LLM thread and broadcast
a clear error message to the AI Analyst panel immediately
- Same warning shown on page load via ai_insights_init event
- /ai/debug already exposes hf_token_set flag for diagnostics
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Scheduler: change elif condition to start_t <= now < end_t so the
session is never auto-started when current time is past end time
(previously: end at 17:00, then next tick 17:00>=10:00 restarts it)
- nginx: replace localhost with 127.0.0.1 to avoid IPv6 connection
refused errors on HuggingFace (localhost resolves to ::1 there)
- AI panel: indigo top border + shadow to make it visually distinct;
button enlarged and labelled with ✨ for better discoverability
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AI Analyst: add Generate Now button for on-demand insights
- Button in AI Analyst panel header calls POST /session/ai_insight
- Dashboard publishes {"action": "generate_insight"} to control topic
- ai_analyst listens and runs LLM call in a background thread
- Button shows "Generating…" / disabled while waiting, re-enables on result
- Fix: control topic key was "command", now correctly uses "action"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add AI Analyst service: Ollama (local) + HuggingFace (HF Spaces)
New ai_analyst/ai_analyst.py service consumes trades/snapshots from
Kafka, builds a market-context prompt every 30 min, calls Ollama
(llama3.1:8b) locally or HuggingFace Inference API (Mistral-7B) as
fallback, and publishes insights to the ai_insights Kafka topic.
Dashboard consumes ai_insights and broadcasts via SSE. New full-width
AI Analyst panel displays timestamped insights with animated cards.
- ai_analyst/ai_analyst.py: new service (Ollama-first, HF fallback)
- ai_analyst/Dockerfile: minimal Python image for local compose
- shared/config.py: add AI_INSIGHTS_TOPIC
- dashboard/dashboard.py: consume ai_insights, SSE broadcast
- dashboard/templates/index.html: AI Analyst panel + JS handlers
- Dockerfile: copy ai_analyst.py into HF single-container image
- entrypoint.sh: create ai_insights topic, start ai_analyst.py
- docker-compose.yml: ai_analyst service with OLLAMA_HOST + HF_TOKEN
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the individual orange dots with a continuous orange polyline +
dots overlay. Remove the filled candlestick bodies (keep wicks) so the
horizontal flat lines no longer clutter each price point.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Frontend (disconnected root cause):
- All fetch('/endpoint') calls were hitting nginx '/' (dashboard) instead
of '/frontend/endpoint'. Added BASE detection at page load:
const BASE = window.location.pathname === '/' ? '' : pathname.replace(/\/$/, '');
Applied to /securities, /order, /book, /trades
FIX UI (session disrupted by reloader):
- debug=True caused Flask reloader to spawn a child process and restart
the app, breaking the QuickFIX session on startup
- Changed to debug=False, use_reloader=False
Entrypoint timing:
- FIX OEG sleep increased from 3s → 6s (allow full socket bind)
- FIX UI sleep increased from 2s → 3s (allow QuickFIX initiator to start)
Dashboard:
- Local clock added to header bar (updates every second, browser timezone)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix scheduler: wrong path + no timezone = never fires
Bug 1 — Wrong schedule file path:
SCHEDULE_FILE defaulted to /app/shared_data/market_schedule.txt but
the volume/Dockerfile uses /app/data/. File was never found so
load_market_schedule() silently returned {}, scheduler never triggered.
Fixed default path + added ENV in Dockerfile as belt-and-suspenders.
Bug 2 — Server in UTC, market in Athens (GMT+2):
datetime.now() returned UTC time; at 11:46 Athens = 09:46 UTC the
scheduler saw 09:46 < 10:00 and did nothing.
Added Timezone field to market_schedule.txt and _local_now(tz) helper
that uses zoneinfo (Python 3.9+) with pytz fallback.
market_schedule.txt now:
Timezone Europe/Athens
Start 10:00
End 17:00
Scheduler logs local time on every tick for observability.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Frontend button to dashboard; wire frontend into single-container
Dashboard:
- FRONTEND_URL env var injected into template; button only shown when set
- docker-compose: FRONTEND_URL=http://localhost:5000 added to dashboard service
- Button opens frontend in new tab (indigo pill style, matching FIX UI)
Single-container (HuggingFace):
- nginx: /frontend/ route added → localhost:5003
- entrypoint.sh: starts frontend on port 5003 with correct template folder
- Dockerfile: copies frontend.py + templates to /app/frontend_templates/
- frontend.py: TEMPLATE_FOLDER env var support added
- Dockerfile: also copies market_schedule.txt to /app/data/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Price chart:
- Volume bars narrowed to 25% slot width, capped at 5px
- Close-price overlay replaced with orange dots per candle (not a line)
- Legend updated to dot symbol instead of line
Multi-symbol chart:
- Volume data now passed from loadAllHistory (live + candle modes)
- drawMultiChart splits into 70% price / 30% volume when volumes present
- Aggregated volume bars (sum across symbols per 60s bucket) shown below
- Volume Y-axis labels on right side (0, 50%, max)
FIX UI:
- Added "← Dashboard" back button in header (links to /)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Volume bars width reduced to 35% of slot (was 65%) for cleaner chart
- Volume Y-axis labels added on right side (0, 50%, max) with k-suffix
- pad.right widened to 46px to accommodate volume labels
- Trading Statistics thead row: background #f0f0f0 (matches Orders/Trades)
- Auto mode: End of Day button stays enabled when session is active
- Default mode changed to Automatic (backend + frontend)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Start/End Day toggle, Manual/Automatic mode with schedule-based auto-trading
- Merge Start of Day / End of Day into single toggle button (green→Start, orange→End)
- Add Manual/Automatic toggle button; Automatic mode disables manual day control
- Add shared_data/market_schedule.txt (Start 10:00, End 17:00)
- Backend: schedule_runner thread auto-starts at 10:00, auto-ends at 17:00
- Backend: POST /session/mode endpoint; broadcasts mode via SSE
- Fix scheduler logic: end check takes priority, nothing fires before 10:00
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Price Chart: show all securities as normalised % chart when no symbol selected
- Default selection is "All Symbols" (empty value) instead of auto-picking first symbol
- drawMultiChart(): plots each security as a % change line from its first data point,
so differently-priced securities (e.g. EXAE ~42 vs AAAK ~4) are comparable on one chart
- Right-side vertical legend with colour-coded symbol names
- Zero-line dashed when chart spans positive and negative % territory
- loadAllHistory(): live mode groups state.trades by symbol; historical mode fetches
all symbols in parallel via Promise.all and draws the multi-line chart
- loadHistory() routes to loadAllHistory() when no symbol is selected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move Price Chart into grid beside Trading Statistics; traditional chart style
- Remove standalone Trade Chart panel from the grid
- Rename Price History panel to Price Chart (full-width, below grid)
- Add "Live" as default period option: shows last 100 trades as a line chart
that auto-refreshes on every SSE trade event
- Historical periods (1H/8H/1D/1W/1M) now also use a consistent line chart
style (close price line + gradient fill + volume bars) instead of candlesticks
- Unified drawChart() function renders both live trades and OHLCV candles with
the same visual: green line, gradient fill, blue volume bars, time axis
- Remove renderPriceChart() and dead #chart-symbol dropdown references
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- md_feeder: add _suspended flag; handle suspend/resume control messages
to pause/unpause order generation without ending the session
- dashboard: add suspended field to session_state; add POST /session/suspend
and POST /session/resume endpoints that publish to control topic
- dashboard template: Suspend button (blue-grey) between Start and End of Day;
toggles to Resume (green) when paused; session badge shows PAUSED (amber)
with pulsing dot when suspended; button disabled when session is idle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add mobile-responsive layout to dashboard and FIX UI client
- Add viewport meta tag (critical: prevents mobile browsers from zooming out)
- Stack panels to single column on screens <= 768px
- Allow tables to scroll horizontally inside panels on mobile
- Wrap h1 header buttons on small screens
- Reduce panel height, font size, and padding on mobile
- Full-width modal on small screens
- Same responsive treatment applied to fix-ui-client template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add FIX UI Client to HuggingFace Space via nginx reverse proxy
- shared/config.py: add CONTROL_TOPIC for start/stop signals
- md_feeder: listen on control topic; pause/resume simulation on stop/start signals, reload securities on start
- dashboard: add SQLite OHLCV history DB (1-min buckets), record every Kafka trade
- dashboard: POST /session/start (reset prices → start), POST /session/end (save closing prices → stop)
- dashboard: GET /history/<symbol>?period=1h|8h|1d|1w|1m returns aggregated OHLCV candles (≤150 bars)
- dashboard UI: Start/End of Day buttons + session status badge in header
- dashboard UI: full-width Price History panel with candlestick + volume chart (canvas)
- docker-compose: mount shared_data volume into dashboard so it can read/write securities.txt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Kafka-based stock exchange simulation with:
- Order matcher engine with SQLite persistence
- FIX protocol OEG server and UI clients
- Frontend order entry with real-time book/trades
- Trading dashboard with SSE streaming and charts
- Market data feeder, consumer, and snapshot viewer
- Docker Compose orchestration for all services
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>