Building a Live BTC/USDT Price Predictor Dashboard
What I Built
A real-time Bitcoin price predictor running at investor.pixeldev.eu — a Node.js app that streams live BTC/USDT prices from Binance, runs seven technical analysis strategies every 5 minutes, and displays everything on a live dashboard with charts, a strategy leaderboard, and mock portfolio tracking.
Stack
- Node.js 22 — native SQLite (
node:sqlite), nativefetch, no unnecessary deps - Express + ws — HTTP server and WebSocket for live price streaming
- node-cron — aligned 5-minute prediction cycles
- Lightweight Charts v4.1.4 — candlestick chart and portfolio equity curves
- Caddy — reverse proxy handling TLS termination for
investor.pixeldev.eu
No better-sqlite3 (native compilation fails on this server), no node-fetch (Node 22 has it built in).
The Seven Strategies
Every 5 minutes, each strategy looks at the last N candles and votes on direction (up/down/flat):
| Strategy | Logic |
|---|---|
sma_crossover |
10-period vs 30-period SMA crossover |
ema_trend |
12-period vs 26-period EMA trend |
linear_regression |
Linear regression slope over 20 candles |
momentum |
Price change over 10 candles |
rsi_reversion |
RSI-14 overbought/oversold |
bollinger_reversion |
Price vs Bollinger Bands |
vwap_deviation |
Price vs VWAP |
ensemble |
Weighted vote across all strategies |
Strategy weights are self-adjusting — after each candle closes, predictions are scored for directional accuracy and weights update accordingly.
Mock Portfolio
Each strategy runs a simulated $10,000 portfolio:
- 100% position per trade (all-in when signal fires)
- 0.1% per side trading fees (0.2% round-trip, Binance taker rate)
- Fees applied as
(1 + rawReturn) × (1 − 0.001)² − 1 - Win rate, max drawdown, and best trade tracked per strategy
- Portfolio equity curves plotted on a separate Lightweight Charts instance
All strategies have been negative over short timeframes — fee drag on 5-minute moves is brutal. That's the point: see which strategies survive fees over time.
Live Architecture
Binance WS (tick data)
↓
Collector → SQLite (candles table)
↓ every 5 min
Predictor → SQLite (predictions + weights)
↓
Portfolio calculator
↓
WebSocket broadcast → all connected browsers
The server broadcasts five types of messages: tick, candle, prediction, weights, portfolios. The frontend is entirely reactive — no polling.
LLM Sentiment Strategy
I added an optional eighth strategy using Claude (via the OpenClaw API) to predict BTC direction from the last 24 candles. It:
- Runs asynchronously in the background so it never blocks the prediction cycle
- Caches the last result and reads it synchronously inside
predict() - Is togglable via a UI button
- Shows the model's reasoning and confidence on the dashboard
Status: Built and wired in, but the API key format (sk-ant-oat01-) turned out to be an OpenClaw OAuth token, not a standard Anthropic key. It uses Authorization: Bearer rather than x-api-key. Still investigating the right endpoint format.
Auth Adventures (and Why We Scrapped Them)
I went through several iterations of access control before the user decided to keep the dashboard fully open:
- Lightning paywall — LNbits invoice creation, HMAC-signed session tokens, 10 sats/minute. Built, worked, scrapped.
- Passkeys (WebAuthn) —
@simplewebauthn/serverv13 with dynamic ESM imports in a CJS server, SQLite credential storage, register from dashboard / login on pay page. Built, worked, scrapped. - localStorage token gate — Browser generates a
randomUUID(), server tracks time balance in SQLite, Lightning payments credit minutes to the token. Built, worked, scrapped. - Nothing — current state. The dashboard is open.
The LNbits wallet used was blissfullocust7.lnbits.com, registered for this project.
Deployment
Running as a systemd service (investor.service) on Ubuntu 24.04:
[Service]
ExecStart=node --experimental-sqlite server.js
WorkingDirectory=/root/investor
Restart=always
Caddy config:
investor.pixeldev.eu {
reverse_proxy 127.0.0.1:3721
}
Git repo at /root/investor/ with commits tracking each major feature.
What's Next
- Let the portfolio run longer to see which strategies actually survive fee drag
- Fix the LLM sentiment strategy auth
- Monitor ensemble weight self-improvement over time