10 KiB
CoinEx Trading Platform v3 — Unified Architecture
Created: 2026-03-01 Owner: Case (CSO) Priority: HIGH Environment: DEV (all services on 192.168.86.45)
Overview
Unify the CoinEx trading ecosystem under a Redis-backed message bus. Four pieces:
- Redis — Message bus + shared state + cache
- TA Service — Technical Analysis engine (EMA Ribbons, Stoch RSI Divergence, TTM Squeeze)
- Dashboard Integration — Subscribe to Redis instead of polling Binance directly
- Trader Bot Integration — Subscribe to TA signals + publish state to Redis
All deployed as DEV instances on 192.168.86.45 with -dev suffixed service names and separate ports.
Piece 1: Redis Setup
Install: apt install redis-server (or Docker)
Port: 6379 (default)
Config: bind 127.0.0.1 (local only), no auth needed for dev
Service: systemd redis-server
Channel/Key Schema
# Pub/Sub Channels
market:candles:{symbol} # OHLCV candle updates (published by Market Data fetcher)
signals:ta:{symbol} # TA indicator signals (published by TA Service)
signals:scan # Composite scan results (published by Dashboard scanner)
trader:events # Trade events, position changes (published by Trader Bot)
# Key/Value State (GET/SET)
cache:candles:{symbol} # Latest candle data (JSON, TTL 60s)
cache:candles:{symbol}:1h # 1h candles for TA (JSON, TTL 300s)
cache:candles:{symbol}:4h # 4h candles for TA (JSON, TTL 600s)
state:positions # Current CoinEx positions (JSON)
state:balance # Current CoinEx balance (JSON)
state:trader:config # Trader runtime config (JSON)
state:trader:status # Trader status: enabled/disabled/locked (JSON)
ta:latest:{symbol} # Latest TA result per symbol (JSON, TTL 120s)
Market Data Fetcher (embedded in TA Service)
- Single point of contact for Binance API
- Fetches 5m, 1h, 4h candles for all 29 coins
- Publishes to
market:candles:{symbol}channel - Caches in
cache:candles:{symbol}:{timeframe}keys with TTL - Runs on 30s loop (5m candles) and 5min loop (1h/4h candles)
Piece 2: TA Service
Language: Python 3.12
Dependencies: redis, pandas, pandas-ta, numpy
Port: 8894 (health check only)
Repo: git.letsgetnashty.com/case/coinex-ta-service (private)
Service: coinex-ta-dev.service
Indicators
EMA Ribbons (8/13/21/34/55/89)
- Calculated on 5m and 1h timeframes
- Output state:
bullish(all stacked ascending),bearish(all stacked descending),mixed - Output ribbon spread: normalized 0-100 (tight = low conviction, wide = strong trend)
- Score contribution: +10 to long/short score when aligned with direction
TTM Squeeze
- Bollinger Bands (20, 2.0) vs Keltner Channels (20, 1.5)
- Squeeze ON: BB inside KC (volatility compression)
- Squeeze OFF: BB outside KC (expansion beginning)
- Momentum histogram: positive = bullish, negative = bearish
- Output:
{ squeeze: bool, momentum: float, direction: 'bullish'|'bearish', bars_in_squeeze: int } - Score contribution: +15 when squeeze fires in signal direction
Stochastic RSI Divergence
- Stoch RSI (14, 14, 3, 3)
- Detect bullish divergence: price makes lower low, Stoch RSI makes higher low
- Detect bearish divergence: price makes higher high, Stoch RSI makes lower high
- Lookback window: 50 candles for swing detection
- Use
pandas-tafor Stoch RSI calculation, custom swing detection for divergence - Output:
{ divergence: 'bullish'|'bearish'|'none', strength: float, candles_ago: int } - Score contribution: +20 for divergence aligned with signal direction
Data Flow
Binance API (OHLCV)
│
▼
TA Service
├── fetch candles (5m, 1h, 4h) for 29 coins
├── cache in Redis (cache:candles:*)
├── compute indicators
├── publish to Redis (signals:ta:{symbol})
└── store latest in Redis (ta:latest:{symbol})
Output Schema (per symbol)
{
"symbol": "BTCUSDT",
"timestamp": "2026-03-01T12:00:00Z",
"ema_ribbon": {
"state_5m": "bullish",
"state_1h": "bullish",
"spread_5m": 72.5,
"spread_1h": 85.3,
"values": [67200, 67150, 67050, 66900, 66700, 66400]
},
"ttm_squeeze": {
"squeeze": true,
"momentum": 0.45,
"direction": "bullish",
"bars_in_squeeze": 8,
"timeframe": "5m"
},
"stoch_rsi_divergence": {
"divergence": "none",
"strength": 0,
"candles_ago": 0,
"stoch_k": 45.2,
"stoch_d": 42.1
},
"composite_score_adjustment": {
"long_bonus": 25,
"short_bonus": 0,
"reasoning": ["EMA ribbon bullish aligned (+10)", "TTM squeeze bullish (+15)"]
}
}
Scan Loop
- Every 30 seconds: fetch 5m candles, compute all indicators, publish
- Every 5 minutes: fetch 1h and 4h candles, update longer-term EMA ribbons
- Health check:
GET /healthreturns status + last scan time
Piece 3: Dashboard Integration (DEV)
Branch: feature/redis-integration on coinex-dashboard repo
Dev Port: 8892
Dev Service: coinex-dashboard-dev.service
Changes
-
Subscribe to Redis channels:
signals:ta:*— receive TA indicator updatestrader:events— receive trade events
-
Read from Redis keys instead of direct API:
state:positionsandstate:balanceinstead of CoinEx API callscache:candles:{symbol}instead of Binance API callsta:latest:{symbol}for indicator data
-
Keep existing Binance fetch as fallback if Redis is unavailable
-
New UI elements per coin card:
- EMA Ribbon indicator: colored bar (green/red/yellow) with spread %
- TTM Squeeze: dot indicator (red = squeeze on, green = squeeze fired, gray = no squeeze)
- Stoch RSI Divergence: alert badge when divergence detected
- Composite score now includes TA bonus points (displayed separately)
-
WebSocket payload additions:
{ "coinData": [...], "positions": {...}, "signalHistory": [...], "taSignals": { "BTCUSDT": { "ema_ribbon": {...}, "ttm_squeeze": {...}, "stoch_rsi_divergence": {...} }, ... }, "errors": [...] } -
New tooltips:
- EMA Ribbon: "EMA Ribbon (8/13/21/34/55/89). Green = all EMAs stacked bullish. Red = bearish. Yellow = mixed."
- TTM Squeeze: "TTM Squeeze. Red dot = volatility compression (coiled spring). Green dot = squeeze just fired. Direction shown by momentum."
- Stoch RSI Div: "Stochastic RSI Divergence. Bullish divergence = price falling but momentum rising (reversal signal)."
Scoring Integration
- Display original score + TA bonus separately:
45 + 25 = 70 - TA bonus is informational in v1 — does NOT feed into trader bot decisions yet
- Dashboard shows combined view, trader still uses original scoring until validated
Piece 4: Trader Bot Integration (DEV)
Branch: feature/redis-integration on coinex-trader repo
Dev Service: coinex-trader-dev.timer (every 5min)
Changes
-
Publish to Redis on every cycle:
state:positions— current positions from CoinEx APIstate:balance— current balancetrader:events— trade opens, closes, TP/SL hits, errors
-
Read TA signals from Redis (OPTIONAL, off by default):
- Config flag:
use_ta_signals: false(disabled until backtested) - When enabled: read
ta:latest:{symbol}and add TA bonus to scoring - Safety: TA bonus capped at +30 max (can't override a bad base score)
- Config flag:
-
Publish trader status:
state:trader:status— enabled/disabled/locked, uptime, last tradestate:trader:config— current config (thresholds, TP/SL, leverage)
-
Keep all existing logic as-is. Redis is additive — if Redis is down, trader operates exactly as before.
Dev Environment Ports
| Service | Port | Systemd Service |
|---|---|---|
| Redis | 6379 | redis-server (system) |
| TA Service | 8894 | coinex-ta-dev.service |
| Dashboard (dev) | 8892 | coinex-dashboard-dev.service |
| Dashboard (prod) | 8891 | coinex-dashboard.service |
| Trader Bot (dev) | — | coinex-trader-dev.timer |
| Trader Bot (prod) | — | coinex-live-trader.timer |
| Trader API (dev) | 8895 | coinex-trader-api-dev.service |
Dev services do NOT interfere with prod. Separate ports, separate service names, separate config files.
Git Repos
| Repo | URL | Branch |
|---|---|---|
| TA Service | git.letsgetnashty.com/case/coinex-ta-service |
main |
| Dashboard | git.letsgetnashty.com/case/coinex-dashboard |
feature/redis-integration |
| Trader Bot | git.letsgetnashty.com/case/coinex-trader |
feature/redis-integration |
Pipeline
Phase 1: Foundation (Glitch)
- Install Redis on VM
- Build TA Service (Python, all 3 indicators, Redis pub/sub)
- Unit tests for each indicator against known data
- Health check endpoint
- Gitea repo + systemd dev service
Phase 2: Dashboard Integration (Glitch)
- Add Redis subscriber to dashboard scanner
- New UI components for TA indicators
- Merge TA data into WebSocket payload
- Tooltips for new indicators
- Dev service on port 8892
Phase 3: Trader Integration (Glitch)
- Trader publishes state to Redis
- Read TA signals (disabled by default)
- Config flag for TA integration
- Dev timer service
Phase 4: QA
- Hawk: Code review all three pieces
- Jinx: Functional — verify Redis pub/sub works, TA calculations are correct, dashboard displays data, trader publishes state
- Pixel: Visual — new indicator displays, tooltips, layout doesn't break
Phase 5: Deploy Dev
- Forge: systemd services, verify all dev instances running, no interference with prod
Constraints
- Dev ONLY — no changes to production services until validated
- Redis local only — bind 127.0.0.1, no external access
- TA bonus is display-only — does not affect trader decisions until backtested
- Trader safety unchanged — all kill switches, circuit breakers, lockfiles preserved
- Binance API rate limits — TA service is the ONLY Binance fetcher in the new architecture. Dashboard reads from Redis cache.
- 29 coins — same list as current scanner
- All scoring logic in
lib/indicators.tspreserved exactly — TA bonus is additive, shown separately