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

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

Алгоритмическая торговля представляет собой показательный пример такой задачи. Текстовое описание торговой идеи необходимо преобразовать в стратегию для конкретного фреймворка бэктестинга, корректно реализовать индикаторы и правила входа и выхода, а затем убедиться, что полученный код действительно запускается и совершает сделки на исторических данных.

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

Для исследования этих вопросов мы разработали QuantCode-Bench — бенчмарк для оценки способности больших языковых моделей генерировать исполняемые алгоритмические торговые стратегии по текстовым спецификациям. В нём оценивается не только техническая корректность кода, но и вся последовательность преобразования торговой идеи в наблюдаемое поведение стратегии.

Код, датасет и скрипты запуска опубликованы в репозитории QuantCode-Bench. Результаты моделей также доступны на публичной странице бенчмарка.

Что именно измеряет QuantCode-Bench

Задача модели формулируется просто: по англоязычному описанию торговой идеи необходимо сгенерировать стратегию для Backtrader.

Но успех определяется не одним тестом, а последовательностью вложенных требований.

Стратегия должна:

  1. быть синтаксически корректной;

  2. успешно исполниться в среде бэктеста;

  3. совершить хотя бы одну сделку;

  4. соответствовать исходной торговой идее.

Каждый следующий этап усиливает предыдущий.

Синтаксически корректный код может завершиться runtime-ошибкой. Исполняемая стратегия может не сгенерировать ни одного сигнала. Торгующая стратегия может реализовывать не ту логику, которая была указана пользователем.

Поэтому основной метрикой бенчмарка является Judge Pass — доля задач, в которых решение прошло весь пайплайн, включая финальную семантическую проверку.

Почему обычных кодовых метрик недостаточно

В классическом text-to-code бенчмарке прохождение тестов обычно означает, что программа реализовала требуемое преобразование. В алгоритмической торговле между текстовым заданием и наблюдаемым поведением кода появляется несколько дополнительных слоёв.

Неформальное описание нужно превратить в строгие правила

Торговая идея может быть сформулирована как точный набор условий:

Открывать long, когда RSI(14) опускается ниже 30, и закрывать позицию, когда RSI поднимается выше 70.

Но реальное описание нередко выглядит иначе:

Покупать откат в растущем тренде, если импульс сохраняется, а цена возвращается к быстрой EMA.

Во втором случае модель должна самостоятельно решить, как определить тренд, какой индикатор использовать для импульса, что считать откатом и какое событие считать подтверждением входа.

То есть задача включает не только генерацию кода, но и операционализацию естественно-языкового описания.

Нужно знать семантику конкретного API

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

Характерный пример — использование объекта Line как обычного логического значения:

if self.rsi < 30:
    self.buy()

В зависимости от контекста корректная работа требует обращения к текущему значению линии через индекс:

if self.rsi[0] < 30:
    self.buy()

Модель также может смешивать параметры и интерфейсы Backtrader, pandas-ta, TA-Lib и других библиотек.

Условия должны срабатывать на данных

Даже полностью исполняемый код может не совершить ни одной сделки. Причины бывают разными:

  • слишком строгая комбинация фильтров;

  • несовместимые пороги;

  • неверная интерпретация пересечения индикаторов;

  • недостаточное число баров для расчёта признаков;

  • условие вычисляется, но не связано с торговым действием;

  • логика корректна формально, но не активируется на выбранном активе и таймфрейме.

Поэтому наличие хотя бы одной сделки — отдельный этап оценки.

Торгующая стратегия может не решать исходную задачу

Предположим, пользователь запросил стратегию на основе RSI и уровней перекупленности и перепроданности. Модель вместо неё сгенерировала пересечение двух скользящих средних.

Такой код может компилироваться, проходить бэктест и совершать сделки. С технической точки зрения он работает. С точки зрения задания — нет.

Именно поэтому в QuantCode-Bench используется финальная проверка семантического соответствия.

Как устроен датасет

QuantCode-Bench содержит 400 задач разной сложности.

Источник

Количество

Reddit

183

TradingView

100

StackExchange

90

GitHub

19

Synthetic

8

Итого

400

Источники заметно различаются по стилю.

