A high-performance asynchronous Python trading bot for Binance, featuring dynamic trailing take-profit strategies, regime detection, Donchian channel gating, and Ed25519 authentication.
Code Quality: Pragmatic bot script checks pass - balancing strict type checking with real-time trading requirements
Topics: trading-bot binance cryptocurrency algorithmic-trading python asyncio websocket trailing-stop donchian-channels ed25519 telegram-bot market-making quantitative-trading technical-indicators automated-trading
- System Architecture
- Architectural Decisions
- Screenshots
- Features
- Setup
- Usage
- Project Structure
- Development
graph TB
subgraph "External Systems"
BINANCE[Binance WebSocket API]
TELEGRAM[Telegram Bot API]
end
subgraph "Bot Core"
MAIN[Main Trading Loop]
AUTH[Ed25519 Authentication]
CONFIG[Configuration Validator]
LOGGER[Logging System]
end
subgraph "Market Data Layer"
WS_MARKET[Market Stream]
WS_ACCOUNT[Account Stream]
WS_ORDERS[Order Management]
KLINE[Kline Historical Fetch]
end
subgraph "Strategy Components"
REGIME[Regime Detection]
DONCHIAN[Donchian Channels]
TRAILING[Trailing Take-Profit]
HARDSTOP[Hard Stop Logic]
end
subgraph "Order Execution"
MAKER[Persistent Maker Exit]
REPLACE[Order Replace API]
JUMPSTART[Jumpstart Balance Init]
end
BINANCE -->|WS Connection| AUTH
AUTH -->|Authenticated| MAIN
CONFIG -->|Validate| MAIN
LOGGER -.->|Log Events| MAIN
MAIN -->|Subscribe| WS_MARKET
MAIN -->|Subscribe| WS_ACCOUNT
MAIN -->|Fetch History| KLINE
WS_MARKET -->|BookTicker| REGIME
WS_ACCOUNT -->|Balance Updates| REGIME
KLINE -->|Historical Data| DONCHIAN
REGIME -->|BASE/QUOTE State| TRAILING
DONCHIAN -->|Channel Levels| HARDSTOP
DONCHIAN -->|Gating Logic| HARDSTOP
TRAILING -->|Exit Signal| MAKER
HARDSTOP -->|Stop Triggered| MAKER
MAKER -->|Place Order| REPLACE
REPLACE -->|Execute| WS_ORDERS
WS_ORDERS -->|Confirm| BINANCE
JUMPSTART -.->|Initialize| WS_ACCOUNT
MAIN -.->|Notifications| TELEGRAM
style MAIN fill:#4A90E2
style REGIME fill:#7ED321
style DONCHIAN fill:#F5A623
style HARDSTOP fill:#D0021B
style MAKER fill:#50E3C2
This system was engineered for 24/7 autonomous reliability on low-cost infrastructure. The architecture prioritizes low latency and operational simplicity over microservice complexity.
- Decision: Built using Python's native
asyncioevent loop rather than multi-threading. - Reasoning: The workload is heavily I/O bound (waiting for WebSocket frames). Threading introduces Context Switching overhead and Race Conditions.
asyncioallows us to handle high-frequency Market Data streams and User Data streams concurrently on a single core with sub-100ms reaction time.
- Decision: Deployed as a native
systemdservice rather than a Docker container. - Reasoning: For a single-node bot, Docker adds network bridging overhead and complexity in persistence.
- Auto-Restart: Configured with
Restart=alwaysto recover instantly from crashes. - Logging: Native integration with
journaldallows for centralized log rotation without external agents. - Resource Management:
systemdslices set strict CPU/Memory quotas to prevent the bot from starving the host OS.
- Auto-Restart: Configured with
- Decision: Implemented Ed25519 asymmetric key authentication.
- Reasoning: HMAC relies on a shared secret; if compromised, it allows full request forgery. Ed25519 uses asymmetric cryptography, signing requests with a private key that never leaves memory while the server verifies with a public key. This eliminates shared-secret risks and enables safer, non-disruptive key rotation for long-running production systems.
- Decision: Volatile in-memory state with "Fire-and-Forget" updates.
- Reasoning: DB writes introduce latency. The bot is designed to be stateless on restart and fully event-driven. Instead of querying REST APIs (which block and hit rate limits), it rebuilds state via WebSocket Reconciliation: triggering an immediate push of fresh Account and Order snapshots from the User Data Stream upon connection, ensuring synchronization is instant and purely stream-based.
The bot runs continuously on cloud VPS using systemd for automatic startup, restart on failure, and 24/7 operation. Real-time trade alerts and regime changes are delivered via Telegram.
-
Asynchronous Architecture — Built on
asyncioandwebsocketsfor low-latency market data processing and concurrent stream handling. -
Secure Authentication — Uses Ed25519 key pairs for secure, non-expiring API authentication with Binance WebSocket API.
-
Resilience — Auto-reconnect logic for WebSocket streams with exponential backoff and configurable retry limits.
-
Cross-Platform — Supports both Windows and Linux with native hotkey listener implementation using threading.
-
Trailing Take-Profit — Dynamic callback-based profit-taking with exponential decay from start to min factor. Automatically adjusts profit targets as gains increase, locking in profits while allowing room for continued upside.
-
Regime Detection and Auto-Compounding — Automatically switches between BASE (inventory holding) and QUOTE (cash holding) modes:
- Fire and Forget: Balance updates on every change via WebSocket user data stream
- All-In Compounding: Perfect for bull rallies - reinvests entire portfolio each cycle
- No Pre-Session Balance Required: Jumpstart orders initialize balance snapshots at startup
-
Jumpstart Balance Initialization — Places deep out-of-market orders (+/- 10% from current price) to trigger Binance's user data stream balance snapshot:
- Solves Cold Start Problem: User data stream only sends updates on balance changes
- Safe and Non-Intrusive: Orders immediately cancelled after triggering snapshot
- Session Independence: No need to manually track balances between restarts
-
Hard Stop with Donchian Gating — Intelligent stop-loss system with automatic re-entry gating:
- Volatility-Aware: Uses Donchian Channels (configurable window) to adapt to market conditions
- Re-Anchor on Stop: Resets anchor/high values after exit for fresh cycle
- Regime-Specific Behavior:
- BASE: Flushes all inventory to cash (persistent SELL orders at best bid)
- QUOTE: Pauses trading and holds cash position
- Smart Re-Entry: Gate opens only when price crosses mid-channel in favorable direction
- After BASE exit: Waits for price to rally above mid-channel
- After QUOTE pause: Waits for price to drop below mid-channel
-
Configurable Min Gain with Fee Support — Dynamic minimum gain threshold considers multiple factors:
- Static Fraction: User-configurable minimum profit percentage
- Fee + Buffer: Adjusts for symbol-specific fee structure (supports 0% maker fees)
- Donchian Multiplier: Scales with channel width for volatility adaptation
- Takes Maximum: Uses strictest requirement to ensure profitable trades
-
Persistent Maker Exit with Order Chasing — Leverages Binance's native
order.replaceAPI for aggressive price-chasing:- Post-Only Orders: Always maker orders (no fees on ETHFDUSD and similar pairs)
- clientOrderId Overwrite: Replaces same order ID repeatedly, no order spam
- Best Price Tracking: Updates every loop iteration to chase best bid/ask
- Guaranteed Fill: Persists until complete fill or manual override
-
Donchian Channels (Active) — Primary indicator for gating logic and volatility adaptation:
- Price Squeeze Detection: Reacts immediately to narrowing price ranges (consolidation)
- Breakout Signals: Triggers on channel breakouts for entry/exit timing
- Dynamic Gating: Uses mid-channel as support/resistance for re-entry logic
- Better Than ATR For: Price compression, consolidation phases, and range-bound markets
-
ATR (Average True Range) - Ready Function Only — Complete implementation available but currently passive:
- Temporal Volatility: Measures price movement magnitude over time
- Lagging Nature: Reacts after volatility has occurred, not predictive
- Use Case: Better suited for position sizing and stop-loss distance calculation
- Why Donchian Preferred:
- ATR only responds to historical volatility (backward-looking)
- Donchian reacts instantly to price action and consolidation (forward-looking)
- Price squeezes (narrow channels) often precede major moves
- Channel breakouts provide clear directional signals
Technical Note: ATR functions (
compute_atr,compute_atr_from_rows, etc.) are fully implemented insrc/trailingedge/indicators/atr.pyand ready for integration if position sizing or adaptive stop-loss logic is needed.
-
Cloud-Hosted 24/7 Operation — Production-ready systemd service configuration for unattended VPS deployment:
- Auto-Start on Boot: Service automatically starts after server reboot
- Auto-Restart on Failure: Configurable restart policy with exponential backoff
- Resource Management: Memory and CPU limits with systemd cgroups
- Log Aggregation: Integrated with journald for centralized logging and monitoring
- Service Management: Standard systemctl commands for start/stop/status control
- Graceful Shutdown: Proper signal handling for clean termination
-
Telegram Notifications — Integrated alerts for regime flips, order execution, and critical events with broadcast support to multiple recipients.
-
Comprehensive Logging — Session-timestamped file logs with configurable levels (console + file). Each bot run creates a new log file for easy session tracking.
-
Configuration Validation — Startup validation ensures all settings are valid before trading. Checks trading pair constraints, fee settings, API credentials, and secret files.
-
Manual Override — Hotkey support ('x' + Enter) for operator-triggered exits during runtime without restarting the bot.
- Python 3.10 or higher
- uv (recommended for dependency management)
- Binance Account with API Keys (Ed25519 keys required)
-
Clone the repository:
git clone https://github.com/adityonugrohoid/trailing-edge.git cd trailing-edge -
Sync dependencies:
uv sync
-
Setup Environment:
Copy the example configuration:
cp .env.example .env
Edit
.envand add your credentials:BINANCE_ED25519_API_KEY- Your Binance API keyBINANCE_ED25519_PRIV_PATH- Path to your Ed25519 private key (default:secrets/ed25519-priv.pem)TELEGRAM_BOT_TOKEN- Your Telegram bot tokenTELEGRAM_CHAT_ID- Your personal Telegram chat IDTELEGRAM_GROUP_CHAT_ID_1- (Optional) Group chat ID for notificationsTELEGRAM_GROUP_CHAT_ID_2- (Optional) Additional group chat ID
-
Setup Secrets:
Generate an Ed25519 key pair and place them in the
secrets/directory:secrets/ed25519-priv.pemsecrets/ed25519-pub.pem
Note: Ensure
secrets/is ignored by git (it is by default).
Start the trading bot:
# Using uv
python -m uv run trailing-edge
# Or directly with python (if venv is active)
python -m trailingedge.mainThe bot will:
- Validate configuration
- Authenticate to Binance WebSocket API
- Fetch historical klines and compute baseline indicators
- Subscribe to market and account streams
- Initialize balance snapshot with jumpstart orders
- Start the main trading loop
Press Ctrl-C to stop the bot gracefully.
For 24/7 unattended operation on Linux VPS:
-
Create systemd service file:
sudo nano /etc/systemd/system/trailing-edge.service
-
Add service configuration:
[Unit] Description=Trailing Edge Trading Bot After=network-online.target Wants=network-online.target [Service] Type=simple User=your-username WorkingDirectory=/path/to/trailing-edge Environment="PATH=/home/your-username/.local/bin:/usr/bin:/bin" EnvironmentFile=/path/to/trailing-edge/.env ExecStart=/home/your-username/.local/bin/uv run python -m trailingedge.main Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
-
Enable and start service:
sudo systemctl daemon-reload sudo systemctl enable trailing-edge.service sudo systemctl start trailing-edge.service -
Monitor bot status:
# Check service status sudo systemctl status trailing-edge.service # View live logs sudo journalctl -u trailing-edge.service -f # View recent logs sudo journalctl -u trailing-edge.service -n 100
The project includes a comprehensive test suite covering authentication, order logic, and indicators.
# Run all tests
python -m uv run pytest
# Run with coverage report
python -m uv run pytest --cov=src/trailingedge
# Run specific test file
python -m uv run pytest tests/test_main_logic.py -vsrc/trailingedge/
├── auth/ # Ed25519 authentication manager
│ ├── __init__.py
│ └── manager.py # Session authentication and signing
├── websocket/ # WebSocket streams (Market, Account, Orders)
│ ├── __init__.py
│ ├── account.py # User data stream subscription
│ ├── account_stream.py # Balance update processing
│ ├── market_fetch.py # Historical kline fetching
│ ├── market_stream.py # Real-time market data streams
│ └── orders.py # Order placement and management
├── indicators/ # Technical indicators (ATR, Donchian)
│ ├── __init__.py
│ ├── atr.py # Average True Range calculations
│ └── donchian.py # Donchian Channel calculations
├── notifications/ # Telegram integration
│ ├── __init__.py
│ └── telegram.py # Message sending and broadcasting
├── config.py # Trading parameters and constants
├── config_validator.py # Startup configuration validation
├── logging_config.py # Logging setup and configuration
└── main.py # Main entry point and trading loop
Linting:
uv run ruff check .Formatting:
uv run ruff format .Type Checking:
uv run mypy .Trading parameters can be adjusted in src/trailingedge/config.py:
- Trading pair settings (SYMBOL, BASE_ASSET, QUOTE_ASSET)
- Order constraints (MIN_QTY, MIN_NOTIONAL, LOT_SIZE)
- Trailing stop parameters (START_FACTOR, MIN_FACTOR)
- Donchian channel settings (WINDOW, SHIFT, GAIN_MULTIPLIER)
- Fee and buffer settings
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
MIT License - see LICENSE for details.
Trading cryptocurrencies carries significant risk. This bot is provided for educational purposes only. Use at your own risk. The authors are not responsible for any financial losses incurred while using this software.
Adityo Nugroho

