Building a Read-Only FastAPI Dashboard | Toss Auto-Trading Dev Journal #15

๐ŸŒ ํ•œ๊ตญ์–ด๋กœ ๋ณด๊ธฐ

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/trades
  • GET /api/alerts
  • GET /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.

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.

๐Ÿ‘‰ Next up: Phase 5(2) โ€” Telegram bot command interface (coming soon)

2 thoughts on “Building a Read-Only FastAPI Dashboard | Toss Auto-Trading Dev Journal #15”

  1. Pingback: FastAPI ์ฝ๊ธฐ์ „์šฉ ๋Œ€์‹œ๋ณด๋“œ ๊ตฌ์ถ•๊ธฐ | ํ† ์Šค ์ž๋™๋งค๋งค ๊ฐœ๋ฐœ๊ธฐ #15 - TS ํ€€ํŠธ: ์ฃผ์‹ ์ž๋™๋งค๋งค ์—ฐ๊ตฌ์†Œ

  2. Pingback: File-Based Signals for Bot Pause Control | Toss Auto-Trading Dev Journal #16 - Orbit - Space & ETF Investing

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top