Forex Market Scanner · Full-Stack + ML · CS Thesis
Edge
Multi-tier forex market scanner with macroeconomic scoring & GBDT signal layer
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.
| Indicator | Weight | Scoring |
|---|---|---|
| Interest Rate | 3.0 | vs. forecast |
| Core Inflation | 2.5 | vs. forecast |
| Employment Change | 2.0 | beats / misses forecast |
| GDP Growth | 2.0 | beat / miss |
| COT (net change %) | 1.8 | positional bias |
| Unemployment Rate | 1.5 | inverse: lower = +1 |
| Manufacturing PMI | 1.2 | beat / miss |
| Services PMI | 1.2 | beat / miss |
| Retail Sales | 1.0 | beat / 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
| Frontend | React 19 · Vite 6 · React Router 7 · TailwindCSS 4 · Framer Motion · Recharts · react-financial-charts (OHLC) · styled-components · lucide-react |
| Main API | Express 5 · MySQL 2 (two pools) · express-session + connect-mongo · helmet · express-rate-limit · express-validator · cookie-parser · cors · multer (uploads) |
| Auth API | Express 5 (separate process) · bcrypt + bcryptjs · JWT · nodemailer (OTP delivery) |
| ML server | Python 3 · Flask · scikit-learn (GBDT) · joblib · pandas · numpy |
| Data | MySQL — two databases: 8con (accounts, assets) and 8cons (payments, OTP) |
| Document export | jsPDF + jspdf-autotable · pdfkit · docx · exceljs (PDF / DOCX / XLSX) |
| Production | Docker + docker-compose (separate Dockerfile.node and Dockerfile.python) · Nginx reverse proxy · certbot for TLS · self-managed VPS |
| Tooling | concurrently (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).RoleRouteguards admin pages; tier guards dashboard features.useAccessControlhits 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/heartbeatkeeping 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.
pool8conserves user-facing data (accounts, assets);pool8consserves 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.