bybit-trade
Authenticated bracket-order execution for Bybit v5 linear perps. Calls
risk-guard check as a subprocess before every order and aborts on any
non-zero exit. Testnet by default — requires BOTH --live AND BYBIT_ENV=live
to route to production.
When to use
Only when the user has:
- Planned size via
scalp-plan - Confirmed a
risk-guardsession exists - Explicitly asked to place / execute / open the trade
Always echo the plan and confirm with the user before invoking.
Required env vars
BYBIT_API_KEYBYBIT_API_SECRETBYBIT_ENV=liveis REQUIRED in addition to--livefor production
Keys are never accepted on the command line. If keys are missing the script exits with a clear error.
How to run
# Dry-run (signs the request but never POSTs)
python bybit-trade/trade.py place \
--symbol SOLUSDT --side buy --qty 11.2 \
--sl 145.97 --tp 151.16 --risk-usd 25 --dry-run
# Testnet (default; BYBIT_ENV=live NOT set)
BYBIT_API_KEY=... BYBIT_API_SECRET=... \
python bybit-trade/trade.py place \
--symbol SOLUSDT --side buy --qty 11.2 \
--sl 145.97 --tp 151.16 --risk-usd 25
# Live — both flags required
BYBIT_ENV=live BYBIT_API_KEY=... BYBIT_API_SECRET=... \
python bybit-trade/trade.py place --live \
--symbol SOLUSDT --side buy --qty 11.2 \
--sl 145.97 --tp 151.16 --risk-usd 25
# Close (reduce-only market)
python bybit-trade/trade.py close --symbol SOLUSDT
# Inspect positions
python bybit-trade/trade.py positions [--symbol SOLUSDT]
Order structure
Every place call sends a Bybit v5 native bracket:
category=linear,orderType=Market,timeInForce=IOCstopLoss=<sl>,takeProfit=<tp>, both withtriggerBy=LastPriceorderLinkId = "clive-{symbol}-{unix_ms}"for idempotency
Qty rounded to lotSizeFilter.qtyStep, SL/TP rounded to priceFilter.tickSize
(fetched from /v5/market/instruments-info). Raw floats are never sent.
Guardrails (all hard-coded, no flags to disable)
- Testnet unless
--liveANDBYBIT_ENV=live. If--liveis set butBYBIT_ENVisn'tlive, exit 2. risk-guard check --risk-usd Nmust exit 0. Its stderr is surfaced and the order is aborted on any non-zero exit.- Refuses to open a second position if one already exists for the symbol.
- Qty below exchange minimum → exit with Bybit's message.
- Bybit errors are surfaced verbatim. No fallbacks, no retries.
Exit codes
- 0 on success
- 2 on env/config veto (wrong env, missing keys, --live without BYBIT_ENV=live)
- 2 on risk-guard veto
- 1 on Bybit API error or invariant violation
Dry-run
--dry-run runs every step up through signing and prints the exact request
it would have sent. Safe without testnet keys (uses placeholders if missing).