๐ ํ๊ตญ์ด๋ก ๋ณด๊ธฐ
Toss Auto-Trading Dev Journal (Phase 5 ยท 15/15)
โ Previous: Phase 4 #14 | Next: not yet published
๐ก Phase 5 Summary
- Goal: Build a read-only web dashboard for trade, alert, and price history
- Key decision: Deliberately excluded any remote control of safety values like DRY_RUN โ that goes in the separate Telegram bot item instead
- Verification: 10 FastAPI TestClient tests, 88 total passing
By the time I wrapped up Phase 4, the bot was buying and selling on its own reasonably well. The problem was that checking “what is it actually doing right now” meant opening a log file by hand. Phase 5 exists to fix that, and the dashboard was the first piece.
Phase 5 was originally scoped as two items: a Telegram bot command interface and a web dashboard. The Telegram bot needs to control a running process from the outside, which is a much trickier design problem, so I started with the lower-risk dashboard.
Why fully read-only
The dashboard only queries the trades, alerts, and price_snapshots tables built up since Phase 3. I deliberately left out any way to change safety-critical values like DRY_RUN or target prices remotely โ that kind of control deserves a much more careful design, which I’m saving for the Telegram bot.
Building dashboard.py with FastAPI
I added a new dashboard.py with a main page (summary cards plus recent trades/alerts tables) and four JSON endpoints:
GET /api/tradesGET /api/alertsGET /api/price-snapshots/{symbol}GET /health
The UI is plain inline HTML/CSS with no frontend framework. Dashboard settings (host, port, display count) went into config.py instead of being hardcoded, with the host defaulting to 127.0.0.1 to keep it off the public network.
# config.py excerpt (masked values)
DASHBOARD_HOST = "127.0.0.1"
DASHBOARD_PORT = 8000
DASHBOARD_RECENT_LIMIT = 20
# dashboard.py excerpt
@app.get("/api/trades")
def get_trades(limit: int = DASHBOARD_RECENT_LIMIT):
# example symbol is masked
return query_trades(symbol="005930", limit=limit)
Testing without a running server
FastAPI’s TestClient lets you exercise endpoints in-memory without spinning up a real server. I wrote 10 tests in test_dashboard.py covering health check, empty-DB state, the limit parameter, newest-first ordering, and per-symbol filtering.
I also added a regression guard: a test that checks every registered route only allows the GET method, so if anyone ever accidentally adds a POST/PUT/DELETE endpoint that mutates state, the test suite fails immediately.
Troubleshooting: starlette.testclient requires the httpx2 package
Running pytest locally threw this:
RuntimeError: The starlette.testclient module requires the httpx2 package
Turns out the latest starlette version that FastAPI depends on now requires the new httpx2 package for its test client, instead of the older httpx. pip install httpx2 fixed it immediately, and I added it to requirements.txt.
Building a safe FastAPI dashboard comes down to scoping it to read-only endpoints, verifying with TestClient instead of a live server, and adding a dedicated regression test that checks routes only allow GET.
Final results
The full pytest suite passed all 88 tests (78 existing + 10 new), and I confirmed the safety-critical values were untouched. I also ran python dashboard.py for real and checked the dashboard in a browser.
What’s next
The remaining Phase 5 item is the Telegram bot command interface (/status, /holdings, /pause, etc.). Since it has to control a running monitoring loop from the outside, its interaction with the safety mechanisms needs especially careful design.
FAQ
Q1. Can the dashboard change trading settings directly?
No. It’s read-only by design โ it only displays trade, alert, and price history. There’s no feature to remotely change safety values like DRY_RUN or target prices.
Q2. Why build the web dashboard before the Telegram bot?
The Telegram bot needs to control a running process externally, which is riskier to design. Starting with the lower-risk read-only feature made more sense.
Q3. Why did the httpx2 error happen?
The latest starlette version FastAPI depends on now requires the httpx2 package for its test client instead of httpx. Installing httpx2 resolves it.
Q4. How is accidental state-mutation prevented?
A dedicated test checks that every registered route only allows GET, so any endpoint that could mutate state would fail the test suite immediately.
Pingback: FastAPI ์ฝ๊ธฐ์ ์ฉ ๋์๋ณด๋ ๊ตฌ์ถ๊ธฐ | ํ ์ค ์๋๋งค๋งค ๊ฐ๋ฐ๊ธฐ #15 - TS ํํธ: ์ฃผ์ ์๋๋งค๋งค ์ฐ๊ตฌ์
Pingback: File-Based Signals for Bot Pause Control | Toss Auto-Trading Dev Journal #16 - Orbit - Space & ETF Investing