A professional, production-ready CLI trading bot for Binance Futures Testnet (USDT-M) built with Python 3.x.
Supports Market, Limit, and Stop-Limit orders with full input validation, structured rotating logs, and clean separation between the API layer and the CLI layer.
trading_bot/
├── bot/
│ ├── __init__.py # Package exports
│ ├── client.py # Binance Futures Testnet client wrapper
│ ├── orders.py # Order placement logic (market / limit / stop-limit)
│ ├── validators.py # Input validation — raises clear ValueError on bad input
│ └── logging_config.py # Rotating file + console logging setup
├── cli.py # CLI entry point (argparse)
├── requirements.txt # Runtime dependencies
├── .env # API credentials ← fill this in before running
├── .gitignore
└── README.md
- Visit https://testnet.binancefuture.com
- Register / log in
- Go to API Management → Generate Key
- Copy your API Key and Secret Key
# Windows
python -m venv venv
venv\Scripts\activate
# macOS / Linux
python -m venv venv
source venv/bin/activatepip install -r requirements.txtEdit .env and paste your testnet keys:
BINANCE_API_KEY=your_testnet_api_key_here
BINANCE_API_SECRET=your_testnet_api_secret_here
BINANCE_TESTNET_URL=https://testnet.binancefuture.comSecurity:
.envis in.gitignoreand must never be committed.
All commands are run from the trading_bot/ directory (where cli.py lives).
python cli.py --help
python cli.py place-order --helpExecutes immediately at the best available price.
python cli.py place-order --symbol BTCUSDT --side BUY --type MARKET --quantity 0.001Expected output:
=== ORDER REQUEST ===
Symbol: BTCUSDT
Side: BUY
Type: MARKET
Quantity: 0.001
=== ORDER RESPONSE ===
Order ID: 18164753457
Status: FILLED
Executed Qty: 0.001
Avg Price: 58,423.60
✅ Order placed successfully!
python cli.py place-order --symbol BTCUSDT --side SELL --type MARKET --quantity 0.001Rests on the order book until the price reaches 50000 (GTC).
python cli.py place-order --symbol BTCUSDT --side BUY --type LIMIT --quantity 0.001 --price 50000Expected output:
=== ORDER REQUEST ===
Symbol: BTCUSDT
Side: BUY
Type: LIMIT
Quantity: 0.001
Price: 50,000.00
=== ORDER RESPONSE ===
Order ID: 18164806068
Status: NEW
Executed Qty: 0.0000
Avg Price: 50,000.00 (order open — not yet filled)
✅ Order placed successfully!
python cli.py place-order --symbol BTCUSDT --side SELL --type LIMIT --quantity 0.001 --price 150000Triggers a BUY limit when price rises above stop_price.
Use when the current market price is below the stop price (breakout entry).
python cli.py place-order --symbol BTCUSDT --side BUY --type STOP_LIMIT --quantity 0.002 --price 75000 --stop-price 74000Expected output:
=== ORDER REQUEST ===
Symbol: BTCUSDT
Side: BUY
Type: STOP_LIMIT
Quantity: 0.002
Price: 75,000.00
Stop Price: 74,000.00
=== ORDER RESPONSE ===
Order ID: 18165012340
Status: NEW
Executed Qty: 0.0000
Avg Price: 75,000.00 (order open — not yet filled)
Stop Price: 74,000.00
✅ Order placed successfully!
Triggers a SELL limit when price falls below stop_price.
Use when current market price is above the stop price (stop-loss on a long position).
python cli.py place-order --symbol BTCUSDT --side SELL --type STOP_LIMIT --quantity 0.002 --price 43000 --stop-price 44000The bot validates all inputs before any network call:
# Invalid side
python cli.py place-order --symbol BTCUSDT --side HOLD --type MARKET --quantity 0.001
# ❌ Validation Error: Side must be one of ['BUY', 'SELL']. Got: 'HOLD'.
# Invalid order type
python cli.py place-order --symbol BTCUSDT --side BUY --type FOK --quantity 0.001
# ❌ Validation Error: Order type must be one of ['LIMIT', 'MARKET', 'STOP_LIMIT']. Got: 'FOK'.
# Negative quantity
python cli.py place-order --symbol BTCUSDT --side BUY --type MARKET --quantity -5
# ❌ Validation Error: Quantity must be a positive number greater than zero. Got: -5.0.
# LIMIT order missing --price
python cli.py place-order --symbol BTCUSDT --side BUY --type LIMIT --quantity 0.001
# ❌ Validation Error: --price is required for LIMIT orders.
# STOP_LIMIT missing --stop-price
python cli.py place-order --symbol BTCUSDT --side BUY --type STOP_LIMIT --quantity 0.001 --price 45000
# ❌ Validation Error: --stop-price is required for STOP_LIMIT orders.Note: Symbol and order type are normalised to uppercase automatically, so
btcusdt,buy, andmarketare all accepted.
Log file: logs/trading_bot.log (max 5 MB, 3 rotated backups)
2026-07-01 11:15:35 | INFO | bot.client | Binance Futures Testnet client initialized successfully
2026-07-01 11:15:35 | INFO | bot.orders | Placing MARKET BUY order | symbol=BTCUSDT qty=0.001
2026-07-01 11:15:35 | INFO | bot.orders | MARKET order accepted by exchange | orderId=18164753457 status=NEW
2026-07-01 11:15:36 | INFO | bot.orders | Fill confirmed after 1 poll(s) | orderId=18164753457 status=FILLED avgPrice=58423.60 executedQty=0.001
2026-07-01 11:15:36 | INFO | bot.orders | MARKET order result | orderId=18164753457 status=FILLED avgPrice=58423.60 executedQty=0.001
2026-07-01 11:15:58 | INFO | bot.orders | Placing LIMIT BUY order | symbol=BTCUSDT qty=0.001 price=50000.0
2026-07-01 11:15:58 | INFO | bot.orders | LIMIT order placed | orderId=18164806068 status=NEW price=50000.00000000
2026-07-01 11:16:45 | INFO | bot.orders | Placing STOP_LIMIT BUY order | symbol=BTCUSDT qty=0.002 price=75000.0 stopPrice=74000.0
2026-07-01 11:16:46 | INFO | bot.orders | STOP_LIMIT order placed | orderId=18165012340 status=NEW stopPrice=74000.00000000
2026-07-01 11:22:05 | ERROR | bot.orders | API error (MARKET order): APIError(code=-4164): Order's notional must be no smaller than 20
cli.py
│ Parses CLI args → normalises to uppercase → validates
▼
bot/validators.py
│ Raises ValueError with clear message on bad input
▼
bot/orders.py
│ Calls Binance API, polls fill status, normalises response
▼
bot/client.py
│ Wraps python-binance Client (testnet=True)
│ Provides create_order_direct() to bypass library routing quirks
▼
Binance Futures Testnet (https://testnet.binancefuture.com)
| Module | Responsibility |
|---|---|
bot/client.py |
Authentication, connection, direct order routing |
bot/orders.py |
Order placement, fill polling, normalised responses |
bot/validators.py |
Pure input validation — no side effects |
bot/logging_config.py |
Log format, rotation, handler attachment |
cli.py |
Argument parsing, formatted output, exit codes |
- Testnet only — all orders use
testnet=True; no real funds are at risk. GTC(Good Till Cancelled) time-in-force is applied to all non-market orders.- Stop-Limit orders map to Binance Futures
STOPtype, which triggers onstopPriceand fills atprice. Price direction rules:- BUY STOP:
stopPricemust be above the current market price. - SELL STOP:
stopPricemust be below the current market price.
- BUY STOP:
- Minimum notional of
quantity × price ≥ $50applies to stop-limit orders on BTCUSDT Testnet. Usequantity ≥ 0.002near $50k BTC to be safe. - Quantities are passed as supplied — the caller is responsible for respecting exchange lot-size and minimum-notional rules for each symbol.
- Market order status on Testnet: The Binance Futures Testnet matching engine
sometimes returns
status=NEWin the create-order response before confirming the fill. The bot polls order status once after placement to surface the actualFILLEDstate andavgPrice. If the fill is not confirmed within ~1.6 seconds, the initial response is returned — the order is still accepted and will fill. - Some versions of
python-binancerouteSTOPorder types to the algo-order endpoint instead of/fapi/v1/order. The bot usescreate_order_direct()to bypass this and always target the correct endpoint. - API keys are loaded exclusively from
.envviapython-dotenv. The.envfile is gitignored and must never be committed.
| Scenario | Behaviour |
|---|---|
| Missing / wrong API keys | ValueError with setup instructions |
| Invalid symbol / side / type | ValueError before any network call |
| Non-positive qty or price | ValueError before any network call |
Missing --price for LIMIT |
ValueError at CLI layer |
Missing --stop-price |
ValueError at CLI layer |
| Notional below exchange minimum | BinanceAPIException -4164; error printed |
| Stop price on wrong side of market | BinanceAPIException -2021; error printed |
| Network / connectivity failure | BinanceRequestException; error printed |
| Any unhandled exception | Full traceback written to log file |
python-binance>=1.0.19
python-dotenv>=1.0.0
requests>=2.31.0
Install with:
pip install -r requirements.txtBuilt for Binance Futures Testnet (USDT-M). Do not use with real API keys.