| name | bybit-trade |
| description | Place a market entry with a native bracket stop-loss and take-profit on Bybit v5. Testnet by default. Use ONLY when the user explicitly asks to place/execute/open a trade and has already planned size with scalp-plan and confirmed risk with risk-guard. Dangerous — authenticated, touches real money on --live. Always confirm with the user before invoking. |
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-guard session 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_KEY
BYBIT_API_SECRET
BYBIT_ENV=live is REQUIRED in addition to --live for 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=IOC
stopLoss=<sl>, takeProfit=<tp>, both with triggerBy=LastPrice
orderLinkId = "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
--live AND BYBIT_ENV=live. If --live is set but
BYBIT_ENV isn't live, exit 2.
risk-guard check --risk-usd N must 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).