Reddit чаще содержит разговорные и неполные описания. TradingView обычно предлагает более формализованные идеи с индикаторами и параметрами. StackExchange сочетает вопросы по реализации с обсуждением торговой логики. GitHub содержит постановки, близкие к уже существующим программным реализациям.

После сбора каждая задача проходила структурное обогащение. Из исходного текста извлекались:

  • используемые индикаторы;

  • условия входа;

  • условия выхода;

  • дополнительные правила и ограничения;

  • параметры управления позицией;

  • уровень сложности.

Распределение по источникам и сложности выглядит так:

Источник

Easy

Medium

Hard

Всего

Reddit

147

16

20

183

TradingView

6

57

37

100

StackExchange

32

34

24

90

GitHub

12

1

6

19

Synthetic

0

8

0

8

Итого

197

116

87

400

Задачи оцениваются на исторических данных, соответствующих исходной постановке: для разных примеров используются разные активы и таймфреймы. Для разных постановок используются соответствующие исторические данные, активы и таймфреймы. Например, задача может относиться к дневным данным по акции, часовым данным по криптовалюте или внутридневным данным по валютной паре.

Это делает проверку ближе к исходному контексту стратегии и снижает зависимость результатов от одного конкретного рыночного режима.

Четыре этапа проверки

1. Compilation

На первом этапе код проверяется на синтаксическую корректность и возможность интерпретации.

Этот тест отсекает незакрытые скобки, неверные отступы, некорректную структуру класса и другие базовые дефекты.

2. Backtest

Затем стратегия запускается на предоставленных бенчмарком исторических данных.

На этом этапе проявляются:

  • обращения к несуществующим методам;

  • неверные параметры индикаторов;

  • ошибки типов;

  • неправильная работа с линиями Backtrader;

  • выход за границы доступной истории;

  • ошибки исполнения и тайм-ауты.

3. Trade

После успешного бэктеста проверяется, была ли совершена хотя бы одна сделка.

Этот критерий не оценивает прибыльность. Он отвечает на более базовый вопрос: реализована ли логика так, чтобы стратегия вообще проявляла торговое поведение на данных.

4. Judge

На финальном этапе LLM-судья сопоставляет код с исходной постановкой.

Проверяется:

  • используются ли требуемые индикаторы или допустимая эквивалентная формализация;

  • реализованы ли ключевые условия входа и выхода;

  • соответствует ли поведение стратегии заданию;

  • не заменена ли задача универсальным торгующим шаблоном.

Только прохождение всех четырёх этапов считается полным успехом.

Два режима: одна попытка и итеративное исправление

Single-turn

В single-turn режиме модель получает описание задачи и должна с первой попытки вернуть готовую стратегию.

Она не видит результат исполнения, не получает traceback и не может исправить код. Такой режим измеряет качество one-shot генерации: насколько хорошо модель сразу понимает спецификацию, знает Backtrader и связывает индикаторы с торговыми действиями.

Agentic multi-turn

В agentic multi-turn режиме после неудачной попытки модель получает структурированную обратную связь:

  • тип ошибки;

  • сообщение среды исполнения;

  • информацию о том, на каком этапе остановился пайплайн.

После этого она может изменить решение и повторить запуск. Максимальное число попыток — 10.

Этот режим измеряет уже не только генерацию, но и способность модели использовать диагностику, локализовать дефект и итеративно исправлять стратегию.

Результаты single-turn

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

Модель

Compilation, %

Backtest, %

Trade, %

Judge, %

gpt-5.5

100.0

99.8

84.8

82.5

claude-opus-4.8

100.0

98.0

78.8

77.0

claude-opus-4.6

100.0

98.2

77.2

75.8

gpt-5.4

100.0

95.5

72.0

70.2

claude-sonnet-4.5

100.0

91.5

71.2

69.8

gpt-5.2-codex

100.0

94.5

74.5

67.5

glm-5

100.0

92.4

70.3

65.4

claude-sonnet-4.6

100.0

85.8

66.2

65.0

kimi-k2.5

99.7

87.3

67.5

64.8

gemini-3-flash

100.0

76.0

63.2

59.8

grok-4.1-fast

99.2

70.2

56.1

48.9

deepseek-v3.2

100.0

75.8

50.0

48.8

qwen3-235b

100.0

72.5

49.0

48.2

qwen3-coder-30b

100.0

59.0

40.5

39.2

gemini-2.5-flash

99.5

49.2

33.2

31.2

qwen3-14b

98.0

42.2

27.8

25.2

qwen3-8b

99.5

31.8

19.8

18.5

qwen3-4b

98.8

24.6

16.4

12.3

qwen3-1.7b

98.1

23.1

13.7

7.8

Главное наблюдение: 100% Compilation почти ничего не говорит о конечном качестве.

Например, несколько моделей компилируют все 400 решений, но их Judge Pass различается на десятки процентных пунктов. Значит, основной разрыв возникает не в способности написать синтаксически корректный класс Python, а в правильном исполнении торговой логики.

Лучшая single-turn модель — GPT-5.5 с 82,5% Judge Pass. Claude Opus 4.8 достигает 77,0%, Claude Opus 4.6 — 75,8%.

При этом задача всё ещё далека от насыщения: даже лидер не решает 17,5% задач с первой попытки.

Результаты agentic multi-turn

Обратная связь резко меняет картину.

Модель

Comp., %

Backtest, %

Trade, %

Judge, %

AvgT

T1

T3

T5

T10

gpt-5.5

100.0

100.0

100.0

98.8

1.2

83.8

98.5

98.8

98.8

claude-opus-4.6

100.0

100.0

100.0

97.5

1.5

75.8

95.2

97.5

97.5

claude-opus-4.8

100.0

100.0

99.5

96.5

1.2

78.5

96.0

96.5

96.5

claude-sonnet-4.6

100.0

99.8

99.8

96.0

2.0

65.0

90.2

93.8

96.0

gpt-5.4

100.0

99.8

98.2

95.0

1.9

70.2

91.5

93.2

95.0

kimi-k2.5

100.0

100.0

98.8

93.5

2.3

64.8

84.2

89.2

93.5

claude-sonnet-4.5

100.0

100.0

99.5

93.0

2.0

69.8

90.0

91.2

93.0

gemini-3-flash

100.0

97.5

94.5

91.8

2.4

59.8

83.5

88.2

91.8

glm-5

100.0

99.5

95.8

90.8

2.4

65.4

83.2

88.2

90.8

gpt-5.2-codex

100.0

100.0

99.8

89.8

2.4

67.5

84.2

88.2

89.8

qwen3-235b

100.0

98.2

93.8

87.2

3.1

48.2

74.0

81.2

87.2

grok-4.1-fast

100.0

97.0

92.2

84.5

3.2

48.9

74.5

79.2

84.5

deepseek-v3.2

100.0

97.2

92.0

83.8

3.1

48.8

75.5

80.0

83.8

qwen3-coder-30b

100.0

86.2

76.0

68.0

4.7

39.2

57.0

61.8

68.0

qwen3-14b

100.0

83.2

67.0

62.7

5.3

25.2

51.0

56.0

62.7

gemini-2.5-flash

100.0

79.8

65.2

62.5

5.2

31.2

52.0

57.8

62.5

qwen3-8b

100.0

66.2

48.9

47.6

6.5

18.5

30.9

40.2

47.6

qwen3-4b

98.1

52.5

41.9

31.9

7.4

12.3

17.5

25.6

31.9

qwen3-1.7b

100.0

35.0

26.5

14.2

9.2

7.8

8.1

9.2

14.2

T1, T3, T5 и T10 показывают накопленную долю успешно решённых задач к соответствующей попытке. AvgT — среднее число попыток для успешных решений.

У сильных моделей основная часть улучшения происходит очень быстро.

GPT-5.5 повышает Judge Pass с 83,8% на первой попытке до 98,5% к третьей. Claude Opus 4.8 — с 78,5% до 96,0%. Claude Opus 4.6 — с 75,8% до 95,2%.

К десятой попытке лидеры достигают 96,5–98,8%.

Это означает, что большая доля ошибок не является фундаментальной. Модель в целом понимает задачу, но с первой попытки допускает локальный дефект: неверно называет параметр, неправильно индексирует линию, слишком жёстко задаёт сигнал или пропускает часть условия. Диагностическая обратная связь позволяет быстро исправить такие ошибки.

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

Где ломаются модели в single-turn

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

Результат

Доля, %

Success

48.2

Backtest fail

26.8

No trades

17.8

Reasoning loops

4.2

Judge rejected

2.7

Compilation fail

0.3

Компиляция отвечает только за 0,3% отказов. Основные потери происходят значительно позже:

  • стратегия падает во время бэктеста;

  • стратегия исполняется, но не совершает сделок;

  • стратегия торгует, но не соответствует постановке.

Отдельная категория Reasoning loops фиксирует случаи, когда модель зацикливается в процессе формирования ответа и не выдаёт пригодное финальное решение.

Какие ошибки встречаются чаще всего

Более детальная классификация выглядит так:

Тип ошибки

Доля, %

Что происходит

Сигнальные условия не активируются

17.8

Код исполняется, но входы или выходы ни разу не срабатывают

bool / ошибки объектов Line

13.1

Объекты Backtrader Line используются как обычные boolean-значения без корректной индексации

Missing attribute/method

3.9

Модель обращается к несуществующему атрибуту или методу

Wrong API params

3.9

Индикатор создаётся с неверными именами или значениями параметров

Strategy doesn’t match task

2.7

Стратегия работает и торгует, но не реализует исходную постановку

Type/NoneType errors

2.1

Операции выполняются над None или несовместимыми типами

Other runtime errors

1.4

Прочие ошибки исполнения

Syntax errors at runtime

1.2

Синтаксическая ошибка выявляется во время динамического exec()

Index out of range

1.0

Стратегия обращается к данным до накопления необходимой истории

Compilation error

0.3

Ошибка базовой структуры или синтаксической проверки

Execution timeout

0.2

Зацикливание или превышение лимита исполнения

Самая частая проблема — не сломанный Python и даже не галлюцинация метода. Это неактивная торговая логика.

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

  • RSI ниже 20;

  • цену выше длинной скользящей средней;

  • положительное пересечение MACD;

  • объём в два раза выше среднего;

  • подтверждение ещё на нескольких барах.

Каждое условие по отдельности разумно, но их пересечение может ни разу не встретиться на данных.

Вторая крупная категория связана со спецификой Backtrader — объектами Line. Это показывает, что знание общей логики Python не заменяет точного понимания модели исполнения конкретного фреймворка.

Прямые галлюцинации API встречаются реже, чем ошибки активации логики и обращения с линиями. То есть проблема современных моделей всё меньше похожа на «модель не знает название функции» и всё больше — на «модель не понимает, как код будет вести себя внутри среды».

Что остаётся после десяти попыток

В agentic-режиме совокупный успех по всем моделям достигает 81,8%. Финальные исходы распределяются так:

Результат

Доля, %

Success

81.8

Backtest fail

7.9

Judge rejected

5.6

No trades

4.7

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

Тип ошибки среди анализируемых категорий

Turn 1

Последняя попытка

Сигнальные условия не активируются

17.8%

23.7%

bool / ошибки объектов Line

13.1%

28.9%

Missing attribute/method

3.9%

3.3%

Wrong API params

3.9%

6.6%

Strategy doesn’t match task

2.7%

23.7%

Compilation fail

0.3%

6.2%

Эти проценты описывают состав оставшихся неуспешных траекторий, а не абсолютную частоту ошибок по всему бенчмарку.

По мере итеративного исправления простые дефекты исчезают, и относительная доля сложных ошибок растёт. Особенно заметны три категории:

  • неверная работа с объектами Line;

  • условия, которые так и не начинают срабатывать;

  • семантическое несоответствие исходной задаче.

Итеративная отладка хорошо исправляет локальные runtime-ошибки. Но если модель неправильно поняла торговую идею, traceback почти не помогает. Код можно сделать исполняемым, не сделав его правильным по существу.

Пять выводов из экспериментов

1. Синтаксис почти перестал быть узким местом

Для сильных моделей Compilation Rate находится около 100%. Поэтому бенчмарк, который измеряет только синтаксическую корректность, уже слабо различает современные frontier-модели.

Основная сложность сместилась на уровень наблюдаемого поведения программы.

2. Agentic-режим — не косметическое улучшение

Разница между single-turn и multi-turn достигает десятков процентных пунктов. Для практического применения это принципиально.

