ARANEA
ARANEA личный блог
Вчера в 20:33

ARANEA: CPU, GPU и ИИ не делают торговую стратегию умной. Часть 5

ARANEA: CPU, GPU и ИИ не делают торговую стратегию умной. Часть 5


После статей про ARANEA в комментариях быстро появилась тема GPU. Это ожидаемо: когда речь идет о сотнях миллиардов и триллионах прикладных оценок, первый вопрос почти всегда звучит так: зачем считать это на CPU, если можно вынести симуляцию на GPU?
Второй вопрос рядом: зачем вообще строить сложный исследовательский контур, если сейчас есть ИИ, Python, Numba, Taichi, CUDA и можно быстро нагенерировать код?

Оба вопроса нормальные. Но в них часто смешиваются разные слои задачи.

GPU может резко ускорить массовую симуляцию. ИИ может помочь быстрее написать код, набросать прототип, подготовить утилиту, нарисовать отчет, сгенерировать обвязку или подсказать техническое решение. Но ни GPU, ни ИИ сами по себе не отвечают на главный вопрос алгоритмической торговли:  что именно мы считаем торговой закономерностью, как проверяем ее живучесть и почему результат не является просто красивым максимумом прошлого участка?

Эта мини-серия будет не про спор «CPU против GPU» и не про спор «человек против ИИ». Мне интереснее другое: где заканчивается скорость вычислений и начинается исследование стратегии.

Стартовая позицияЯ не спорю с тем, что GPU может быть очень быстрым. Если задача уже приведена к плотному однотипному batch-у, где есть подготовленные сигналы, одинаковый цикл симуляции и много независимых параметров, GPU может дать большой прирост.Но это не вся задача.

Здесь стоит ненадолго остановиться на слове `batch`. Дальше будет краткое пояснение для общего развития, без попытки превратить статью в учебник по архитектуре процессоров и видеокарт. В общих чертах этого достаточно, чтобы понять, почему один и тот же оптимизатор может в одних местах хорошо жить на CPU, а в других проситься на GPU.
Batch — это не просто «много задач». Это пачка задач, которую система может обработать одним организованным проходом. В торговой оптимизации такой пачкой может быть набор PM-прогонов для одной entry-карты, одна группа похожих параметров stop/take, один срез стратегий по инструменту или серия профилей, у которых уже подготовлены одинаковые входные данные.

Хороший batch имеет несколько признаков:

1. данные уже лежат в удобном виде;
2. задачи внутри batch-а похожи друг на друга;
3. цикл расчета у них одинаковый или почти одинаковый;
4. память читается предсказуемо;
5. результат можно сохранить компактно;6. не нужно на каждом шаге принимать сложное разветвленное решение.

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

CPU устроен как универсальный исполнитель. У него немного мощных ядер, сложная логика предсказания ветвлений, развитые кэши, быстрый доступ к разным участкам памяти и хорошая способность быстро переключаться между неодинаковыми задачами. Поэтому CPU хорошо чувствует себя там, где расчет не идеально ровный: где есть условия, фильтры, пропуски, разные типы PM, разные правила выхода, разные форматы артефактов и постоянная работа с кэшами.

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

Отсюда простое практическое отличие. CPU удобен как диспетчер и исследовательский контур: подготовить данные, построить карты, отбросить мусор, разложить задачи по группам, проверить контракты, сохранить артефакты, собрать отчет. GPU удобен как ускоритель уже подготовленного плотного участка: взять большой массив однотипных PM-задач и быстро прогнать его по одинаковому циклу.

В ARANEA batch — это не случайная пачка комбинаций, которую просто бросили в цикл. Перед ним есть работа: нормализовать данные, построить TR/STEP/EMA/ATR-слои, подготовить entry-карты, сгруппировать совместимые входы, отрезать пустые ветки, выбрать PM-семейство, задать правила stop/take и понять, какие метрики нужно сохранить. Только после этого появляется вопрос: этот конкретный кусок выгоднее считать на CPU или его уже можно отдать на GPU?

В реальном исследовательском контуре есть несколько разных слоев:

1. подготовка данных;
2. расчет индикаторных рядов;
3. построение entry-карт;
4. отсечение веток с нулевыми или слабыми входами;
5. группировка входов;
6. разные PM-семейства;
7. разные stop/take/trailing-автоматы;
8. pruning;
9. расчет метрик;
10. сохранение артефактов;
11. правая сторона истории;
12. повторный запуск;
13. сборка пулов;
14. связь с торговым runtime.
и много чего еще 

GPU может быть сильным исполнителем внутри этой цепочки. Но он не заменяет саму цепочку.
TSLab, Zorro и вопрос про стек
ARANEA: CPU, GPU и ИИ не делают торговую стратегию умной. Часть 5



Для сравнения удобно взять две известные программы из этой области.

TSLab — это визуальная среда для сборки торговых стратегий. Ее сильная сторона в том, что трейдер может собрать логику блоками, увидеть входы на графике, запустить оптимизацию и работать с результатами без написания собственного движка.

Zorro — это другой тип инструмента. Он ближе к программной среде для бэктестинга, оптимизации и автоматизации торговых систем через код и скрипты. Там меньше визуального конструктора в стиле TSLab, зато больше прямого программного контроля над логикой.

Обе программы решают реальные задачи. И здесь появляется хороший инженерный вопрос: если разработчики знают преимущества других языков, GPU, новых библиотек и современных подходов, почему они просто не перепишут весь стек?


Ответ простой: потому что зрелый торговый продукт — это не только язык.

Внутри есть:
1. совместимость старых стратегий;
2. формат данных;
3. поведение бэктестера;
4. правила исполнения сделок;
5. комиссии, проскальзывание, stop/take;
6. пользовательский интерфейс;
7. тысячи ожиданий пользователей;
8. баги, которые уже найдены и исправлены;
9. документация и привычные сценарии работы;
10. интеграции с брокерами, файлами, отчетами и внешними сервисами.

Переписать такой продукт «на более быстрый язык» — это не просто заменить синтаксис. Это риск изменить поведение старых стратегий, сломать доверие к результатам, потерять совместимость и несколько лет заново ловить ошибки, которые в старом контуре уже были пройдены.

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

Это важно и для ARANEA. Я не пишу, что TSLab или Zorro «плохие», потому что они не устроены как мой контур. У них другая задача, другая история и другая аудитория. ARANEA появилась не как замена любой программе, а как ответ на мой конкретный предел: мне нужен был не только сборщик стратегии или быстрый бэктестер, а управляемая исследовательская машина вокруг множества гипотез, PM, метрик, правой стороны и runtime.

Скрипт, движок и полноценное ПО
Еще одна ошибка на старте — считать оптимизатор или торговый движок полноценным программным продуктом.

Скрипт полезен, когда нужно быстро проверить идею: загрузить данные, посчитать показатель, прогнать один набор параметров и понять, есть ли смысл двигаться дальше. Но как только появляются разные рынки, таймфреймы, кэши, PM, отчеты, повторные запуски и live-режим, простой скрипт начинает держаться на ручных договоренностях.

В этот момент главная проблема уже не в скорости, а в воспроизводимости. Через неделю становится трудно понять, какие данные были на входе, какая версия правил считалась, были ли комиссии, как работали stop/take и можно ли вообще сравнивать новый отчет со старым.

Поэтому вокруг расчета нужна инженерная оболочка: явная конфигурация, проверка данных, версии правил, единые контракты стратегий и PM, управляемые кэши, лимиты памяти, логи, метрики, артефакты и checkpoint-и. Эти слои нужны не для красоты, а чтобы результат можно было объяснить, повторить и безопасно перенести из research в live.

Для торговой системы это критично. Ошибка в отчете неприятна, ошибка в runtime может стоить денег, а ошибка в оптимизации может убедить человека, что стратегия рабочая, хотя на самом деле был проверен другой эксперимент.

Поэтому серьезный оптимизатор должен расти не как один большой файл, а как исследовательская система: сначала данные и контракты, потом расчет, кэши, метрики, отчеты, проверка правой стороны и только затем live runtime. А уже внутри этой архитектуры можно выбирать, где считать: CPU, GPU, Go, Rust, C++, Python или смешанным контуром.

Почему я начал не с GPU
ARANEA: CPU, GPU и ИИ не делают торговую стратегию умной. Часть 5


Я видел, как на хорошем оборудовании люди собирали быстрый вычислительный стек, но при этом долго не могли понять, что именно происходит внутри расчета. Машина мощная, все вроде бы крутится, отдельные замеры выглядят прилично, но много времени уходит на тестирование, повторные прогоны, поиск узкого места и попытку объяснить, почему один режим ускорился, а другой внезапно начал вести себя хуже.

Хорошее оборудование в целом прощает много ошибок. Оно может быстро проглотить лишние копирования, неудачные структуры данных, неидеальную группировку задач, слишком широкий batch или неудачный порядок кэшей. До определенного момента кажется, что система работает нормально, потому что абсолютное время все еще выглядит приемлемым.

Старое оборудование ведет себя иначе. Оно показывает слабость еще до красивых замеров. Если batch собран плохо, оно не «чуть медленнее считает», а сразу упирается в память, ловит bottleneck, начинает захлебываться на очередях или просто падает. Это неприятно, но полезно: архитектурные ошибки становятся видны раньше.

Поэтому старый компьютер, как ни странно, помог мне в этом процессе. Он заставлял строить ПО параллельно с изучением тонкостей самого расчета: где данные нужно подготовить один раз, где нельзя плодить копии, где нужен кэш, где нужен checkpoint, где batch слишком разнородный, а где уже можно думать об ускорителе.

В первых статьях замеры идут на старом компьютере:
CPU: Intel Core i5 750 @ 2.67  GHzRAM: 16 GB SSD: Samsung 870 EVO 250 GB GPU: AMD Radeon R9 200 Series, 2 GB
Это не сервер и не современная рабочая станция. Более того, в рабочих конфигурациях ARANEA расчет часто ограничен несколькими CPU-ядрами, чтобы машина оставалась стабильной и не упиралась в память.

Именно поэтому этот пример полезен. Он показывает не максимальную скорость железа, а роль архитектуры:1. что можно не считать вообще;
2. что можно подготовить один раз;
3. что можно переиспользовать;
4. что можно отсечь до тяжелого PM-прогона;
5. что нужно сохранить;
6. что нужно проверить на правой стороне.

Если перенести тот же подход на сервер уровня `AMD EPYC 9554` с `64` ядрами / `128` потоками, `128-256 GB RAM` и добавить `2-4` GPU класса `RTX 4090`, `RTX 6000 Ada` или `L40S`, цифры будут другими. Плотные PM-batch-и можно отправлять на GPU и получать уже не сотни тысяч, а миллионы или десятки миллионов PM-оценок в секунду на подходящих задачах.

Но это не отменяет главный слой: сначала нужно понять, какие batch-и вообще стоит считать.

Что означает скорость GPU

Когда кто-то пишет: я считаю `200 000` комбинаций в секунду на GPU это может быть сильным результатом. Но для сравнения нужно уточнить, что такое «комбинация».

Это может быть:1. одна стратегия с разными параметрами;
2. один PM;
3. один набор stop/take/trailing-автоматов;
4. уже подготовленные сигналы;
5. одна целевая метрика;
6. без полного набора метрик;
7. без сохранения всех промежуточных веток;
8. без правой стороны9. без повторного анализа профилей.

В таком случае `200 000` комбинаций в секунду — это скорость backend-слоя симуляции. Это хорошо. Но это не то же самое, что скорость исследования.

Для ARANEA важнее другая метрика: сколько полезных гипотез прошло полный путь: entry -> фильтры -> PM -> pruning -> метрики -> правая сторона -> сохранение результата.

Где CPU выигрывает у GPU
CPU выигрывает не потому, что он всегда быстрее. Он выигрывает там, где задача плохо ложится в плотную GPU-форму:

1. много ветвлений;
2. разные PM-семейства;
3. разные длины жизни сделок;
4. разные stop/take/trailing-состояния;
5. sparse-entry, где большая часть веток не дала сделок;
6. разные уровни детализации метрик;
7. постоянная работа с кэшами, файлами, очередями и артефактами;
8. последовательная логика pruning;
9. необходимость сохранить не только лучшую строку.

GPU любит плотную однотипную математику. В торговой оптимизации до этой стадии еще нужно дойти. Возьмем условный пример, максимально упрощенный.

Есть ряд баров:

x_t = (O_t, H_t, L_t, C_t, V_t)

Считаем несколько рядов:

EMA_t(n) = alpha * C_t + (1 — alpha) * EMA_{t-1}(n)  alpha = 2 / (n + 1)
TR_t = max(
  H_t — L_t,  abs(H_t — C_{t-1}),  abs(L_t — C_{t-1}))

Строим простой entry-сигнал: entry_t(p) = 1, если C_t > EMA_t(n) и TR_t > q
entry_t(p) = 0, иначе
Дальше PM-прогон для параметров `theta`:theta = (stop_pct, take_pct, max_bars, fee, slip)

stop_price = entry_price * (1 — stop_pct)
take_price = entry_price * (1 + take_pct)

exit_t = stop, если L_t <= stop_price
exit_t = take, если H_t >= take_price
exit_t = time, если age >= max_bars

pnl = (exit_price — entry_price) / entry_price — fee — slip

На бумаге это выглядит как одна формула. В реальном оптимизаторе вокруг нее появляется много служебной логики: какие `entry_t` вообще дали сделки, какие параметры пустые, какие PM-семейства совместимы между собой, какие метрики сохранять, какие ветки можно отсечь до тяжелого расчета.
На CPU/Rust такая последовательность может выглядеть так:

Условный пример, не код ARANEA.
let bars: Vec<Bar> = load_and_validate_bars(path)?;
let ema = build_ema(&bars, n);
let tr = build_tr(&bars);

let entries: Vec<EntryEvent> = bars.iter()
    .enumerate()
    .filter_map(|(i, b)| {
        if b.close > ema[i] && tr[i] > q {
            Some(EntryEvent { index: i, price: b.close })
        } else {
            None
        }
    })    .collect();

if entries.len() < min_trades {
    return Ok(None);
}

let groups = group_compatible_pm_params(&entries, &pm_params);
for group in groups {
    let batch = build_dense_pm_batch(&bars, &entries, &group);
    let result = run_pm_on_cpu_or_gpu(batch);    save_metrics_and_artifacts(result)?;
}
CPU здесь делает много разной работы: проверяет данные, строит ряды, создает sparse-список входов, отсекает пустые ветки, группирует параметры, решает, что считать дальше. Это не идеально ровная математика. Здесь много условий и решений.

На GPU/Python такой же фрагмент имеет смысл только после того, как batch уже стал плотным:

Условный пример на CuPy/Numba-подобной логике.
bars_gpu = cp.asarray(bars_ohlc)          # [bars, 4]
entries_gpu = cp.asarray(entry_indices)   # [entries]
params_gpu = cp.asarray(pm_params)        # [params, 3]

kernel считает сетку [params x entries]pnl_matrix = pm_kernel(
    bars_gpu,    entries_gpu,
    params_gpu,
    fee,
    slip,
)

net_pnl = pnl_matrix.sum(axis=1)
max_dd = calc_drawdown_gpu(pnl_matrix)

GPU-часть хороша, если `entries_gpu` уже подготовлен, `params_gpu` плотный, память лежит ровно, а kernel делает один и тот же цикл для тысяч или миллионов независимых вариантов. Если же внутри каждого варианта разные правила, разные stop/take-автоматы, разные длины жизни сделок и много пропусков, видеокарта начинает терять свое преимущество: потоки расходятся по ветвлениям, память читается неровно, а передача данных туда-обратно съедает часть выигрыша.

Поэтому в такой задаче CPU чаще выигрывает на этапах подготовки и управления исследованием, а GPU — на узком участке плотного PM-batch-а. GPU здесь не враг. Он просто не главный архитектор исследования.

Почему ИИ-vibe coding не решает эту задачу
ARANEA: CPU, GPU и ИИ не делают торговую стратегию умной. Часть 5

ИИ действительно ускоряет разработку. Он может быстро написать прототип стратегии, переписать цикл, накидать GPU-kernel, добавить график equity или собрать черновой отчет.

Но в торговой системе чаще ломается не синтаксис. Ломается постановка эксперимента: в данные попал будущий бар, stop/take активируется не в тот момент, комиссия считается не так, OOS слишком короткий, соседние параметры не проверены, а лучший результат выбран по одной красивой метрике.ИИ не знает, какой именно контракт исполнения сделок вы считаете правильным. Он не отличит рабочую рыночную гипотезу от красивой подгонки, если сама система не заставляет проверять данные, правую сторону, комиссии, проскальзывание и повторяемость запуска.

Поэтому в алготрейдинге опасность «vibe coding» не в том, что код будет медленным. Опасность в том, что он быстро и уверенно посчитает неправильный эксперимент.

Что в этом всем делает ARANEA

ARANEA не строится вокруг идеи «CPU лучше GPU» или «GPU не нужен». Наоборот, GPU может стать вторым исполнительным контуром для плотных PM-batch-ей.

Но первый уровень задачи другой:

1. разложить торговую идею на ветки;
2. понять, какие ветки вообще дают сделки;
3. отсечь пустое и слабое до тяжелого расчета;
4. не потерять соседние решения;
5. считать PM не как одну кнопку, а как семейства управления позицией;
6. хранить результаты;
7. проверять правую сторону;
8. повторять эксперимент;
9. использовать результаты в торговом runtime.

Поэтому я начал с CPU/Rust/Go-контура. Не потому что GPU бесполезен. А потому что сначала нужна система, которая решает, что именно считать.

Главная мысль этой части
GPU может ускорить симуляцию. ИИ может ускорить написание кода. Но ни GPU, ни ИИ не превращают слабую торговую гипотезу в рабочую стратегию.

В алгоритмической торговле опасно путать три разные вещи:

1. скорость вычислений;
2. качество исследовательской постановки;
3. торговую пригодность результата.

Можно очень быстро максимизировать одну метрику и получить красивую equity на истории. Но это еще не значит, что найден живой принцип. Для этого нужны карта гипотез, отсечения, метрики риска, правая сторона, повторяемость и понимание того, где стратегия живет как семейство, а не как одна случайная строка.
Именно поэтому вопрос «CPU или GPU?» для меня вторичен. Главный вопрос звучит иначе:что мы считаем, зачем мы это считаем, что не считаем вообще и как проверяем, что результат не умер за пределами видимого участка?
Данная публикация является личным мнением автора. Мнение владельца сайта может не совпадать с мнением автора.
1 Комментарий
  • sergik99
    Вчера в 22:35
    Чем дальше, тем больше длинных текстов.
    Это дипфейкуи от ИИ?

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн