A newer version of the Streamlit SDK is available: 1.62.0
Architecture Migration Plan: Local Server + HF Client
Date: 2026-03-19
Current Architecture (Problem)
HuggingFace Space
βββ live_trading_multi.py (bot, all logic)
βββ src/ui/api_server.py (Flask REST API, port 5001)
βββ src/ui/app.py (Streamlit UI, port 8501)
βββ calls http://127.0.0.1:5001/api/*
Problems:
- Binance Testnet geo-blocked from HuggingFace's datacenter (HTTP 451)
- Cloudflare Workers proxy is unreliable and adds latency
- Bot cannot reach testnet.binance.vision from HF
Target Architecture (Solution)
Local Machine
βββ live_trading_multi.py (bot, trading logic)
βββ src/ui/api_server.py (Flask REST API, port 5001)
βββ [tunnel tool] (exposes :5001 as public HTTPS URL)
βββ e.g. https://abc123.ngrok.io β localhost:5001
HuggingFace Space
βββ src/ui/app.py (Streamlit UI, CLIENT only)
βββ calls $API_SERVER_URL/api/*
βββ API_SERVER_URL = https://abc123.ngrok.io (HF Secret)
Benefits:
- Bot runs locally β direct Binance testnet access (no geo-blocks)
- HF Space becomes a pure UI/client, no trading logic
- Testnet tab works via server-side
testnet_server.py(direct connection locally)
Implementation Plan
Step 1: Configure Flask API Server for Remote Access
File: src/ui/api_server.py
Changes:
- Enable CORS properly so HuggingFace domain can call the API
- Add a
/api/pinghealth endpoint (lightweight check for client) - Add startup banner showing the public URL
from flask_cors import CORS
CORS(app, origins=["*"]) # Allow HF and any origin
File: start_local_server.sh (new)
A convenience script to:
- Start the Flask API server (port 5001)
- Optionally start a tunnel (ngrok or Cloudflare)
- Print the public URL to copy into HF Secrets
Step 2: Make Streamlit UI Configurable
File: src/ui/app.py
Changes:
- Replace all hardcoded
http://127.0.0.1:5001withget_api_url()helper get_api_url()reads fromos.environ.get('API_SERVER_URL', 'http://127.0.0.1:5001')- Show connection status in UI (connected/disconnected + server URL)
- Graceful degradation when server is unreachable (not just red error)
Occurrences of hardcoded URL to replace:
- Line 1183:
requests.get('http://127.0.0.1:5001/api/state', ...) - Line 1221:
requests.get(f'http://127.0.0.1:5001/api/market?symbol=...', ...) - Line 1427:
requests.get('http://127.0.0.1:5001/api/state', ...) - Line 1438:
requests.get(f'http://127.0.0.1:5001/api/market?symbol=...', ...) - Line 1459:
requests.get('http://127.0.0.1:5001/api/trades', ...) - Line 1539:
requests.get('http://127.0.0.1:5001/api/state', ...) - Line 1553:
requests.get('http://127.0.0.1:5001/api/trades', ...)
Step 3: Fix Testnet Tab
File: src/ui/testnet_server.py
Changes:
- Remove the HuggingFace detection/warning block (it no longer applies)
- Remove Cloudflare proxy fallback (not needed locally)
- Simplify to direct
BinanceConnectorwithtestnet=True - Server now calls
https://testnet.binance.visiondirectly
File: src/ui/app.py (testnet tab section)
Changes:
- Always use server-side (
testnet_server.py) since server runs locally - Remove the client-side JS fallback (optional, can keep as backup)
Step 4: Add Tunnel Support (ngrok)
File: requirements.txt
Add: pyngrok>=7.0.0
File: start_local_server.py (new script)
# Start Flask server with optional ngrok tunnel
# Usage:
# python start_local_server.py # local only
# python start_local_server.py --tunnel # with ngrok tunnel
Logic:
- Start
api_server.pyin a background thread - If
--tunnel: start pyngrok tunnel, print public URL - Print instructions to add URL to HF Secrets
Step 5: Integration Tests
File: tests/test_integration/test_server_client.py (new)
Tests:
test_server_starts()- Flask server starts,/healthreturns 200test_api_state()-/api/statereturns valid JSONtest_api_trades()-/api/tradesreturns listtest_api_market()-/api/market?symbol=BTCUSDTreturns market datatest_cors_headers()- Response includes CORS headerstest_binance_testnet_connectivity()- testnet.binance.vision ping returns 200test_binance_testnet_with_keys()- API keys work for account balancetest_client_url_configurable()-API_SERVER_URLenv var is read correctlytest_end_to_end_data_flow()- Bot saves state β API serves it β client reads it
Step 6: Update HuggingFace Space
File: src/ui/app.py (already updated in Step 2)
HF Space Secrets to add:
API_SERVER_URL=<ngrok-or-tunnel-url>- Keep existing:
BINANCE_TESTNET_API_KEY,BINANCE_TESTNET_API_SECRET, etc.
File: README.md or HF Space README - update deployment instructions
Push target: Chen4700/drl-trading-bot-dev (DEV space only)
File Changes Summary
| File | Action | Description |
|---|---|---|
src/ui/api_server.py |
Modify | Enable CORS, add /api/ping |
src/ui/app.py |
Modify | Replace hardcoded localhost:5001 with API_SERVER_URL env var |
src/ui/testnet_server.py |
Modify | Remove proxy/HF-specific code, direct testnet access |
start_local_server.py |
Create | Convenience script to start server + optional tunnel |
tests/test_integration/test_server_client.py |
Create | Integration tests |
tests/test_integration/__init__.py |
Create | Package init |
requirements.txt |
Modify | Add pyngrok>=7.0.0 |
.env.example |
Modify | Add API_SERVER_URL example |
Blockers & Solutions
Blocker 1: HuggingFace Space Needs Public URL
Problem: The local Flask server on :5001 is not reachable from HF by default.
Solution: Use ngrok (pyngrok) or Cloudflare Tunnel (cloudflared) to expose it.
- ngrok: requires account but easy setup, free tier works
- Cloudflare Tunnel: free, persistent, but requires
cloudflaredbinary - Chosen: ngrok via
pyngrok(Python package, easiest to automate)
Blocker 2: CORS on Flask
Problem: HuggingFace serves the Streamlit app from a different origin.
Solution: Add flask-cors (already in requirements) and configure CORS(app, origins=["*"]).
Blocker 3: Testnet Keys in HF Secrets vs .env
Problem: The testnet tab reads keys from os.getenv() β works both locally (.env) and on HF (secrets).
Solution: No change needed. Keep reading from env vars.
Blocker 4: Streamlit on HF can't do ngrok
Problem: Streamlit on HF is the CLIENT, not the server β it doesn't need ngrok. Solution: ngrok only runs on the LOCAL server side.
Execution Order
- Write PLAN.md (this file)
- Modify
src/ui/api_server.pyβ Enable CORS + add /api/ping - Modify
src/ui/app.pyβ Replace hardcoded URLs withAPI_SERVER_URL - Modify
src/ui/testnet_server.pyβ Remove proxy/HF blocks (direct testnet) - Create
start_local_server.pyβ Server startup script with optional ngrok - Add
pyngroktorequirements.txt - Add
API_SERVER_URLto.env.example - Create integration tests (
tests/test_integration/test_server_client.py) - [~] Run tests locally β BLOCKED: this machine has no project venv (no flask/dotenv/etc.)
- Static checks passed: all 5 modified files parse cleanly (ast.parse)
- Logic check passed:
get_api_url()default/custom/trailing-slash behavior verified - Storage check passed: JsonFileStorage save/load verified (when deps available)
- Binance testnet check passed: testnet.binance.vision/api/v3/ping reachable locally
- Full pytest suite must be run in the project's virtualenv:
pip install -r requirements.txt && pytest tests/test_integration/ -v
- Push to
Chen4700/drl-trading-bot-dev