Files
ForexBot2/webapp
Harwinder Sekhon 85a5ba09b8 Add LAMP web dashboard: bot→MySQL publisher, PHP API, numbers-only page
- webapp/: deployable LAMP app for /var/www/ — ingest.php (token-gated
  writes), api.php (public read-only), schema.sql (live_price +
  signal_reports), vanilla-JS dashboard with plain-English indicator
  readings, .htaccess, deploy README
- web_publisher.py: fire-and-forget publisher (bounded queue + daemon
  thread) with plain-English payload builder; public API contractually
  never raises; disabled unless WEBAPP_INGEST_URL/TOKEN are set
- telegram_bot.py: publish hooks (tick in WS loop, report in
  _update_level_cache); _candle_loop per-iteration guard so a failing
  scan can never kill an auto-scan loop; quiet heartbeat teardown
- test_all.py: Module 13 — 6 resilience tests (never-raise contract,
  worker survival, candle-loop survival); suite 189/189
- .gitignore: webapp/config.php (server-side secrets)

Verified end-to-end on a scratch MariaDB 10.11 + PHP 8.3 built-in
server incl. headless-Firefox render of the live page.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYNEHBuwwy6sgRM9f9sPx5
2026-07-17 11:41:03 -04:00
..

ForexBot2 web dashboard (LAMP)

Numbers-only live dashboard: latest XAU/USD price plus each timeframe's signal, indicator values, and a plain-English reading of every one.

How it flows

telegram_bot.py (owns the single Twelve Data WebSocket)
   ├─ every tick  ──►  POST ingest.php  ──►  MySQL live_price   (throttled 1/s)
   └─ every scan  ──►  POST ingest.php  ──►  MySQL signal_reports
                                                    │
browser  ──►  index.html + app.js  ──►  GET api.php ┘
             (price poll 2 s · reports poll 15 s)

The dashboard needs no Python on the web server — only PHP + MySQL. The bot can run anywhere with outbound HTTPS to the site.

Server setup (once)

  1. Copy this directory to the web root, e.g. /var/www/html/webapp/.
  2. Create DB + tables: mysql -u root -p < schema.sql (also create the app user — commands at the bottom of schema.sql).
  3. cp config.sample.php config.php and fill in DB credentials and a fresh ingest_token (openssl rand -hex 32).
  4. Apache must allow .htaccess (AllowOverride FileInfo Limit or All) so config/schema stay unreachable — or copy those deny rules into the vhost. Verify: curl -I https://site/webapp/config.php must return 403.

Bot setup

Set two environment variables where telegram_bot.py runs:

export WEBAPP_INGEST_URL="https://your-site/webapp/ingest.php"
export WEBAPP_INGEST_TOKEN="<same token as config.php>"

Unset = publishing is disabled and the bot behaves exactly as before. Publishing is fire-and-forget (bounded queue + daemon thread): a dead web server can never block or slow the bot.

Security notes (public access)

  • api.php is read-only and public by design; ingest.php requires the shared token (use HTTPS so it isn't sent in the clear).
  • config.php / schema.sql are denied by .htaccess.
  • Optional hardening: rate-limit api.php (mod_evasive/fail2ban), and restrict ingest.php to the bot host's IP in the vhost.

Data growth

  • live_price: 1 row per symbol (upserted in place).
  • signal_reports: ~400 rows/day for XAU (M5+M15+H1+H4) — ~150k rows/year, no retention job needed. It doubles as a durable log of every signal the engine produced (the payload column holds the full report JSON).

Local smoke test (no Apache needed)

php -S 127.0.0.1:8090 -t webapp/   # then open http://127.0.0.1:8090/