Planning-only commit: no application code yet. The plan specifies a realtime /ES chart that derives moving averages and trendlines across multiple timeframes, projects them onto one chart in a shared (time, price) plane, and alerts when levels from different timeframes converge. Key findings that shaped it, all verified against source rather than assumed: - Schwab streams realtime futures fine (CHART_FUTURES, LEVEL_ONE_FUTURES) but provides no futures price *history* at all. An account does not change this; it is an API-surface limit. - Yahoo's chart endpoint needs no key and has exactly what Schwab lacks: ~730d of hourly ES=F (~750 sessions), enough to warm a 200DMA from startup. So it serves as both the no-keys dev source and the history seeder, behind one MarketDataSource protocol. - Yahoo anchors daily bars to midnight ET while the CME session runs 18:00-17:00 ET, so daily bars are built from hourly using our own session rules instead. - Lightweight Charts v5 replaced addCandlestickSeries() with addSeries(CandlestickSeries, ...); most tutorials online are v4. Build order defers judgment-heavy work: moving averages first (fully deterministic), then confluence scoring, then hand-drawn trendlines. Automatic trendline detection comes last, tuned against the hand-drawn lines as ground truth. Includes a real trimmed Yahoo response as a test fixture; it contains a null in the OHLC arrays, which is the parsing case that needs handling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
66 lines
2.2 KiB
Markdown
66 lines
2.2 KiB
Markdown
# chart
|
|
|
|
FastAPI backend + Vue 3 (from CDN, no build step) served at
|
|
<https://chart.amow.com>.
|
|
|
|
Currently a placeholder: the frontend calls `/api/hello` and prints the JSON.
|
|
|
|
**Where this is going:** a realtime `/ES` chart that derives trendlines and moving
|
|
averages across many timeframes and alerts when they converge. The full spec lives in
|
|
[`docs/IMPLEMENTATION_PLAN.md`](docs/IMPLEMENTATION_PLAN.md) — read it before writing
|
|
code; it records decisions and verified API facts that are expensive to rediscover.
|
|
|
|
## Local development
|
|
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
Then open <http://localhost:8000>. Override the host port with
|
|
`PORT=8010 docker compose up` if 8000 is busy — on the VPS itself it always is,
|
|
that's the Coolify UI. The source tree is bind-mounted and uvicorn
|
|
runs with `--reload`, so edits to `main.py` or `static/` take effect without a
|
|
rebuild. Rebuild only when `requirements.txt` changes.
|
|
|
|
Without Docker:
|
|
|
|
```bash
|
|
python3 -m venv .venv && . .venv/bin/activate
|
|
pip install -r requirements.txt
|
|
uvicorn main:app --reload
|
|
```
|
|
|
|
## Layout
|
|
|
|
| Path | Purpose |
|
|
|---|---|
|
|
| `main.py` | FastAPI app — JSON under `/api`, serves the SPA at `/` |
|
|
| `static/` | `index.html`, `app.js`, `style.css` — Vue 3 loaded from unpkg |
|
|
| `requirements.txt` | Python deps |
|
|
| `Procfile` | Start command; **nixpacks needs this** or the deploy has nothing to run |
|
|
| `Dockerfile.dev`, `docker-compose.yml` | Local dev only — production does not use them |
|
|
|
|
## Deployment
|
|
|
|
Push to `main` → Forgejo webhook → Coolify rebuilds with nixpacks → live in
|
|
roughly 25 seconds.
|
|
|
|
```bash
|
|
git push
|
|
```
|
|
|
|
Two things to know before changing the deploy config:
|
|
|
|
- The Coolify domain is registered as `https://chart.amow.com:8000`. The port
|
|
suffix is how Coolify decides the Traefik target port; drop it and every
|
|
request 502s while the container looks perfectly healthy. It does not appear
|
|
in the public URL.
|
|
- Ignore a 502 in the first minute after a deploy — that's the rolling container
|
|
swap, and it clears on its own.
|
|
|
|
Manual redeploy:
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $(cat ~/.coolify-token)" \
|
|
"http://127.0.0.1:8000/api/v1/deploy?uuid=dgvch0xqv8uvjfor7dl8bwl9&force=true"
|
|
```
|