Skip to content

Add FastAPI scanner service with 1Hz web dashboard#1

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1778304462-web-interface
Open

Add FastAPI scanner service with 1Hz web dashboard#1
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1778304462-web-interface

Conversation

@devin-ai-integration
Copy link
Copy Markdown

Summary

The repo was previously empty. This PR introduces a small FastAPI service that polls a public crypto exchange once per second, detects market "situations", and serves a self-contained web dashboard that refreshes the data every second (per the original request).

  • app/scanner.pyMarketScanner background task. Each tick it fetches the Binance 24h ticker, keeps a rolling in-memory history (HISTORY_LEN=120 samples) for the top TOP_N_BY_VOLUME=30 USDT pairs (selected on first tick), and produces a ScannerState snapshot.
  • Situation detector emits four kinds:
    • price_spike_up_1m / price_spike_down_1m — ≥1% move in the last ~60s.
    • volume_surge — last-minute quote volume ≥2× the 10-minute baseline (estimated from the cumulative 24h quoteVolume delta).
    • new_24h_high / new_24h_low — last price touches the daily extreme.
  • app/main.py — FastAPI app wiring the scanner into a lifespan, plus three routes: / (HTML), /api/state (JSON snapshot), /healthz.
  • app/static/{index.html,styles.css,app.js} — vanilla HTML/JS dashboard. app.js polls /api/state in a loop using the server-provided poll_interval_seconds (defaults to 1.0s), flashes price cells green/red on change, and renders a "situations" panel and a tickers table.
  • pyproject.toml / poetry.lock / README.md / .gitignore — project bootstrap (Poetry, Python ≥3.10).

Data source: I'm using https://data-api.binance.vision/api/v3/ticker/24hr (Binance's read-only data mirror) instead of api.binance.com because the main API returned HTTP 451 (geo-blocked) from the dev VM. The mirror exposes the same response shape.

Stack choice rationale: the user picked "На ваше усмотрение" — I went with FastAPI + plain HTML/JS so everything runs from a single uvicorn process with no build step.

Review & Testing Checklist for Human

  • Confirm the stack/UX is what you wanted. I picked FastAPI + vanilla HTML/JS. If you wanted React, a fancier charting UI, WebSocket push instead of HTTP polling, a different exchange (Bybit/OKX/KuCoin/Coinbase all returned 200 from the VM as alternatives), or different/more situation types, this is the moment to redirect.
  • Sanity-check the data source. data-api.binance.vision is Binance's read-only mirror; if you'll deploy this somewhere where api.binance.com is reachable, you may want to point BINANCE_TICKER_URL (or the MarketScanner(ticker_url=...) arg) back at the main API. Also confirm the once-per-second poll of the full 24h ticker payload (~600 KB, ~3000 symbols) is acceptable for your rate-limit budget — fetching only the tracked symbols would be cheaper.
  • Review the situation heuristics. A few are approximations worth a second look:
    • volume_surge uses deltas of the cumulative 24h quoteVolume as a per-minute proxy; that's only a rough estimate and the baseline window only fills once history has ≥10 minutes of samples.
    • new_24h_high / new_24h_low fire whenever price >= high_24h / price <= low_24h. Because the latest price is itself included in the exchange's 24h extreme, this can trigger every second when the market is at the rolling boundary. You may want a debounce or a "strictly new" check.
    • Spike detection uses the oldest history sample within the window, so before 60s of history accumulates the "1m" change is computed against fewer than 60s of data.
  • Run it end-to-end. poetry install && poetry run uvicorn app.main:app --port 8000, then open http://localhost:8000. Check that tickers populate, prices flash on change, the "Last update" timestamp ticks once per second, and curl http://localhost:8000/api/state returns a JSON snapshot with tickers and situations.

Notes

  • I smoke-tested locally: /healthz returns 200, /api/state returns 30 tickers with error: null after the mirror swap, and one new_24h_high situation fired immediately on the boundary check (see the second bullet above).
  • Existing .github/workflows/blank.yml is unchanged — CI is still just the scaffold "Hello world" job, so a green CI here doesn't validate the new code.
  • No automated tests were added in this PR; happy to follow up with pytest coverage of SymbolHistory.price_change_pct, recent_volume_delta, and _detect_situations if you want.

Link to Devin session: https://app.devin.ai/sessions/2eb7aa7344844b0a841c827cba7ab0fa
Requested by: @evgetos

Co-Authored-By: harlequincariotta <harlequincariotta@wshu.net>
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant