Initial import: grid-bot — grid trading bot for BTC-USDT on Cifra Markets
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
# LIVE TRADING CHECKLIST — grid-bot BTC-USDT.IMEX
|
||||
|
||||
**Дата создания:** 2026-06-26 23:30 GMT+7
|
||||
**Last update:** 2026-06-26 23:41 GMT+7 — ответы @KAndrew на open questions
|
||||
**Бот:** grid-bot v0.13.x (PID 1552921, mode=demo, peak=$375.68)
|
||||
**Цель:** выход на реальную торговлю через Cifra Markets (BY) / Tradernet
|
||||
**Целевой размер позиции (от @KAndrew):** $135
|
||||
|
||||
> ⚠️ **Текущий статус: НЕ ГОТОВ.** Ниже — что должно быть сделано перед переключением `LIVE_TRADING_DRY_RUN=false`.
|
||||
|
||||
---
|
||||
|
||||
## 🚦 Блокеры (без них live = деньги на ветер)
|
||||
|
||||
### 1. Подтвердить fees Cifra Markets ✅ ЗАКРЫТ (27.06 00:03)
|
||||
- [x] Зайти в ЛК **cifra.by** → раздел «Тарифы» — @KAndrew подтвердил
|
||||
- [x] Тариф: **«Консультационный»** (ДЛЯ СТАРТА). Возможно есть другие tiers по объёму — уточнить при выходе на стабильный оборот
|
||||
- [x] Записать **точные %** для BTC-USDT: **0.5% per side** (round-trip = **1.0%**)
|
||||
- [x] Обновить `.env`: `FEE_RATE_PERCENT=0.5`, `FEE_SAFETY_MULTIPLIER=1.5` (было 0.2 / 1.25)
|
||||
- [ ] **Открытый вопрос**: «Списывается только в рублях» — реальный fee может быть выше из-за скрытого RUB/USD спреда (~0.1–0.2%)
|
||||
- [ ] При следующем рестарте бота подхватится автоматически
|
||||
|
||||
**Расчёт margin (fee=0.5% per side):**
|
||||
- Round-trip fee: **1.00%**
|
||||
- Step 0.5% − fee 1.00% = **−0.50%** — УБЫТОК ❌
|
||||
- Validator `fee × safety=1.5`: 1.00% × 1.5 = **1.50%** → step должен быть ≥ 1.5%
|
||||
- TP 2% − fees 1.00% = **1.00% net profit** на полный цикл ✅
|
||||
- **Step обязательно поднимать** до 1.5–2.0%
|
||||
|
||||
### 2. Накопить demo-метрики
|
||||
- [ ] Минимум **30 закрытых сделок** (сейчас 13) — не дни, а TP-fill-ы
|
||||
- [ ] Минимум **14 дней** непрерывной работы в demo без критических багов
|
||||
- [ ] **Win-rate > 50%** (TP-fill / total fills)
|
||||
- [ ] **Avg PnL per trade > 0** после учёта fees
|
||||
- [ ] **Max DD < 8%** за весь период (у нас сейчас −4.86% от peak)
|
||||
|
||||
### 3. Настроить kill switch для live
|
||||
- [ ] `LIVE_KILL_CLOSE_POSITION=true` (сейчас `false` — это риск)
|
||||
- [ ] `LIVE_KILL_DD_PCT=5.0` (сейчас не задан → fallback на 10%)
|
||||
- [ ] Проверить TG-polling работает: `/api/kill-switch/status` → `tg_poll_sec: 30`
|
||||
- [ ] Протестировать `/api/kill-switch/test` с reason=`live_test` (на demo!)
|
||||
|
||||
### 4. Code review (см. секцию ниже)
|
||||
- [ ] Пройтись по всем fix-точкам из MEMORY.md (`*100`-баги, anchor-формулы, percent-конверсии)
|
||||
- [ ] Сверить все места с `take_profit_percent` (был баг ×4 → anchor $260K)
|
||||
- [ ] Проверить формулы asymmetric split (3:2 / 2:3)
|
||||
|
||||
### 5. Live API smoke test (см. секцию ниже)
|
||||
- [ ] Тестовый BUY на минимальный lot с ручным отменом через ЛК
|
||||
- [ ] Тестовый SELL (TP-fill) на минимальный lot
|
||||
- [ ] Проверить, что `urllib`-запросы реально доходят до Tradernet, нет 403/timeout
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Pre-live .env настройки (что поменять)
|
||||
|
||||
```bash
|
||||
# === ОБЯЗАТЕЛЬНО изменить перед live ===
|
||||
|
||||
# 1. Trading mode
|
||||
DEMO_MODE=false # было: true
|
||||
LIVE_TRADING_DRY_RUN=false # было: true — это переключатель на реальные ордера
|
||||
|
||||
# 2. Real Tradernet API credentials (НЕ дефолтные)
|
||||
TRADERNET_PUBLIC_KEY=<real_key> # отозвать старые demo-ключи
|
||||
TRADERNET_PRIVATE_KEY=<real_key>
|
||||
TRADERNET_LOGIN=<real_login>
|
||||
TRADERNET_PASSWORD=<real_pass>
|
||||
|
||||
# 3. Kill switch — ОБЯЗАТЕЛЬНО
|
||||
LIVE_KILL_CLOSE_POSITION=true # было: false
|
||||
LIVE_KILL_DD_PCT=5.0 # 5% (было: не задано → 10%)
|
||||
KILL_DD_PCT=10.0 # для demo остаётся 10%
|
||||
|
||||
# 4. Fee rate (после подтверждения в ЛК Cifra)
|
||||
FEE_RATE_PERCENT=0.2 # ОБНОВИТЬ после проверки точных %
|
||||
FEE_SAFETY_MULTIPLIER=1.5 # было: 1.25 — увеличить запас
|
||||
|
||||
# 5. Strategy — для live понизить агрессивность
|
||||
STRATEGY_LOCK_PCT=1.5 # было: 2.0 — раньше блокировать
|
||||
STRATEGY_LOCK_COOLDOWN_SEC=1800 # было: 900 — реже переключаться
|
||||
|
||||
# 6. Inactivity rebuild — для live ВЫКЛЮЧИТЬ
|
||||
INACTIVITY_RESTART_HOURS=999 # было: 6 — на live пусть работает как есть
|
||||
INACTIVITY_PRICE_DRIFT_PCT=99.0 # было: 0.25 — фактически отключить
|
||||
|
||||
# 7. Kronos — пока НЕ включать на live
|
||||
KRONOS_LIVE_ENABLED=false # оставить false, пока не подтверждена статистика
|
||||
|
||||
# === Что НЕ менять ===
|
||||
GRID_STEP_PERCENT=0.005 # 0.5% — нормально для fee 0.2%
|
||||
GRID_TAKE_PROFIT_PERCENT=2.0 # 2% TP — нормально
|
||||
GRID_LEVELS=10 # дефолт (но у нас сейчас 3 в state.json)
|
||||
STRATEGY_CENTER_MODE=sma # OK
|
||||
```
|
||||
|
||||
> После правок — **обязательно** перезапустить бота с `kill -9 PID` + новый запуск через `nohup ./venv/bin/python main.py >> bot.log 2>&1 < /dev/null & disown`
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Code review checklist (что перепроверить в коде)
|
||||
|
||||
### Pattern 1: Percent vs ratio confusion (исторически баг ×4)
|
||||
```bash
|
||||
# Найти все места, где take_profit_percent или step_percent умножаются:
|
||||
grep -n "take_profit_percent\|step_percent" /root/grid-bot/main.py /root/grid-bot/grid.py
|
||||
```
|
||||
**Проверить каждое вхождение:**
|
||||
- Если переменная хранится в **процентах** (2.0 = 2%), формула должна быть `value / 100.0`
|
||||
- Если в **долях** (0.02 = 2%), формула должна быть `value` напрямую
|
||||
- В `grid.py:pnl_percent()` — уже `*100`, значит внутри ratio
|
||||
|
||||
### Pattern 2: Anchor calculation
|
||||
```bash
|
||||
grep -n "sell_anchor\|entry_price.*1\.\|anchor_for_filled" /root/grid-bot/main.py
|
||||
```
|
||||
- Убедиться что **anchor = entry_price × (1 + take_profit_percent / 100)**
|
||||
- НЕ `entry_price * (1.0 + take_profit_percent)` (это и был баг 17.06, anchor × 4)
|
||||
|
||||
### Pattern 3: Live order placement
|
||||
```bash
|
||||
grep -n "_place_live_buy\|_place_live_sell\|_live_cancel" /root/grid-bot/main.py /root/grid-bot/grid.py
|
||||
```
|
||||
- Проверить, что `LIVE_TRADING_DRY_RUN=false` реально идёт в код, не в логику демо
|
||||
- Проверить обработку ошибок `403 / 429 / timeout` — бот должен ретраить ИЛИ тихо отменять (не падать)
|
||||
- Проверить, что при ошибке API бот НЕ дублирует ордер
|
||||
|
||||
### Pattern 4: Asymmetric grid split
|
||||
```bash
|
||||
grep -n "STRATEGY_ASYMMETRY\|buy.*sell\|split" /root/grid-bot/main.py /root/grid-bot/grid.py
|
||||
```
|
||||
- bias=up → 3 BUY / 2 SELL (anchor выше)
|
||||
- bias=down → 2 BUY / 3 SELL (anchor ниже)
|
||||
- bias=range → 3 BUY / 2 SELL (default)
|
||||
|
||||
### Pattern 5: Peak equity reset
|
||||
```bash
|
||||
grep -n "peak_equity\|_peak_lock" /root/grid-bot/main.py
|
||||
```
|
||||
- При live-старте вызвать `kill_switch.reset()` — peak начнёт отсчитываться от live-баланса
|
||||
- Без reset — KS может триггернуться сразу (peak=$375.68 demo, на live у нас меньше)
|
||||
|
||||
### Pattern 6: 403 авто-pause (требует НОВОГО кода) ⭐
|
||||
**Требование @KAndrew:** при HTTP 403 от Tradernet API → авто-pause бота, НЕ kill.
|
||||
|
||||
**Сейчас:** KS считает все API errors одинаково (`api_errors_threshold=5` за 600 сек → kill).
|
||||
|
||||
**Что нужно сделать:**
|
||||
- [ ] Разделить счётчики ошибок: `api_errors_403` (auth/perm) vs `api_errors_5xx` (infra)
|
||||
- [ ] При `api_errors_403 >= 1` → bot_running=false (pause), KS НЕ triggered, reason=`auth_403`
|
||||
- [ ] При `api_errors_5xx >= 5` за 600 сек → KS trigger (как сейчас)
|
||||
- [ ] При resume (после ручного `/api/bot/start`) — счётчики сбрасываются
|
||||
- [ ] TG-алерт при любой 403: «⚠️ 403 от Tradernet — бот поставлен на паузу»
|
||||
|
||||
**Файл для правки:** `/root/grid-bot/main.py` — секция API error tracking (см. grep `_api_errors`)
|
||||
|
||||
**Smoke test после фикса:**
|
||||
```bash
|
||||
# На demo: подменить API ключ на невалидный, дождаться 403 → бот должен встать на паузу
|
||||
sed -i 's/TRADERNET_PUBLIC_KEY=.*/TRADERNET_PUBLIC_KEY=INVALID_KEY/' /root/grid-bot/.env
|
||||
kill -9 $(pgrep -f 'python.*main.py'); cd /root/grid-bot && nohup ./venv/bin/python main.py >> bot.log 2>&1 < /dev/null & disown
|
||||
sleep 60
|
||||
curl -s -u kolpakov:GrinderBot1090 https://gridbot.kolp.pro/api/status | grep bot_running
|
||||
# → должно быть bot_running: false, reason: auth_403
|
||||
# Восстановить ключ!
|
||||
```
|
||||
|
||||
### Pattern 7: TG-уведомления на сделку (требует НОВОГО кода) ⭐
|
||||
**Требование @KAndrew:** каждая сделка (BUY fill / SELL fill / TP-fill) → TG-сообщение с деталями.
|
||||
|
||||
**Сейчас:** TG вызывается только при `tg_notify()` в `main.py:384` (KS-alerts, важные изменения). Сами сделки НЕ спамят.
|
||||
|
||||
**Что нужно сделать:**
|
||||
- [ ] Хук в `check_fill_buy` / `check_fill_sell` / `check_take_profit` после успешного fill → `tg_notify(...)` с шаблоном:
|
||||
- BUY: `🟢 BUY fill @ $XXX (qty Y, balance $Z)`
|
||||
- SELL: `🔴 SELL fill @ $XXX (pnl +$W)`
|
||||
- TP-fill: `🎯 TP @ $XXX (pnl +$W, total trades: N)`
|
||||
- [ ] Anti-spam: не слать TG если fill дубликат (idempotency по order_id)
|
||||
- [ ] Quiet hours НЕ применяются (24/7 по решению @KAndrew)
|
||||
- [ ] Тест: дождаться следующего BUY fill на demo → проверить TG
|
||||
|
||||
**Файлы для правки:** `/root/grid-bot/main.py` (buy/sell fill handlers) + `/root/grid-bot/grid.py` (TP logic)
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Smoke test (перед переключением на live)
|
||||
|
||||
### Pre-flight (на demo)
|
||||
```bash
|
||||
# 1. Kill switch готов?
|
||||
curl -u kolpakov:GrinderBot1090 https://gridbot.kolp.pro/api/kill-switch/status
|
||||
# → enabled=true, triggered=false, reason=none, peak=$375.68
|
||||
|
||||
# 2. Тест KS в demo (НЕ в live!)
|
||||
curl -u kolpakov:GrinderBot1090 -X POST https://gridbot.kolp.pro/api/kill-switch/test
|
||||
# → reason="test:..." triggered=true
|
||||
curl -u kolpakov:GrinderBot1090 -X POST https://gridbot.kolp.pro/api/kill-switch/reset
|
||||
# → reason="none"
|
||||
|
||||
# 3. API ключи валидны?
|
||||
curl -u kolpakov:GrinderBot1090 https://gridbot.kolp.pro/api/account
|
||||
# → account_id, balance > 0, currency=USDT
|
||||
```
|
||||
|
||||
### Live dry-run (минимальная позиция)
|
||||
```bash
|
||||
# 1. Переключить на live dry-run
|
||||
sed -i 's/LIVE_TRADING_DRY_RUN=true/LIVE_TRADING_DRY_RUN=false/' /root/grid-bot/.env
|
||||
# (НЕ ТРОГАТЬ DEMO_MODE — оставить true чтобы не запускать боевую логику)
|
||||
|
||||
# 2. Запустить, наблюдать 1 час
|
||||
kill -9 $(pgrep -f 'python.*main.py')
|
||||
cd /root/grid-bot && nohup ./venv/bin/python main.py >> bot.log 2>&1 < /dev/null & disown
|
||||
sleep 3600
|
||||
|
||||
# 3. Проверить логи
|
||||
grep -E 'LIVE_|PLACE|ERROR' /root/grid-bot/bot.log | tail -30
|
||||
|
||||
# 4. Откатить если что-то не так
|
||||
sed -i 's/LIVE_TRADING_DRY_RUN=false/LIVE_TRADING_DRY_RUN=true/' /root/grid-bot/.env
|
||||
kill -9 $(pgrep -f 'python.*main.py')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Phased rollout plan (целевой размер $135)
|
||||
|
||||
### Phase 0 — Smoke (1 день)
|
||||
- `DEMO_MODE=true`, `LIVE_TRADING_DRY_RUN=false` (только меняем флаг, не логику)
|
||||
- Наблюдаем 1 день — бот реально стучится в Tradernet API, ордера не размещает
|
||||
- Проверяем логи на 403/timeout/retry
|
||||
|
||||
### Phase 1 — Micro-live Week 1 (5–7 дней)
|
||||
- **$40** (≈30% от $135)
|
||||
- `GRID_LEVELS=3`, `GRID_STEP_PERCENT=0.005`, `GRID_TAKE_PROFIT_PERCENT=2.0`
|
||||
- `LIVE_KILL_DD_PCT=5.0`, `LIVE_KILL_CLOSE_POSITION=true`
|
||||
- `KRONOS_LIVE_ENABLED=false` (default, осторожно)
|
||||
- 24/7 (по решению @KAndrew)
|
||||
- Авто-pause при 403 (после код-фикса)
|
||||
- Ежедневный отчёт в TG (PnL, win-rate, max DD, #trades) — `@Kolp` генерит сам
|
||||
|
||||
### Phase 2 — Half Week 2 (5–7 дней)
|
||||
- **$90** (≈67% от $135)
|
||||
- Если Phase 1: PnL > 0 И DD < 3% И win-rate > 50%
|
||||
- Иначе: остаёмся на $40 ещё на неделю
|
||||
|
||||
### Phase 3 — Full Week 3-4
|
||||
- **$135** (100%)
|
||||
- Если Phase 2 стабильно PnL > 0 И DD < 3%
|
||||
- Включить `KRONOS_LIVE_ENABLED=true` (опционально, после подтверждения Kronos-метрик в demo)
|
||||
|
||||
### Steady state
|
||||
- 100% ($135), 24/7, full automation
|
||||
- Weekly отчёт в TG (можно выключить если утомит)
|
||||
|
||||
> ❌ **Откатить на Phase N-1 (или в demo) если:** DD > 5%, > 3 API errors подряд, любой phantom-order баг, > 5 trades подряд в убыток, TG spam от kill-switch.
|
||||
|
||||
---
|
||||
|
||||
## ↩️ Rollback plan (если что-то пошло не так)
|
||||
|
||||
```bash
|
||||
# 1. Остановить бота
|
||||
kill -9 $(pgrep -f 'python.*main.py')
|
||||
|
||||
# 2. Откатить .env на demo
|
||||
sed -i 's/DEMO_MODE=false/DEMO_MODE=true/' /root/grid-bot/.env
|
||||
sed -i 's/LIVE_TRADING_DRY_RUN=false/LIVE_TRADING_DRY_RUN=true/' /root/grid-bot/.env
|
||||
|
||||
# 3. Вручную закрыть все висящие ордера через ЛК cifra.by → «Активные заявки»
|
||||
|
||||
# 4. Запустить demo снова
|
||||
cd /root/grid-bot && nohup ./venv/bin/python main.py >> bot.log 2>&1 < /dev/null & disown
|
||||
|
||||
# 5. Сделать snapshot кода
|
||||
cp -r /root/grid-bot /root/grid-bot.live-fail-$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# 6. Проверить убытки в ЛК cifra.by → История сделок
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Решения (ответы @KAndrew, 26.06 23:41 GMT+7)
|
||||
|
||||
| # | Вопрос | Решение |
|
||||
|---|---|---|
|
||||
| 1 | Размер позиции на live | **$135** (целевой финальный размер) |
|
||||
| 2 | Одновременно ордеров | **3** (как сейчас в state.json) |
|
||||
| 3 | Kronos live | **Вариант А — выключить навсегда** (подтверждено @KAndrew). Код оставить как legacy, `STRATEGY_BIAS_SOURCE=trend` |
|
||||
| 4 | Ночной режим | **24/7** (без QUIET_HOURS) |
|
||||
| 5 | Если API 403 | **авто-pause** (НЕ kill) — требует код-фикса, см. Code review §6 |
|
||||
| 6 | TG-отчёты | **(a) каждое сообщение на сделку** (подтверждено @KAndrew) — BUY/SELL/TP-fill → отдельный TG. Требует код-фикса, см. Code review §7 |
|
||||
|
||||
> Все defaults можно переопределить — скажи явно.
|
||||
|
||||
---
|
||||
|
||||
## 📊 Текущие метрики (для сравнения с live)
|
||||
|
||||
| Метрика | Demo сейчас | Live минимум |
|
||||
|---|---|---|
|
||||
| Total trades | 13 | 30+ (закрытых) |
|
||||
| Total PnL | $3.06 | > $0 за неделю |
|
||||
| Peak equity | $375.68 | — |
|
||||
| Max DD | −4.86% | < 5% |
|
||||
| Win-rate | 1/1 = 100% (n=1) | > 50% (n≥20) |
|
||||
| Avg TP-fill time | ~2ч | — |
|
||||
| Avg step fill | ~30 мин | — |
|
||||
| Days running | ~14 | 14+ |
|
||||
| Uptime | ~95% (были рестарты) | > 98% |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Связанные файлы
|
||||
|
||||
- `/root/grid-bot/.env` — основные настройки
|
||||
- `/root/grid-bot/config.py` — defaults (все через `os.getenv`)
|
||||
- `/root/grid-bot/main.py` — trading loop + KS + state.json
|
||||
- `/root/grid-bot/grid.py` — grid logic, TP, fills
|
||||
- `/root/grid-bot/api.py` — Tradernet REST client
|
||||
- `~/.openclaw/workspace/MEMORY.md` — патчи, баги, решения
|
||||
- `~/.openclaw/workspace/memory/2026-06-*.md` — daily notes
|
||||
|
||||
---
|
||||
|
||||
**Автор:** Kolp (OpenClaw + M3)
|
||||
**Версия:** 1.1 (обновлено 2026-06-26 23:41 GMT+7)
|
||||
**История:**
|
||||
- v1.0 (23:30) — первая версия, open questions
|
||||
- v1.1 (23:41) — ответы @KAndrew: $135, 3 ордера, 24/7, 403→pause
|
||||
- v1.2 (23:42) — TG-отчёты на сделку (Pattern 7)
|
||||
- v1.3 (23:45) — Kronos = Вариант А (выключить)
|
||||
- v1.4 (23:48) — все 6 open questions закрыты
|
||||
- v1.5 (23:54) — fees=0.15% (первая оценка @KAndrew)
|
||||
- v1.6 (27.06 00:03) — fees=**0.5% per side** (тариф «Консультационный», round-trip=1.0%). Требует пересмотра step
|
||||
|
||||
**Следующий шаг:** @KAndrew выбирает step (1.5% / 2.0%) — пока grid-стратегия убыточна на live
|
||||
Reference in New Issue
Block a user