Forex Market Scanner · Full-Stack + ML · CS Thesis
Edge
Multi-tier forex market scanner with macroeconomic scoring & GBDT signal layer
Edge forex market scanner demo
What it is
Edge (deployed as 8ConEdge) is my Computer Science thesis: a full-stack SaaS platform that ranks forex currency pairs by macroeconomic-indicator consensus and augments those signals with a Python GBDT model. Users sign in, browse a "Top Setups" leaderboard of pairs scored from -10 to +10, drill into a per-pair profile (score breakdown, OHLC chart, ML conviction reading), and — depending on their tier — export the analysis to PDF / DOCX / XLSX. It's built as a real product, not a notebook: role- and tier-gated access, session security, payment-receipt uploads, and a four-service Docker production deploy behind Nginx.
The signal: how pairs are ranked
For each currency pair (EUR/USD, GBP/USD, …) the engine pulls nine macro indicators for both the base and quote currencies, scores each indicator +1 / 0 / −1 by comparing actual vs. forecast (or by direction-of-change), then aggregates with a fixed weight per indicator. Result is a normalized totalScore in [-10, +10] that ranks every tracked pair.
IndicatorWeightScoring
Interest Rate3.0vs. forecast
Core Inflation2.5vs. forecast
Employment Change2.0beats / misses forecast
GDP Growth2.0beat / miss
COT (net change %)1.8positional bias
Unemployment Rate1.5inverse: lower = +1
Manufacturing PMI1.2beat / miss
Services PMI1.2beat / miss
Retail Sales1.0beat / miss
The ML layer
A separate Python Flask service (port 5001) runs two pre-trained Gradient Boosted Decision Tree models on top of the rule-based scores: conviction_regressor.pkl outputs how strongly to trust the signal for a given regime, and regime_classifier.pkl labels the current market regime. A scaler.pkl handles feature normalization. The Node API proxies requests to this service so the React frontend talks to a single domain. Training data lives alongside the project as synthetic_training_data.csv; train_gbdt.py regenerates the models.
System architecture
Browser (React 19 + Vite + Tailwind + Framer Motion)
  │
  ▼
Nginx reverse proxy (production) ─── or ─── Vite proxy (dev)
  │
  ├──► Express Main API     (Node, :3000)  ── pool8con  (users, profiles, assets)
  │                                         └─ pool8cons (payments, OTP, registrations)
  │
  ├──► Express Enrollment   (Node, :3001)  ── signup · OTP · password reset
  │                                              │
  │                                              └── nodemailer → SMTP
  │
  └──► Python AI Server     (Flask, :5001) ── GBDT (conviction + regime) · scaler

dev: 4 services run concurrently (concurrently --names BACKEND,ENROLL,VITE,AI-GBDT)
prod: docker-compose orchestrates all four behind Nginx + certbot TLS
Tech stack
FrontendReact 19 · Vite 6 · React Router 7 · TailwindCSS 4 · Framer Motion · Recharts · react-financial-charts (OHLC) · styled-components · lucide-react
Main APIExpress 5 · MySQL 2 (two pools) · express-session + connect-mongo · helmet · express-rate-limit · express-validator · cookie-parser · cors · multer (uploads)
Auth APIExpress 5 (separate process) · bcrypt + bcryptjs · JWT · nodemailer (OTP delivery)
ML serverPython 3 · Flask · scikit-learn (GBDT) · joblib · pandas · numpy
DataMySQL — two databases: 8con (accounts, assets) and 8cons (payments, OTP)
Document exportjsPDF + jspdf-autotable · pdfkit · docx · exceljs (PDF / DOCX / XLSX)
ProductionDocker + docker-compose (separate Dockerfile.node and Dockerfile.python) · Nginx reverse proxy · certbot for TLS · self-managed VPS
Toolingconcurrently (4-service dev runner) · ESLint · nodemon · yarn lock + npm lock both present
Notable engineering decisions
  • Two-dimension access control. Users have a role (student / teacher / admin) and an orthogonal tier (basic / full, payment-gated). RoleRoute guards admin pages; tier guards dashboard features. useAccessControl hits sessionStorage first then verifies with the backend, so guard re-renders are instant after the first check.
  • Session security beyond the basics. A 15-minute idle timer triggers a 2-minute warning modal then auto-logout, with a 4-minute heartbeat to /api/session/heartbeat keeping live sessions alive. Single-tab enforcement uses a BroadcastChannel + localStorage heartbeat so opening a second tab kicks the first — protects shared accounts in lab/classroom contexts.
  • Two MySQL databases on purpose. pool8con serves user-facing data (accounts, assets); pool8cons serves payments, OTP records, and registrations. Splitting concerns across pools means a payments outage can't take down the dashboard.
  • Multi-format export. Reports can be downloaded as PDF (via jspdf-autotable), DOCX (docx), or XLSX (exceljs) so users can drop them straight into whatever workflow they're using.
  • OTP, real-world. 5-minute expiry, 5-attempt limit, Multer-handled receipt uploads to a Docker-volume-mounted directory so they survive container restarts.
  • Production hardening from day 1. helmet (security headers), express-rate-limit (anti-bruteforce), express-validator (input validation), cookie-parser, cors — all wired in from the initial commit instead of bolted on later.
Scope
Computer Science undergraduate thesis (8Con Academy). Originally deployed live on a self-managed VPS for the thesis evaluation period; the VPS is currently paused. The full thesis manuscript covers the analytical methodology, GBDT training procedure, and findings from live use, and is available on request.
© 2026 Jhames Andrew Macabata