# Bybit Trade

> 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.

- Skill: `daviddme/bybit-trade` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add daviddme/bybit-trade`
- Raw SKILL.md: https://api.skillmd.com/api/skills/daviddme/bybit-trade/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: daviddme (https://skillmd.com/u/daviddme)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/daviddme/bybit-trade

---


# 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:
1. Planned size via `scalp-plan`
2. Confirmed a `risk-guard` session exists
3. 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)
1. Testnet unless `--live` AND `BYBIT_ENV=live`. If `--live` is set but
   `BYBIT_ENV` isn't `live`, exit 2.
2. `risk-guard check --risk-usd N` must exit 0. Its stderr is surfaced and the
   order is aborted on any non-zero exit.
3. Refuses to open a second position if one already exists for the symbol.
4. Qty below exchange minimum → exit with Bybit's message.
5. 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).

