Archived
ЧТО: code/ (стенд и методы), results/ (сводки), charts/ (3 графика), reports/ (издержки, плацебо, по годам), docs/REJECTED.md. ПОЧЕМУ: цель — найти кандидатов на 5м или доказать с цифрами их отсутствие. КАК ПРОВЕРЕНО: движок сверен с прод-движком TON-бота 1:1; плацебо и рандом-контроль в отчёте; бутстрап по дням.
148 lines
14 KiB
Markdown
148 lines
14 KiB
Markdown
# ПЛАН: поиск прибыльных стратегий на 5-минутных свечах (Bybit USDT-перпы)
|
||
|
||
Рабочая папка: `/opt/data/work/screener5m/` · Репо: `anatoly/crypto-screener-5m` (Gitea)
|
||
Гейты (пишет оркестратор, исполнителю править нельзя):
|
||
`/opt/data/scripts/screener5m_gate_f1.sh`, `..._f2.sh`, `..._f3.sh`
|
||
|
||
## 0. Разведка, сделанная ДО постановки цели (факты, не догадки)
|
||
|
||
Проверено 28.09.2026 на живом Bybit REST с этой машины (прокси не нужен):
|
||
|
||
| Что проверено | Результат |
|
||
|---|---|
|
||
| `GET /v5/market/time` | 200, сервер отвечает |
|
||
| 5м свечи, последние 1000 баров | 1000 баров, 25.09.2026 09:05 → 28.09.2026 20:20 (≈3,5 суток) |
|
||
| **5м история глубоко назад при `start`/`end`** | BTCUSDT: бары есть с 2020-04-01, 2021-01-01, 2022-01-01 — **история доступна пагинацией назад** |
|
||
| пагинация | внутри диапазона отдаётся ПОСЛЕДНИЕ `limit` баров → идти назад `end = oldest − 1`, 1000 баров/запрос |
|
||
| скорость одиночных запросов | 40 запросов за 14,9 с = **2,7 запроса/с** (запас есть; при 4–6 потоках ≈10/с) |
|
||
| линейных USDT-перпов | 784; топ-50 = 90% оборота, топ-100 = 95%, топ-150 = 97% |
|
||
| `/v5/market/funding/history` | `retCode 0`, работает (прежние отказы были транзиентным лимитом) |
|
||
| место на диске | 29 ГБ свободно |
|
||
|
||
**Поправка к прежней заметке** («Bybit отдаёт 5м ≈3,5 дня — только накопление»): это верно только
|
||
для запроса БЕЗ `start`. С явным `start`/`end` 5м история отдаётся вглубь (проверено на 2020–2022).
|
||
Значит 5м-исследование можно строить на годах истории, а не на накоплении кроном.
|
||
|
||
### Планка издержек, замеренная на живых данных (20 пар, 30 дней)
|
||
|
||
| Показатель | Значение |
|
||
|---|---|
|
||
| Средний модуль 5м-доходности (20 пар) | **22,8 б.п.** (BTC 6,2 · ETH 7,9 · SOL 13,4 · QNT 75,8 · ENA 37,0) |
|
||
| Средний модуль 1ч-доходности | 78,0 б.п. |
|
||
| Комиссия тейкера на круг | 0,11% (0,055% × 2 ноги) |
|
||
|
||
Порог безубыточной точности `p* = (Стоп + Издержки) / (Цель + Стоп)`:
|
||
|
||
| Цель / стоп | тейкер 0,11% | мейкер 0,04% |
|
||
|---|---|---|
|
||
| 0,1% / 0,1% | 105% (мёртвая зона) | 70% |
|
||
| 0,2% / 0,2% | 77,5% | 60% |
|
||
| 0,3% / 0,2% | 62,0% | 48% |
|
||
| 0,5% / 0,3% | 51,2% | 42,5% |
|
||
| 1,0% / 0,5% | 40,7% | 36% |
|
||
|
||
Вывод для планирования: «скальпинг на один 5м-бар» (цель = типичное движение 5м ≈ 0,2% у BTC)
|
||
требует точности 77% — это заведомо проигрыш. Осмысленные конструкции: цель в 3–10 раз больше
|
||
комиссии (то есть сигнал на 5м, удержание от десятков минут), либо мейкер-исполнение, либо
|
||
кросс-секционные корзины (доход не с одной пары, а с разницы между парами).
|
||
|
||
## 1. Данные (этап Э1)
|
||
|
||
- Источник: `https://api.bybit.com/v5/market/kline`, `category=linear`, `interval=5`, пагинация назад
|
||
(`end = oldest_ts − 1`), 1000 баров/запрос, `retCode 10016` — пропускать пару, не падать.
|
||
- Вселенная: USDT-перпы, статус Trading, оборот 24ч ≥ $5M, история 5м ≥ 90 дней, исключить
|
||
токенизированные TradFi-инструменты (XAU/CL/SOXL и подобные) — они другой природы; ожидается ≈100–130 пар.
|
||
- Период: максимум доступного, минимум 18 месяцев там, где история есть (цель — с 2024-10-01).
|
||
- Формат: `data/5m/<SYMBOL>_5m.csv`, **без шапки**, 6 полей: `ts_ms,open,high,low,close,volume`,
|
||
время по возрастанию. Плюс `data/manifest_5m.json` = `{"pairs": {SYMBOL: {symbol,bars,first_ts,last_ts}}}`.
|
||
- Объём: 100 пар × 288 баров × 540 дней ≈ **15,5 млн баров** ≈ 11 000 запросов ≈ 400 МБ на диске.
|
||
Запускать в background с notify; после выгрузки — докачка только того, что короче ожидаемого.
|
||
- Валидатор → `reports/validate_5m.json`: `{"dup": 0, "pairs": {SYMBOL: {"bars": N, "coverage": 0.99}}}`,
|
||
где `coverage` = фактические бары / календарные 5м-слоты между first_ts и last_ts.
|
||
- Грабли: pandas 3 (`np.nan_to_num` на `.values` read-only → копировать), имена переменных в циклах
|
||
(`d` однажды перетёрла словарь сигналов), длинные выгрузки — только background+notify.
|
||
|
||
## 2. Стенд и его сверка (этап Э2)
|
||
|
||
- Движок: итерация по ВСЕМ барам (не по списку сигналов), одна позиция на пару, вход по `close` бара
|
||
сигнала, выход по правилу (SL проверяется первым), комиссия от цены входа, проскальзывание,
|
||
funding при удержании через 00/08/16 UTC.
|
||
- **Сверка обязательна**: тот же движок прогнать на 30м барах (ресемпл из 5м) теми же правилами,
|
||
что прод-движок TON-бота (`run_mr_backtest`), ≥4 пары, расхождение PF ≤ 5 % →
|
||
`reports/stand_reconcile.json` = `{"pairs": {SYMBOL: {prod_n, stand_n, prod_pf, stand_pf}}}`.
|
||
Урок прошлого кейса: расхождение ищут в МАШИНЕ СОСТОЯНИЙ, а не в правилах входа.
|
||
|
||
## 3. Планка издержек (этап Э3)
|
||
|
||
`reports/costs.json`: `mean_abs_r5m_bp`, `mean_abs_r1h_bp`, `fees_pct_per_leg {taker:0.055, maker:0.02}`,
|
||
`p_star` — ≥5 сценариев «цель/стоп → требуемая точность»; плюс человекочитаемый `reports/COSTS.md`
|
||
(что дорого, что дешёво, при каких целях 5м вообще имеет смысл). Числа считать скриптом, не в голове.
|
||
|
||
## 4. Банк методов на 5м (этап Э4 — минимум 12, правила фиксируются ДО прогона)
|
||
|
||
| № | Метод | Идея |
|
||
|---|---|---|
|
||
| 1 | XS-реверсал 5м/15м/1ч | покупать худшие за окно, продавать лучшие (доллари-нейтрально) |
|
||
| 2 | XS-моментум 5м | продолжение короткого импульса между парами |
|
||
| 3 | Lead-lag BTC → альты | импульс BTC за k баров → позиция в альте на m баров |
|
||
| 4 | VWAP-возврат + фильтр EMA200 | откат к VWAP внутри тренда |
|
||
| 5 | OU-возврат к EMA(20) | вход по |z|>2, выход по z→0 |
|
||
| 6 | Ордер-флоу прокси из OHLCV | CLV (close в диапазоне бара) + z-объём → реверсал/продолжение |
|
||
| 7 | Liquidity sweep | прокол экстремума за N баров и возврат в диапазон |
|
||
| 8 | Volatility breakout | пробой диапазона N баров с фильтром персентиля ATR |
|
||
| 9 | Внутридневная сезонность | часы UTC (Азия/Лондон/НЙ) |
|
||
| 10 | Intraday momentum | импульс первой половины дня → вторая половина |
|
||
| 11 | Funding-carry внутри дня | уровень/знак funding → позиция до момента выплаты (топ-30 пар) |
|
||
| 12 | Пары на 5м | спред BTC/ETH, Engle-Granger за 30 дней |
|
||
| 13 | Открытие/закрытие: базис перп−спот | прокси funding на 5м |
|
||
| 14 | Комбинация «час дня + реверсал» | сезонный реверсал |
|
||
| 15 | ML (LightGBM) на OHLCV-фичах | walk-forward, обязана побить порог издержек |
|
||
|
||
Каждый метод: фиксированная конфигурация (без перебора параметров), прогон на всей выборке и на
|
||
OOS-половине (вторая половина времени), ≥100 сделок, разбивка по годам.
|
||
|
||
## 5. Протокол честности (этапы Э5–Э7)
|
||
|
||
Жёсткие требования (без них цифры не принимаются):
|
||
|
||
1. **Плацебо**: сигнал, сдвинутый вперёд на горизонт удержания, должен давать ≈0 (медиана |EV| < 3 б.п.).
|
||
2. **Рандом-контроль**: случайные входы с той же частотой — эталон «нуля».
|
||
3. **Альфа, а не доходность**: сравнение с «купил и держу» и с лонг-шорт-конструкцией; на растущем
|
||
рынке сырые б.п. обманывают (урок прошлого кейса: плацебо дало те же +33…50 б.п.).
|
||
4. **Издержки** тейкер И мейкер; проскальзывание 1 б.п. на ногу (3 б.п. вне топ-30 по обороту);
|
||
funding при удержании через момент выплаты. Считать от нотионала, а не от «спреда».
|
||
5. **Поправка на множественное тестирование**: `reports/count_tests.json` — число вариантов и порог
|
||
Бонферрони (для 12–20 проверок |t| ≈ 2,9…3,1; для 40 ≈ 3,3).
|
||
6. **Block-bootstrap** по дням вместо наивного t (перекрывающиеся окна раздувают t).
|
||
7. **По годам**: убыточный год — не приговор, но кандидат обязан быть плюсовым минимум в 2 из 3 лет.
|
||
8. **Ликвидность**: отдельный прогон по топ-30 парам (эдж из неликвида не считается).
|
||
9. **Опровергнутое** — в `docs/REJECTED.md` таблицей с цифрами (часть ценности, не «мусор»).
|
||
|
||
## 6. Артефакты и контракты файлов (по ним проверяют гейты)
|
||
|
||
| Этап | Файл | Контракт |
|
||
|---|---|---|
|
||
| Э1 | `data/5m/*.csv` | ≥100 файлов, 6 полей, без шапки |
|
||
| Э1 | `data/manifest_5m.json` | ≥100 пар, суммарно ≥15 млн баров, ≥40 пар ≥12 мес |
|
||
| Э1 | `reports/validate_5m.json` | `dup=0`, медиана `coverage` ≥ 0,95 |
|
||
| Э2 | `reports/stand_reconcile.json` | ≥4 пары, расхождение PF ≤ 5 % |
|
||
| Э3 | `reports/costs.json`, `reports/COSTS.md` | `fees_pct_per_leg {taker:0.055,maker:0.02}`, ≥5 сценариев `p*`, MD ≥1500 Б |
|
||
| Э4 | `results/methods/*.csv` | ≥12 файлов, ≥100 сделок, ≥4 колонки |
|
||
| Э4 | `results/summary_5m.csv` | ≥12 строк, колонки `method,n_trades,ev_bp,ev_bp_oos,t_boot,placebo_ev_bp,rand_ev_bp,sharpe,max_dd_pct,by_year_ok` |
|
||
| Э5 | `reports/by_year.csv` | ≥12 методов × ≥3 года |
|
||
| Э5 | `reports/count_tests.json` | `n_tests ≥12`, `bonferroni_t ≥2.9` |
|
||
| Э5 | `reports/PLACEBO.md` | ≥800 Б, числа по каждому методу |
|
||
| Э6 | `docs/REJECTED.md` | ≥12 строк таблицы с цифрами |
|
||
| Э6 | `charts/*.png` | ≥3 графика |
|
||
| Э7 | `reports/VERDICT.md` | первая строка «ВЕРДИКТ: …», итог — «ПОЛОЖИТЕЛЬНОЕ МАТОЖИДАНИЕ» или «ОТРИЦАТЕЛЬНЫЙ РЕЗУЛЬТАТ» |
|
||
| Э8 | `strategies/<name>/rules.md`, `bot/paper_5m.py`, `reports/paper_dry_run.json`, `reports/paper_first_report.md`, `reports/FORWARD_PLAN.md` | при наличии кандидата; иначе `reports/NO_CANDIDATE.md` (≥12 строк) |
|
||
| Э9 | `reports/PUBLISH.md`, `README.md` | ссылка на репо + ≥7 страниц вики; README ≥3000 Б |
|
||
|
||
## 7. Порядок работы и бюджет
|
||
|
||
1. Ф1 (данные + стенд + планка) → гейт Ф1.
|
||
2. Ф2 (методы + плацебо + Бонферрони + по годам) → гейт Ф2.
|
||
3. Ф3 (вердикт + кандидат/отрицательный результат + демо-бот + публикация) → гейт Ф3.
|
||
4. Бюджет цикла: `goals.max_turns = 60` (проверено в `/opt/data/config.yaml`); при исчерпании — `/goal resume`.
|
||
5. Каждый ход обязан записывать артефакт (файл/лог), иначе цикл встаёт с формулировкой «нечего оценивать».
|