Files
set50-system/README.md
2026-08-23 12:02:22 +07:00

106 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SET50 Alternative Data Platform
Tourism-first vertical slice for a deterministic SET50 alternative-data research system. The app can run against a clearly-labelled fixture or fetch a point-in-time Tourism Indicators vintage from the Bank of Thailand report backed by the Ministry of Tourism and Sports.
Current scope:
```text
fixture or BOT source observation
→ Tourism Pulse surprise
→ versioned exposure score
→ ranked target weights
→ English dashboard
→ internal paper ledger
```
No external webhook receiver and no live MT5 execution are enabled.
## Run the backend
```bash
python -m venv .venv
.venv/bin/pip install -r backend/requirements.txt
PAPER_WRITE_TOKEN=local-paper-token TOURISM_SOURCE=fixture PYTHONPATH=backend .venv/bin/python backend/run.py
```
Health check:
```bash
curl http://127.0.0.1:5000/api/v1/health
```
## Run the dashboard
In a second terminal:
```bash
cd frontend
npm install
npm run dev -- --host 127.0.0.1
```
Open `http://127.0.0.1:5173`.
The frontend reads the live API through Vite's `/api` proxy. Paper writes require the operator to unlock an HttpOnly browser session using the backend `PAPER_WRITE_TOKEN`; the token is never embedded in the frontend bundle. The paper-entry action records an assumed fill in the in-memory paper ledger only.
For HTTPS/non-local deployment, set `PAPER_COOKIE_SECURE=1`. The M0 session store is intentionally in-memory and single-process; use a shared session store before running multiple workers or replicas.
## Run with the real BOT Tourism source
Use the BOT-backed adapter when network access is available:
```bash
PAPER_WRITE_TOKEN=local-paper-token TOURISM_SOURCE=bot PYTHONPATH=backend .venv/bin/python backend/run.py
```
At startup the adapter performs a read-only GET/POST against the BOT Tourism Indicators report, parses the available monthly history, computes the latest year-over-year arrival observation against a trailing 12-point baseline, and stores the raw HTML plus normalized snapshot under `backend/data/` (ignored by git). The dashboard labels provisional BOT data as `provisional`, not `high`.
Data-health and replay endpoints:
```text
GET /api/v1/data-health
GET /api/v1/vintages?as_of=<ISO-8601 timestamp>
GET /api/v1/replay/tourism?vintage_id=<vintage_id>
GET /api/v1/backtest/tourism?min_events=12
```
Source: `https://app.bot.or.th/BTWS_STAT/statistics/ReportPage.aspx?reportID=875&language=eng`
## Collect a vintage manually
The collector is intentionally one-shot and idempotent. Run it after a source update; it preserves raw bytes, normalized snapshots, and a manifest under `backend/data/`:
```bash
PYTHONPATH=backend .venv/bin/python backend/scripts/collect_tourism_vintage.py --root backend/data
```
Repeated collection of the same source hash keeps one `vintage_id` and increments `seen_count` without changing `first_seen_at`. A new hash for the same publication timestamp is recorded as a separate `revised` vintage.
## Tests and build
```bash
PYTHONPATH=backend .venv/bin/python -m unittest discover -s backend/tests -v
cd frontend && npm run build
```
## Current M2 boundary
- English UI and analysis vocabulary
- Research mode and paper mode only
- Tourism Pulse fixture adapter and BOT Tourism Indicators adapter
- Data lineage: source, publication time, retrieval time, vintage
- Raw response hash and normalized snapshot persistence
- Immutable vintage manifest with first-seen/revision metadata
- Read-only data-health, vintage timeline and vintage replay endpoints
- Deterministic event-study engine with benchmark and cost inputs
- Backtest readiness gate that blocks without independent vintages and prices
- Deterministic surprise × exposure × confidence score
- Paper ledger endpoint
- No LLM call yet; the deterministic result is the source of truth
- No webhook receiver yet
- No MT5 bridge yet
The next implementation step is the event-study/backtest layer using only vintages whose `published_at` is known at each test date.
The event-study gate is now exposed through `/api/v1/backtest/tourism`. It returns HTTP `409` with `status=blocked` when the independent-vintage minimum is not met, and it explicitly reports that a point-in-time daily price series is still required. The pure engine accepts events, daily prices, benchmark prices, event windows, and cost assumptions; it does not fetch or invent market prices.