Модель, которая решает 70% задач с первой попытки и 95% после нескольких циклов диагностики, должна оцениваться не только как генератор кода, но и как участник интерактивного процесса разработки.

3. Сложность зависит не только от торговой идеи, но и от качества спецификации

Формально сложная стратегия с точными индикаторами, периодами и правилами может оказаться проще для модели, чем короткое разговорное описание.

Фраза «покупать сильный откат по тренду» концептуально понятна человеку, но оставляет модели множество степеней свободы. Что считать сильным откатом? Как определить тренд? Какой сигнал подтверждает окончание коррекции?

Поэтому качество постановки задачи влияет на результат не меньше, чем количество индикаторов.

4. Кодовая специализация сама по себе не гарантирует лидерства

В QuantCode-Bench универсальные модели часто превосходят специализированные кодовые системы.

Задача требует не только написания Python, но и точной интерпретации финансового намерения, работы с неполным текстовым описанием и сохранения семантики при переводе в исполняемое поведение.

Здесь сильное следование инструкции и общее языковое понимание могут оказаться важнее узкой специализации на коде.

5. Без судьи метрика легко переоценивает качество

Trade Rate всегда выше Judge Pass. Разница означает, что часть стратегий технически работает и совершает сделки, но не решает запрошенную задачу.

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

В экспериментах с RL GRPO наблюдалось именно такое поведение: если награда учитывает только исполнение и наличие сделки, модель начинает оптимизировать метрику, а не соответствие заданию. Добавление семантического судьи делает подобное взламывание вознаграждения невыгодным.

Что QuantCode-Bench не измеряет

Бенчмарк не отвечает на вопрос, можно ли использовать сгенерированную стратегию для реальной торговли.

Он не оценивает:

  • доходность;

  • Sharpe ratio;

  • просадку;

  • устойчивость к комиссиям и проскальзыванию;

  • стабильность на других периодах;

  • out-of-sample качество;

  • экономическую обоснованность сигнала.

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

Ограничения

Один фреймворк

Все решения генерируются для Backtrader. Это обеспечивает контролируемую среду, но часть результатов может отражать знание именно этого API.

Естественное продолжение работы — добавить QuantConnect/LEAN, Zipline и другие среды. Тогда можно будет отделить общую способность синтезировать торговую логику от способности адаптироваться к конкретной библиотеке.

LLM-as-a-Judge

Финальная проверка выполняется языковой моделью. Это значительно строже, чем ограничиться только компиляцией и сделками, но не гарантирует абсолютную точность.

Судья может пропустить тонкое расхождение, особенно если большая часть стратегии соответствует задаче, а ошибка находится в одном из дополнительных ограничений. Также остаются общие для LLM-as-a-Judge риски: стилистические, позиционные и модельно-специфичные смещения.

Отсутствие оценки экономического качества

QuantCode-Bench проверяет генерацию исполняемой и семантически релевантной стратегии, а не поиск торгового преимущества.

Это сознательное ограничение: оценка прибыльности потребовала бы отдельного дизайна с несколькими периодами, активами, режимами рынка, комиссиями, контролем переобучения и строгим out-of-sample протоколом.

Итог

QuantCode-Bench показывает, что генерация торговых стратегий — отдельный класс задач на пересечении программирования, финансовой логики и агентной отладки.

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

  • правильно интерпретировать естественно-языковую спецификацию;

  • использовать реальный API фреймворка;

  • учитывать семантику данных и индикаторов;

  • формулировать условия, которые действительно активируются;

  • связывать сигналы с ордерами;

  • сохранять соответствие исходной торговой идее.

В single-turn режиме лучший результат достигает 82,5% Judge Pass. Это сильный показатель, но 17,5% задач всё ещё остаются нерешёнными.

В agentic multi-turn режиме лучшие модели поднимаются до 96,5–98,8%. Следовательно, значительная часть дефектов исправима в интерактивном цикле на основе обратной связи. Для реального использования LLM при разработке стратегий способность читать диагностику и корректировать код может быть не менее важна, чем качество первой генерации.

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

Именно поэтому оценка доменно-специфичной кодогенерации не должна останавливаться на вопросе «запускается ли код». Более важный вопрос звучит так:

Реализует ли исполняемая программа именно то поведение, которое было запрошено?

Материалы

Комментарии (0)