Обновить

DiffQuant: прямая оптимизация коэффициента Шарпа через дифференцируемый торговый симулятор

Уровень сложностиСложный
Время на прочтение15 мин
Охват и читатели8.8K
Всего голосов 7: ↑7 и ↓0+9
Комментарии8

Комментарии 8

А ваши разработки нельзя использовать в игре foodtrack bench?

Проект заточен под финансовые временные ряды, так что для food truck напрямую не подойдёт. Но дифференцируемый симулятор в теории адаптируем под любую задачу с end-to-end оптимизацией метрики.

Хотелось бы видеть какие-то обоснования того , что при указанных входных данных, решаемая задача вообще имеет хоть какое-то осмысленное решение. В математике так часто бывает. Проблема есть. Методы решения есть. А решения нет. Принципиально.

PS: Вот Вы пишете в комментах - " Проект заточен под финансовые временные ряды ". Под временные ряды понятно. Это довольно абстрактное понятие. А при чем здесь финансы? Где это можно увидеть в Ваших формулах?

Спасибо за вопрос по существу.
По первому пункту: строгого доказательства существования решения у меня нет, и я на него не претендую. Два положительных held-out квартала это эмпирический сигнал, а не теорема. Именно поэтому раздел "Ограничения" написан как принципиальная часть статьи, а не как формальная оговорка.
По второму: финансовая специфика здесь не в самой алгебре, а в интерпретации переменных и в постановке задачи. p - торговая позиция (long/short), r - рыночная доходность, вычисленная из реальных цен, cost - комиссия и проскальзывание. Objective - коэффициент Шарпа. Именно это и делает абстрактный time-series framework торговой постановкой.

Вы во входных данных берёте стандартный временной ряд плюс объёмы, и как они по вашему они должны повлиять на будущие данные в стохастическом процессе? У вас есть канал для связи, а то вы призываете к обсуждению, а где?

Спасибо за хороший вопрос.

По OHLCV, я не исхожу из того, что эти данные детерминированно определяют будущее. Гипотеза слабее: в них могут существовать локальные статистические зависимости и режимные асимметрии, которые проверяются только эмпирически. Объёмы здесь не "магический предиктор", а прокси ликвидности и интенсивности движения. Два положительных held-out квартала это сигнал к дальнейшей проверке, не закрытый вопрос.

Для технического обсуждения - GitHub Issues: github.com/YuriyKolesnikov/diffquant

Как успехи с проектом?

Спасибо! Проект развивается нормально.

Главное направление сейчас: переход от single-asset версии к управлению портфелем. Идея остаётся той же: модель обучается не на прокси-цели, а через дифференцируемый торговый симулятор напрямую под торговую метрику.

В первой версии модель управляла одной позицией:


p_t = \tanh\left(\frac{d_t}{\tau_d}\right) \cdot \sigma\left(\frac{g_t}{\tau_g}\right)

где p_t \in [-1, 1]. Отрицательное значение означает short, положительное значение означает long, значение около нуля означает отсутствие активной позиции.

В портфельной версии модель выдаёт уже не одну позицию, а сырой сигнал по каждому активу:


s_{i,t} = \tanh\left(\frac{d_{i,t}}{\tau_d}\right) \cdot \sigma\left(\frac{g_{i,t}}{\tau_g}\right)

Здесь s_{i,t} ещё не финальный вес портфеля. Это score по активу (i): знак отвечает за направление, модуль отвечает за силу сигнала.

Дальше эти сигналы превращаются в относительные long/short веса портфеля. Например, через рыночно-нейтральную проекцию:


u_{i,t} = s_{i,t} - \frac{1}{N}\sum_{j=1}^{N}s_{j,t}


w_{i,t} = G \cdot \frac{u_{i,t}}{\sum_{j=1}^{N}\sqrt{u_{j,t}^{2}+\varepsilon}}

где (N) это число активов, (G) это заданный общий gross exposure портфеля, а w_{i,t} это финальный вес актива (i).

Например, если (G = 1), то сумма абсолютных весов портфеля будет около 100%.

После такой нормализации положительные веса становятся long-позициями, отрицательные веса становятся short-позициями, а общий размер портфеля остаётся контролируемым.

Портфельная доходность считается уже по всей корзине активов:


gross_t = \sum_{i=1}^{N} w_{i,t-1} \cdot r_{i,t}

где r_{i,t} это доходность актива (i) на шаге (t).

Дальше учитываются комиссии, проскальзывание и стоимость ребалансировки:


\Delta w_{i,t} = w_{i,t} - w_{i,t-1}


cost_t = \sum_{i=1}^{N} c_i \cdot \left|\Delta w_{i,t}\right|


net_t = gross_t - cost_t

То есть tanh не исчезает, он просто перестаёт быть финальной позицией. В single-asset версии он сразу задавал позицию, а в портфельной версии он даёт сырой сигнал по каждому активу. Финальные веса появляются уже после портфельной нормализации.

Если интересно, такую версию можно реализовать довольно прямо: заменить single-asset head на multi-asset score head, добавить слой нормализации весов и считать уже portfolio-level PnL / Sharpe с учётом комиссий, проскальзывания и оборота.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации