Ищем Грааль на рынке криптовалют

от автора

Датасет и скрипты опубликованы на HuggingFace

У TradingView есть портал Ideas. Это система личных блогов трейдеров, куда они постят свои догадки. Ценность информации в том, что такая догадка сразу содержит направление: SHORT или LONG. Это позволяет посчитать настроения на рынке

Я посмотрел, заметил что API не сложное, легко сдампить. Делюсь результатами анализа

Инвестиция глазами бизнеса: четыре оси

Прежде чем спрашивать «хорош ли аналитик», надо определить, что такое инвестиция с точки зрения управления рисками. Ответ раскладывается на четыре величины:

  • сколько времени заморожены деньги — максимальное удержание позиции;

  • какую просадку инвестор готов терпеть — глубина жёсткого стопа;

  • какая прибыль считается достаточной — уровень фиксации (profit lock);

  • сколько отдать от пика при развороте — откат трейлинга.

Откуда взять вход в позицию из этой догадки

Все гениальное просто: перебрать грубой силой. Каждая комбинация этих четырёх величин это отдельная стратегия чтения одного и того же прогноза.

hardStopPercent:      1 … 10 %        (19 значений)trailingTakePercent:  0.5 … 5 %       (10 значений)holdMinutes:          1 … 14 суток    (14 значений)profitLockPercent:    1 … 5 %         (8 значений)                                      = 21 280 точек

После перебора мы получим Positive и False Positive вперемежку в одной выборке. Они идут кластером по sharpe ratio, остальные это промахи, не являются входами вовсе. Торговать на этом не получится, так как мы не знаем точно какой из вариантов эффективного входа выбрал автор, но это позволяет оценить догадку по существу: а могло ли оно вообще принести деньги

Неудачные попытки

Прежде чем дойти до работающего отбора, я сделал полтора десятка попыток. Ниже примечательные из них чтобы быстро ввести в контекст как ведет себя толпа

Отбор авторов по прошлому результату

  • По hitRate прошлого месяца. Чистая регрессия к среднему — прошлая точность не содержит информации о будущей.

  • Пороговые критерии. Защита от малой выборки честно работает и потому надёжнее всех находит авторов на пике удачи, но прямо перед регрессией.

  • Удлинение трека до 2/3/6 месяцев. Тенденция к улучшению есть, ноль не пересекается ни разу.

  • Отбор внутри одного символа. Минус на всех четырёх проверенных символах.

  • Score = число удачных месяцев. Премирует долгожителей, а не точных: не хватит никакой выборки сделать и backtest и paper, 64 месяца мало

  • «Ни одного провального месяца». Единственная статистически значимая серия (21 месяц подряд) принесла копейки, а серия в 15 месяцев у другого автора закончилась убытком. Серии не переводятся в деньги.

Персональные настройки под автора

  • Своё окно риска по hitRate. Оптимизатор у всех авторов уезжает в один угол сетки (трейлинг 0.5 %, лок 1 %) — тот самый, где hitRate ≈ 1.0 при убытке. Единое окно даёт всем авторам столько же плюсовых месяцев, сколько «персональные».

  • Своё окно по PnL. Учебная иллюстрация подгонки, окно зависит от режима рынка и не переносится между месяцами по автору

Толпа как сигнал

  • Консенсус направлений. Согласие авторов в окне ±24 часа выглядело рабочим фильтром — пока окно согласия было симметричным и включало посты, опубликованные после входа. Причинное окно (только прошлое) убивает эффект полностью: улучшение целиком создавали идеи из будущего, которых на момент сделки не существовало.

  • Кластеры постов как ранний сигнал. Вход в начале кластера ≈ вход по посту (разница в сотые доли процента на сделку). Кластеры, сдвинутые на случайные ±30 суток, зарабатывают столько же; кластеры, собранные из постов по чужим монетам, — даже больше настоящих. Плотность постов ловит общий дрейф рынка, а не вброс в конкретную монету.

  • Поиск бот-сетей. Посты кучкуются не потому, что авторы переписывают друг друга, а потому что хором реагируют на уже случившееся движение. Прямой замер: тот же набор идей со входом на неделю раньше публикации был бы в 3–5 раз выгоднее — во всех 100 розыгрышах из 100. Пост стоит в конце движения, а не в начале.

Общий знаменатель всех провалов один: рейтинг по прошлому результату умеет находить плохих авторов и не умеет находить хороших. Худшие по любому рейтингу стабильно хуже случайного выбора; лучшие — не лучше него ни разу.

Правило исполнения, к которому мы пришли

Работа по новостям это Swing Trading. Позиции открываются на срок 14 дней. Обычный стоп лосс считается через внутридневную волатильность. Двухнедельная идея не имеет отношения: для нее ставится хард стоп — статистически недостижимое условие черного лебедя

вход        строго по публикации поста доверенного автора, ждать нельзя            (тот же набор идей со входом на 1–30 суток позже даёт около нуля)сторона     только LONG, только спотхолд        14 суток — это и есть фиксация убытка: не отработала — выходимпрофит-лок  20 %трейлинг    8 %стоп        статистически недостижим: предохранитель от чёрного лебедя,            не инструмент управления позицией

Ограничение жёсткое: конструкция реализуема только на споте без плеча, и размер позиции обязан считать глубокую просадку одной сделки допустимым исходом, а не «маловероятным». Убыток фиксирует таймер. Роли выходов в этой конструкции распределены так:

  • профит-лок и трейлинг — фиксация прибыли, они и создают эдж;

  • истечение холда (14 суток) — штатная фиксация убытка: идея не отработала за свой горизонт — выходим, не дожидаясь «отскока»;

  • стоп — предохранитель от чёрного лебедя, поставленный статистически недостижимо для рабочих движений рынка. Его срабатывание — не торговое событие, а авария.

Кто такой лидер мнений на самом деле

Итог переворачивает само определение. Лидер — это не автор с лучшим треком: любой рейтинг по прошлому результату не отличим от случайного выбора или хуже него. Лидер — это тот, кто пишет, когда по монете ещё тихо: не больше двух чужих постов по символу за сутки до его публикации.

автор

идей за окно

доля ранних

роль

coinpediamarkets

78/год

60 %

доверенный №1

DEXWireNews

15

60 %

доверенный №2

Склонность писать в тишине оказалась самым устойчивым свойством автора в датасете. И отбор по ней работает вперёд, walk-forward, без подглядывания в результаты: топ-2 автора по доле ранних постов за прошлые 12 месяцев бьёт случайный выбор из тех же допущенных

автор

идей всего

доля ранних

PnL/сд ранних

PnL/сд поздних

PnL/сд всего

coinpediamarkets

189

76 %

+3.861

−0.387

+2.850

DEXWireNews

91

57 %

+15.003

+0.990

+8.997

Пост считается ранним, если за 24 часа до его публикации по тому же символу вышло не больше 2 чужих постов. Лента для подсчёта — все посты, включая NEUTRAL (нейтральные не торгуются, но шум в ленте создают). То есть «ранний» = «написал в тишину», а не «написал первым в цепочке». Никакого кластера, к которому надо привязаться, не нужно — у каждого поста своя скользящая 24-часовая ретроспектива, и вопрос continuous-ленты снимается: ранним может быть любой пост в любой момент, если вокруг него было тихо.

Проверка живьём: paper trading

Задача стенда — одна: подтвердить или опровергнуть гипотезу о лидере мнений на практике. Поэтому бэктест уходит на стенд, который торгует правило на бумаге в реальном времени, — исполнение заморожено, проверяется только отбор. Крутить исполнение параллельно значило бы проверять две гипотезы сразу.

Параметры стенда:

  • отбор: топ-2 автора по доле ранних постов за скользящие 12 месяцев, допуск ≥ 10 идей за окно — допуск заодно гарантирует, что автор жив и пишет;

  • вход: строго по публикации поста доверенного автора, в его сторону, без ожидания;

  • исполнение: холд 14 суток, профит-лок 20 %, трейлинг 8 %, стоп статистически недостижим — только LONG, только спот;

  • символ: пока BTCUSDT;

  • пересчёт доверенных: ежемесячно;

  • скрейпер: опрашивает ленты каждые 10 минут и пишет per-idea

Ожидаемый темп — единицы сделок в месяц: правило редкое, недели тишины — норма. Забавная деталь про выбор окна отбора: бектест выводит в топ авторов, которые давно перестали писать. Короткое окно с порогом активности решает это само. Лучшая статистика выбрала мёртвых; прод выбирает живых.

Код отбора ранних авторов для копипасты

function pickEarlyAuthors(ideas, testMonth, K = 2, EARLY_MAX = 2, WIN_H = 24) {  const from = monthAdd(testMonth, -12), to = testMonth;  const bySym = groupBy(ideas, (i) => i.symbol);   // ВСЕ посты, и NEUTRAL  const stat = {};                                  // author -> [ранних, всего]  for (const list of Object.values(bySym)) {    list.sort((a, b) => a.ts - b.ts);    let lo = 0;    list.forEach((idea, hi) => {      if (idea.ts < from || idea.ts >= to || idea.direction === "NEUTRAL") return;      while (list[lo].ts < idea.ts - WIN_H * 3600e3) lo++;      let others = 0;      for (let j = lo; j < hi; j++) if (list[j].author !== idea.author) others++;      const s = (stat[idea.author] ??= [0, 0]);      s[0] += others <= EARLY_MAX ? 1 : 0;      s[1] += 1;    });  }  return Object.entries(stat)    .filter(([, s]) => s[1] >= 10)    .sort((a, b) => b[1][0] / b[1][1] - a[1][0] / a[1][1])    .slice(0, K)    .map(([author]) => author);}

Спасибо за внимание!

ссылка на оригинал статьи https://habr.com/ru/articles/1064898/