Why Trading Bots Need a Live Dashboard
When you run multiple auto-trading bots across Solana, KuCoin, and HyperLiquid, the logs pile up fast. Every trade, every signal, every error -- they all scroll past in a terminal window that nobody watches. The problem isnt that the data isnt there. Its that raw logs are noise, not signal.
DeFiKit runs a fleet of bots: the AutoGunSOL sniping scanner on Solana, the Freqtrade-based auto-trader with Ichimoku strategies on KuCoin, and the experimental HyperLiquid prediction bot. Each generates hundreds of log lines per hour. Buried in that noise are the signals that matter: which strategies are winning, which pairs are bleeding, and where the system is about to hit a rate limit.
A live Telegram dashboard solves this. Instead of scraping log files, you get real-time trade notifications, daily P&L summaries, pair-level heatmaps, and system health alerts -- all delivered to the same Telegram chat where you manage your bots.
Architecture: From Bot Logs to Telegram Messages
The dashboard pipeline has three layers:
- **Data ingestion:** Each bot writes structured JSON log lines (not plain text) to a shared log stream. The format is always `{timestamp, bot_id, event_type, data}`.
- **Aggregation layer:** A lightweight Cloudflare Worker runs every 5 minutes, pulls the last hours worth of logs, and computes metrics: win rate, total volume, open positions, drawdown.
- **Delivery layer:** The worker calls the Telegram Bot API to send formatted messages to the admin chat. No database needed -- just Workers + Bot API.
Structured Log Format
Instead of `INFO: Bought 0.5 SOL at $145.32`, bots log structured JSON:
```json
{
"ts": "2026-05-07T14:30:00Z",
"bot": "autogun-sol-mainnet",
"event": "trade_executed",
"data": {
"pair": "SOL/USDC",
"side": "buy",
"size": 0.5,
"price": 145.32,
"slippage_bps": 3,
"strategy": "momentum_breakout_v2"
}
}
```
This makes aggregation trivial -- no regex parsing, no fragile text scraping.
Building the Aggregation Worker
The Cloudflare Worker that powers the dashboard runs on a cron trigger (every 5 minutes during market hours, every 30 minutes overnight). Heres the core logic:
```javascript
async function aggregateMetrics(logs, since) {
const recent = logs.filter(l => l.ts > since);
// Per-bot stats
const byBot = {};
for (const entry of recent) {
if (!byBot[entry.bot]) byBot[entry.bot] = { trades: 0, wins: 0, losses: 0, volume: 0 };
if (entry.event === 'trade_executed') {
byBot[entry.bot].trades++;
byBot[entry.bot].volume += entry.data.size * entry.data.price;
}
if (entry.event === 'trade_closed') {
if (entry.data.pnl > 0) byBot[entry.bot].wins++;
else byBot[entry.bot].losses++;
}
}
return Object.entries(byBot).map(([name, stats]) => ({
name,
...stats,
winRate: stats.trades > 0 ? (stats.wins / (stats.wins + stats.losses) * 100).toFixed(1) : 0,
avgVolume: stats.trades > 0 ? (stats.volume / stats.trades).toFixed(2) : 0
}));
}
```
The worker stores the last aggregated state in Workers KV so it can compute deltas (today vs yesterday) without polling a database.
Telegram Message Format
Each dashboard push is a single message with inline formatting. Heres the template:
```
📊 DeFiKit Dashboard -- 14:30 CT
🤖 AutoGun SOL Mainnet
Trades: 12 | Win Rate: 75%
Volume: $8,420 | P&L: +$342 (+4.2%)
Active: 3 positions
🤖 Freqtrade KuCoin (Ichimoku)
Trades: 8 | Win Rate: 62.5%
Volume: $12,100 | P&L: +$187 (+1.5%)
Active: 2 positions
🤖 HyperLiquid Prediction
Trades: 3 | Win Rate: 100%
Volume: $450 | P&L: +$28 (+6.6%)
Active: 0 positions
⚠️ Alerts
• AutoGun SOL: Slippage exceeded 5bps on last 3 trades
• Freqtrade: Position SOL/USDT approaching stop-loss at $138
Last updated: 14:30 CT | Next update: 14:35 CT
```
The emoji header makes it scannable at a glance. Critical alerts (slippage, drawdown, exchange errors) get highlighted with emoji markers.
Deploying With Cloudflare Workers
Deployment is a single wrangler command. The worker itself is ~150 lines of JavaScript:
```bash
npx wrangler deploy src/dashboard-worker.js \
--name defikit-dashboard \
--kv DASHBOARD_STATE \
--secret TELEGRAM_BOT_TOKEN \
--secret TELEGRAM_CHAT_ID
```
Set the cron schedule in `wrangler.jsonc`:
```json
{
"triggers": {
"crons": ["*/5 9-23 * * 1-5", "*/30 0-8,0-23 * * 0,6"]
}
}
```
This runs every 5 minutes during market hours (9 AM to 11 PM CT, weekdays) and every 30 minutes outside those hours.
Extending the Dashboard
The same pipeline can power richer analytics:
- **Daily digest:** A separate worker runs at 8 AM and 8 PM CT, sending a fuller report with charts (generated as inline Telegram images using chart.js on Workers).
- **Strategy comparison:** Side-by-side win rates, Sharpe ratios, and max drawdown for each active strategy.
- **Gas/ fee tracking:** For Solana bots, track transaction fees and compute net P&L after fees.
- **Alert thresholds:** Configurable alerts -- notify when win rate drops below 40%, drawdown exceeds 15%, or a bot goes silent for more than 10 minutes.
Why Telegram Instead of a Web Dashboard
A web dashboard is nice to have, but Telegram wins for trading bots for three reasons:
1. **Push, not pull.** You dont open a browser to check -- the data comes to you. On mobile, Telegram notifications are instant.
2. **Same channel as bot commands.** You can reply to a dashboard message with `/pause autogun-sol` and the bot stops trading, all in one chat.
3. **Zero infrastructure.** No database, no frontend, no domain. Just a Worker and the Bot API.
This is the hybrid dev-marketing philosophy in action: build tools that double as communication channels. The dashboard isnt just an internal tool -- its the same interface youd show a partner or investor who wants to see how the bots are performing.
What We Learned
Running this in production for DeFiKit for the last month taught us a few things:
- **Structured logging pays for itself.** The upfront cost of changing bot log formats was two hours of refactoring. It saved ten hours of regex debugging in the first week.
- **Cron-based aggregation is simpler than streaming.** We tried WebSocket streaming first. For a dashboard that updates every 5 minutes, a cron worker triggered by Cloudflare Scheduler is cheaper and more reliable.
- **Keep messages under 4096 characters.** Telegrams message length limit means you need to truncate or paginate. We split long dashboards into a summary message + detail thread.
- **Include a timestamp.** When a dashboard message sits in chat for hours, the reader needs to know how stale the data is. Every message carries a "Last updated" line.
Next Steps
With the dashboard live, the next move is adding two-way interaction -- being able to reply to a dashboard message with a command like `/toggle botname` or `/adjust strategy_name threshold 0.5`. That turns the dashboard from a read-only view into a control panel, all inside Telegram.