Mock API server that replays historical GexBot market data with per-API-key sequential playback. Includes REST API, WebSocket streaming, CLI downloader, and scheduled download daemon.
GEXBOT-FAKER-API.mp4
NOTE: This only downloads and replays GexBot market data.
- REST API with Swagger UI documentation at
/docs - WebSocket streaming (5 hubs, Azure Web PubSub compatible)
- Per-API-key playback position tracking
- Hot reload data dates without server restart
- Sync Broadcast System for external service synchronization
- CLI for downloading historical data from GexBot
- Daemon for scheduled automatic downloads
- Push notifications via ntfy.sh on download completion
- Docker deployment ready
- Go 1.24+ - verify with
go version - just command runner - verify with
just --version - Docker - verify with
docker --version - GexBot API key with Quant Subscription (required for downloading data)
git clone git@github.com:dgnsrekt/gexbot-faker-api.git
cd gexbot-faker-api
# Copy example env and add your GexBot API key
cp gexbot.example.env .env
# Edit .env and set GEXBOT_API_KEY=your_api_key_hereCreate a custom config to select your tickers, packages, and categories:
cp configs/default.yaml configs/custom.yamlEdit configs/custom.yaml to customize:
- tickers: Enable/disable tickers (SPX, NDX, SPY, etc.)
- packages: Enable/disable data packages (state, classic, orderflow)
- categories: Enable/disable specific data types within each package
# Download last 7 days of market data (adjust number as needed)
just download-lookback 7Note: The downloader automatically skips weekends and market holidays.
With Docker (Recommended):
just up # Start API server and daemon
just logs # View logsOr run locally:
just serve-gex-faker # Build and run server
open http://localhost:8080/docs # Access API docsREST API serving historical GEX data with sequential playback per API key.
Endpoints (see /docs for full reference):
/{ticker}/classic/{aggregation}- Classic GEX chain data/{ticker}/state/{type}- State GEX profiles and Greeks/{ticker}/orderflow/orderflow- Orderflow metrics/available-data/{date}- Discover available data for a date/download/{date}/{ticker}/links- Get all download links for a date/ticker/download/{date}/{ticker}/classic/{aggregation}- Download classic data/download/{date}/{ticker}/state/{type}- Download state data/download/{date}/{ticker}/orderflow- Download orderflow data/negotiate- WebSocket connection URLs/health,/tickers,/available-dates- Server info/reload-date- Hot reload data for a different date/reset-cache- Reset playback positions/seek-to-timestamp- Seek positions to a specific timestamp
Key behavior: Each API key maintains independent playback position. Data advances on each request.
Switch data dates at runtime without restarting the server:
# Reload to a different date
curl -X POST http://localhost:8080/reload-date \
-H "Content-Type: application/json" \
-d '{"date": "2025-12-04"}'Response:
{
"status": "success",
"previous_date": "2025-11-28",
"new_date": "2025-12-04",
"loaded_at": "2025-12-27T15:30:00Z",
"files_loaded": 45
}Behavior:
- Validates the date exists before unloading current data
- Pauses WebSocket streaming during reload
- Resets all cache positions to 0 for clean playback
- Returns 400 for invalid/missing dates, 409 if reload already in progress
Control playback positions for testing and synchronization.
Reset positions:
# Reset all positions for an API key
curl -X POST "http://localhost:8080/reset-cache?key=mykey"
# Reset ALL positions (all keys)
curl -X POST http://localhost:8080/reset-cacheSeek to timestamp:
# Seek all positions for an API key to a specific timestamp
curl -X POST http://localhost:8080/seek-to-timestamp \
-H "Content-Type: application/json" \
-d '{"timestamp": 1767191500, "key": "mykey"}'Response:
{
"status": "success",
"message": "Seeked 45 positions to timestamp 1767191500",
"positions_set": 45,
"details": [
{"data_key": "SPX/classic/gex_zero", "index": 98, "timestamp": 1767191500}
]
}Use case: Sync with external services by seeking to a broadcast timestamp from the Sync Broadcast System.
Real-time data streaming via 5 specialized hubs:
| Hub | Data Type |
|---|---|
orderflow |
DEX, GEX, convexity, vanna, charm metrics |
classic |
Classic GEX chain |
state_gex |
State GEX profiles |
state_greeks_zero |
Greeks (0DTE) |
state_greeks_one |
Greeks (1DTE+) |
See WEBSOCKET.md for protocol details.
SSE-based market time broadcast for synchronizing external services with the faker's playback position. External services subscribe to receive position updates and can seek their own data to match.
Endpoint: GET /sync/stream?key={api-key}
Enable via environment:
SYNC_BROADCAST_SYSTEM_ENABLED=trueExample subscription:
curl -N "http://localhost:8080/sync/stream?key=my-api-key"Response (SSE stream):
event: snapshot
id: 1
data: {"broadcaster_id":"gexbot-faker","data_date":"2025-12-05","cache_mode":"exhaust","timestamp":1766870060074,"sequence":1,"positions":[{"cache_key":"SPX/classic/my-a****","index":42,"data_length":23375,"data_timestamp":1764945003,"exhausted":false}]}
event: batch
id: 2
data: {...positions updated every interval...}
Position fields:
cache_key: Cache key path with masked API key (REST or WebSocket format)index: Current playback positiondata_length: Total records availabledata_timestamp: Unix timestamp from the data at current positionexhausted: True if position has reached end (exhaust mode only)
Use case: Other faker-like services with timestamp-indexed data can subscribe and seek their own data to match the broadcaster's market time.
Use quant-python-sockets to connect to the WebSocket feeds.
To use with faker API, change main.py line 36:
# Original (production):
BASE_URL = "https://api.gexbot.com"
# Change to (faker):
BASE_URL = "http://localhost:8080"Then run:
export GEXBOT_API_KEY=test123 # Faker accepts any key
python main.pyDownload historical data from the GexBot API.
# Single date
./bin/gexbot-downloader download 2025-11-14
# Date range
./bin/gexbot-downloader download 2025-11-01 2025-11-14
# Custom tickers/packages
./bin/gexbot-downloader download --tickers SPX,NDX --packages state 2025-11-14
# Preview (dry run)
./bin/gexbot-downloader download --dry-run 2025-11-14Automated daily downloads with market day awareness.
| Variable | Default | Description |
|---|---|---|
DAEMON_SCHEDULE_HOUR |
20 | Hour to run (0-23) |
DAEMON_SCHEDULE_MINUTE |
0 | Minute to run |
DAEMON_TIMEZONE |
America/New_York | Timezone |
DAEMON_RUN_ON_STARTUP |
true | Check/download on start |
Both the daemon and CLI downloader support push notifications via ntfy.sh when downloads complete or fail.
| Variable | Default | Description |
|---|---|---|
NTFY_ENABLED |
false | Enable push notifications |
NTFY_SERVER |
https://ntfy.sh | ntfy server URL (supports self-hosted) |
NTFY_TOPIC |
(required) | Topic name for notifications |
NTFY_PRIORITY |
default | Priority: min, low, default, high, urgent |
NTFY_TAGS |
package | Comma-separated emoji tags |
NTFY_TOKEN |
(optional) | Access token for private topics |
Quick setup:
# In .env
NTFY_ENABLED=true
NTFY_TOPIC=my-gexbot-downloadsSubscribe to notifications at https://ntfy.sh/my-gexbot-downloads or use the ntfy app.
| Variable | Default | Description |
|---|---|---|
PORT |
8080 | HTTP server port |
DATA_DIR |
./data | Data directory path |
DATA_DATE |
latest | Date to load (YYYY-MM-DD or "latest") |
DATA_MODE |
memory | memory (fast) or stream (low RAM) |
CACHE_MODE |
exhaust | exhaust (404 at end) or rotation (loop) |
WS_ENABLED |
true | Enable WebSocket streaming |
WS_STREAM_INTERVAL |
1s | Broadcast interval |
WS_GROUP_PREFIX |
blue | Prefix for WebSocket group names |
SYNC_BROADCAST_SYSTEM_ENABLED |
false | Enable SSE sync broadcast endpoint |
SYNC_BROADCAST_SYSTEM_ID |
hostname | Broadcaster identifier |
SYNC_BROADCAST_SYSTEM_INTERVAL |
1s | Position broadcast interval |
Create configs/default.yaml or set GEXBOT_API_KEY:
api:
api_key: "${GEXBOT_API_KEY}"
timeout_sec: 300
retry_count: 3
download:
workers: 3
rate_per_second: 2
resume_enabled: true
output:
directory: "data"
auto_convert_to_jsonl: true| Package | Categories |
|---|---|
| state | gex_full, gex_zero, gex_one, delta_zero, gamma_zero, delta_one, gamma_one, vanna_zero, vanna_one, charm_zero, charm_one |
| classic | gex_full, gex_zero, gex_one |
| orderflow | orderflow |
Indexes: SPX, NDX, RUT, VIX ETFs: SPY, QQQ, IWM Futures: ES_SPX, NQ_NDX
data/
└── 2025-11-14/
└── SPX/
├── classic/
│ └── gex_zero.jsonl
├── state/
│ ├── gex_zero.jsonl
│ └── delta_zero.jsonl
└── orderflow/
└── orderflow.jsonl
# Build
just build # Downloader
just build-gex-faker # Server
# Code generation
just generate-gex-faker-api-spec # OpenAPI → Go
just generate-protos # Protobuf → Go
# Test and lint
just test
just lint
# Docker
just up # Start containers
just down # Stop containers
just logs # View logsSee LICENSE file.
Telegram = Twitter = Tradingview = Discord = @dgnsrekt
Email = dgnsrekt@pm.me
Note: It may take me a few days to reply.