Как запустить локальную LLM для MetaTrader 5 без Ollama?
Введение
Идея статьи: собрать воспроизводимую связку MetaTrader 5 и локальной языковой модели без Ollama. Индикаторы считаются по рыночным данным, компактная GGUF-модель получает короткий структурированный запрос, собственная программная оболочка MAX TURBO управляет llama.cpp, кэшем и контекстом, а ответ превращается в сделку с контролем риска. Отдельно покажу, что здесь действительно "модель", что просто ускорение работы и какие проверки нужны до выхода на реальный счёт.
Может ли локальная языковая модель анализировать рынок достаточно быстро, чтобы стать полноценной частью автоматической системы в MetaTrader 5? Первая мысль понятна: поднять Ollama и обращаться к нему из торгового скрипта. Для эксперимента удобно. Но между вашим кодом и вычислительным движком появляется ещё один слой со своими настройками, жизненным циклом и сюрпризами. Он перезапускается не тогда, когда нужно, держит модель в памяти не так, как вы рассчитывали, и ведёт себя по-разному на разных машинах.
Я решил заменить его слоем, который полностью контролирую. Программа на Python запускает llama-server и общается с GGUF-моделью через локальный интерфейс, совместимый с OpenAI. Она держит соединение открытым, переиспользует рассчитанный контекст и кэширует одинаковые запросы. По умолчанию стоит компактная Qwen3.5-text-0.8B в 4-битном сжатии Q4_K_M. Модель получает не график, а несколько строк с признаками и должна вернуть ровно три вещи: направление, уверенность и целевую цену через 24 часа.

Сразу о границах
Пакет не содержит универсального результата в токенах в секунду и не доказывает прибыльность на любом брокере. Скорость зависит от процессора, видеокарты и конкретной сборки llama.cpp. Торговый результат зависит от данных, издержек и правил исполнения. Пакет также не доказывает, что модель даёт торговое преимущество: он показывает проверяемую цепочку, а быстрый ответ ещё не означает полезный сигнал.
Поэтому статья не про тезис "ИИ торгует сам", а про инженерную цепочку. Каждое её звено можно проверить, заменить и улучшить отдельно. Я не буду прятать слабые места: "дообучение" без изменения весов, самооценку модели, которую ошибочно принимают за вероятность, и расхождение между закрытием сделок в тесте и в реальной торговле. Именно такие детали отличают рабочий инструмент от красивой демонстрации.
Что и как работает
Система торгует шестью парами: EURUSD, GBPUSD, USDCHF, USDCAD, AUDUSD и NZDUSD. Рабочий таймфрейм M15 (пятнадцатиминутные свечи), горизонт прогноза 96 баров, то есть 24 часа торгового времени (через выходные календарный интервал длиннее). Выход каждого этапа становится входом следующего:
MetaTrader 5, свечи M15
↓
400 последних баров
↓
ATR, RSI, MACD, объём, полосы Боллинджера,
стохастик, EMA
↓
короткий текстовый запрос
↓
оболочка MAX TURBO
↓
llama.cpp + GGUF
↓
UP / DOWN + уверенность + цена через 24 часа
↓
фильтр минимальной уверенности
↓
расчёт риска, стоп-лосса и тейк-профита
↓
сделка MetaTrader 5 Важнее всего то, чего в схеме нет. Модель не видит стакан, новости, тики и скрытые заявки. Её вход: уже рассчитанное состояние рынка, сжатое до нескольких строк. Значит, мы проверяем узкую гипотезу: способна ли компактная языковая модель полезно интерпретировать небольшой набор признаков? Вопрос "понимает ли она рынок" здесь не ставится вообще. Ещё одна оговорка: целевая цена модели в расчёте стоп-лосса и тейк-профита не участвует, сейчас это диагностика, а не часть исполнения.
Программа разбита на режимы, и каждый можно запускать и отлаживать отдельно:
| Этап | Режим | Что происходит |
|---|---|---|
| 1 | Проверка модели | Проверка GGUF, при необходимости скачивание, запуск llama-server, тестовый запрос. |
| 2 | Профиль модели | Локальный профиль и небольшой набор примеров UP/DOWN из набора данных. |
| 3 | Тест на истории | Проход по истории без заглядывания в будущее, проверка 24-часовых прогнозов. |
| 4 | Реальная торговля | Текущие данные из MetaTrader 5, вызов модели, отправка ордеров. |
| 5 | Набор данных | Примеры из реальных данных MetaTrader 5 или искусственно созданный набор. |

Что в MAX TURBO действительно "своё"
Название обманчиво. Я не писал заново матричный движок: нейросеть по-прежнему считает llama.cpp. Моё: программная оболочка вокруг него. Она запускает процесс, подбирает доступные флаги ускорения, поддерживает сетевое соединение, ведёт кэш, готовит запрос, переиспользует контекст и, если агрессивные параметры не заработали, откатывается к безопасной команде запуска.
Видно это уже по конфигурации:
MODEL_NAME = "ShtencoAiTrader-MAX-TURBO-Qwen3.5-0.8B-Q4_K_M" BASE_MODEL = "Qwen3.5-text-0.8B" TURBO_CONTEXT = 2048 TURBO_MAX_TOKENS = 96 TURBO_CACHE_ENTRIES = 4096 TURBO_PORT = 8999
Контекст 2048 токенов и лимит ответа 96 выбраны не случайно. Запрос короткий, ответ ещё короче, большой контекст только замедлял бы работу. Задача оболочки не в том, чтобы изменить математику трансформера, а в том, чтобы убрать накладные расходы вокруг каждого обращения. При этом оболочка тоже слой со своими рисками: процесс, версии, флаги, сеть. Её выигрыш не в отсутствии посредника, а в прозрачности и версионировании: весь код виден и привязан к конкретной версии пакета.
Два режима запуска llama.cpp
Сборки llama.cpp сильно различаются. Одна умеет выгружать слои на видеокарту, поддерживает ускоренный режим внимания и обработку крупными пакетами данных, другая нет. Жёстко прописанная "самая быстрая" команда на чужой машине просто не запустится. Поэтому программа сначала читает вывод llama-server --help и включает только то, что реально доступно:
if "--gpu-layers" in help_text: cmd += ["--gpu-layers", str(gpu_layers)] elif "-ngl" in help_text: cmd += ["-ngl", str(gpu_layers)] if "--batch-size" in help_text: cmd += ["-b", "2048"] if "--ubatch-size" in help_text: cmd += ["-ub", "512"] if "--flash-attn" in help_text: cmd += ["--flash-attn", "on"]
Для видеокарты по умолчанию стоит -ngl 999: движок пытается выгрузить на неё все слои, которые позволяют сборка и память. Если расширенный запуск падает, система повторяет старт с минимальным набором параметров. В итоге один и тот же архив обычно запускается без правки кода и на процессоре, и на видеокартах разных производителей. Однако результат зависит от сборки и драйверов.
При запуске раз в сутки по шести символам скорость не критична. Оптимизации важны для массового бэктеста и для перехода на частый цикл.
Почему модель такая маленькая
По умолчанию используется файл Qwen3.5-text-0.8B-Q4_K_M.gguf. GGUF: контейнер, в котором llama.cpp хранит веса вместе со служебной информацией. Суффикс Q4_K_M означает 4-битное сжатие весов: числа записаны с пониженной точностью, файл заметно меньше, вычисления быстрее. Цена: небольшая потеря качества, и для короткой структурированной задачи этот компромисс обычно приемлем. Сам файл в архив не входит: при первом запуске режим 1 скачивает его с Hugging Face.
Причина выбора практическая. Языковая модель здесь не пишет длинный анализ и не ведёт диалог. На входе короткая таблица признаков, на выходе три строки. В такой задаче задержка важнее способности к длинной генерации.
НАПРАВЛЕНИЕ: UP или DOWN УВЕРЕННОСТЬ: XX% ПРОГНОЗ ЦЕНЫ ЧЕРЕЗ 24Ч: X.XXXXX (+NN или -NN пунктов)
Системная инструкция запрещает вариант FLAT (рынок без направления) и требует согласовать направление (UP: рост, DOWN: падение), знак движения и целевую цену. Для машинного разбора это удобно, но у решения есть цена: модель вынуждена выбрать рост или падение, даже когда объективно не уверена. К чему это приводит, увидим дальше.
Что модель получает от MetaTrader 5
Перед обращением к модели считаются обычные технические признаки. Новой торговой теории в них нет, их задача: компактно описать состояние рынка.
| Признак | Как считается | Что описывает |
|---|---|---|
| Средний истинный диапазон (ATR) | Истинный диапазон, среднее за 14 баров | Текущую амплитуду движения |
| Индекс относительной силы (RSI) | 14 баров | Баланс недавних повышений и снижений |
| MACD | Скользящие средние 12 и 26, сигнальная линия 9 | Направление и силу импульса |
| Объём | Текущий тиковый объём/среднее за 20 баров | Необычность активности |
| Полосы Боллинджера | Средняя 20, отклонение ±2σ | Положение цены в локальном диапазоне |
| Стохастик | Линия K за 14 баров, линия D за 3 | Положение цены закрытия относительно недавних максимумов и минимумов |
| Скользящие средние 50 и 200 (EMA) | Экспоненциальные средние | Среднесрочную структуру тренда |
Про объём: на валютном рынке MetaTrader 5 отдаёт тиковый объём, то есть число изменений цены за бар, а не реальный оборот. Как индикатор относительной активности он годится, но принимать его за объём торгов не стоит.
Баг, который молчал. В исходной версии условие высокой волатильности сравнивало ATR с самим собой. Выражение ATR > ATR * 1.3 при положительном ATR никогда не выполняется, и ветка была мёртвой: код на месте, сработать не может. Исправленный вариант сравнивает ATR со своей средней за 20 значений:
if row["ATR"] > row["ATR_avg_20"] * 1.3: # режим повышенной волатильности
Одна строка, но такие ошибки опасны именно тишиной. Исключений нет, ошибок в логе нет, просто часть логики незаметно отсутствует.
Из чисел в короткий запрос
Модели не отдают всю таблицу данных. Формируется компактный запрос:
EURUSD 2026-09-20 10:00 Текущая цена: 1.08500 RSI: 32.5 MACD: -0.000150 ATR: 0.00085 Объёмы: 1.80x BB позиция: 0.15 Stochastic K: 25.0 Проанализируй и дай точный прогноз цены через 24 часа.
Чем короче вход, тем дешевле его обработка и тем эффективнее работает повторное использование кэша контекста. Восемь строк обрабатываются несравнимо быстрее, чем таблица из сотен чисел.
Но есть и обратная сторона. Модель видит уже отфильтрованную картину рынка. Если важного сигнала нет в этих признаках, "догадаться" о нём она не сможет.
Сетевой обмен без лишнего посредника
Оболочка обращается по адресу /v1/chat/completions, совместимому с OpenAI, который отдаёт сам llama-server. Соединение держится одной сессией requests.Session(), поэтому сетевое соединение не приходится устанавливать заново на каждый прогноз.
payload = {
"messages": messages,
"max_tokens": 96,
"temperature": 0.3,
"top_p": 0.90,
"top_k": 20,
"repeat_penalty": 1.05,
"stream": False,
"cache_prompt": True,
} Параметры выбраны ради предсказуемости. Низкая температура и ограничения на набор допустимых слов ( top_p и top_k ) сужают выбор модели, короткий лимит длины ответа ( max_tokens ) не даёт ей рассуждать. Ключевое здесь cache_prompt=True: если начало нового запроса совпадает с предыдущим, llama.cpp использует уже рассчитанный контекст вместо полного пересчёта.
Важное уточнение: cache_prompt является параметром llama.cpp, а не стандартом OpenAI, поэтому на переносимость между серверами и версиями рассчитывать нельзя. К тому же общий префикс (системная инструкция и формат ответа) короткий, а дальше идут изменяемые данные, так что выигрыш скромный.
Второй кэш: одинаковый запрос в модель не идёт
Помимо кэша внутри llama.cpp, у программы есть собственный кэш, который при переполнении выбрасывает самые давно не использованные записи. Для каждого запроса строится короткий хэш-отпечаток. В исходной версии ключ кэша включал только messages, temperature и max_tokens. Это ошибка: при смене top_p, top_k, repeat_penalty, версии модели или профиля кэш мог вернуть ответ, полученный при других условиях. Теперь ключ строится по всему набору параметров генерации плюс MODEL_NAME и флаг примеров-образцов ( use_fewshot ). Если такой запрос уже был, готовый текст возвращается из памяти.
cache_material = json.dumps(
[messages, temperature, max_tokens,
top_p, top_k, repeat_penalty,
MODEL_NAME, use_fewshot],
ensure_ascii=False,
sort_keys=True,
)
key = hashlib.blake2s(
cache_material.encode("utf-8"),
digest_size=16,
).hexdigest() По умолчанию хранится до 4096 записей. В живой торговле абсолютно одинаковые рыночные запросы повторяются редко. Зато при отладке, тестах интерфейса и повторных вызовах такой кэш почти полностью убирает время генерации.
Выходит двухуровневая защита от лишних вычислений: сначала кэш программы, и только при промахе запрос уходит в llama-server, где может сработать повторное использование контекста.
Как текст превращается в сигнал
Модель отвечает свободным текстом, поэтому ответ нужно разбирать. Здесь работают регулярные выражения:
prob = re.search(
r"(?:УВЕРЕННОСТЬ|ВЕРОЯТНОСТЬ)[\s:*]*(\d+)",
text,
re.I,
)
direction = re.search(
r"НАПРАВЛЕНИЕ[\s:*]*(UP|DOWN)\b",
text,
re.I,
)
prices = re.findall(r"\b\d+[.,]\d{4,5}\b", text) Ответ считается разобранным, только когда найдены все три поля. В исходной версии при отсутствии уверенности подставлялось 50%, а при отсутствии направления DOWN: сбой разбора способен был превратиться в конкретную сделку. Теперь такой ответ пропускается. Направление читается только из строки "НАПРАВЛЕНИЕ:", запятая допускается как десятичный разделитель, а целевая цена должна согласоваться с направлением. Формат ответа здесь не косметика, а часть торговой логики.
И важное уточнение. "Уверенность 82%": это самооценка языковой модели, а не откалиброванная вероятность выигрыша. Модель может уверенно ошибаться, а механизма, сопоставляющего её проценты с реальной частотой успешных сделок, в системе нет. Порог 70% нужно воспринимать как фильтр текста, а не как математическое утверждение о вероятности.
Набор данных на реальной истории MetaTrader 5
Для каждого из шести инструментов загружается примерно полгода данных M15. Текущий бар становится входом, бар через 96 шагов становится ответом. Метка соответствует движению примерно через 24 часа торгового времени, через выходные календарный интервал длиннее.
future_idx = idx + PREDICTION_HORIZON future_row = df.iloc[future_idx] price_change = future_row["close"] - row["close"] if price_change > 0: direction = "UP" elif price_change < 0: direction = "DOWN" else: continue
Нулевое изменение цены метку не получает: такой пример пропускается, иначе он молча превратился бы в DOWN.
Примеры делятся на рост и падение, и система старается взять поровну обоих. Если дисбаланс всё равно велик, примеры редкого направления дублируются. Это выравнивание частоты классов в примерах: набор, где одно направление встречается заметно чаще, легко научит просто повторять более частый ответ. Но дублирование не создаёт новых рыночных ситуаций, а веса здесь не обучаются.
Режим 2: это не дообучение
Функция называется mode_finetune(), и название создаёт ложное впечатление, будто система дообучает Qwen и записывает новые веса. Этого не происходит.
Режим читает файл с примерами, берёт не более двух примеров роста и двух примеров падения и записывает их в файл профиля:
up = [x for x in training_data if x.get("direction") == "UP"][:2] down = [x for x in training_data if x.get("direction") == "DOWN"][:2] examples = up + down
Более того, даже эти четыре примера по умолчанию в запрос не попадают. Они включаются только переменной окружения:
SHTENCO_TURBO_FEWSHOT=1 Корректнее говорить не об "обученной модели", а о локальном профиле базовой GGUF-модели. Так честнее, и для воспроизводимости это важно: читатель понимает, что именно он запускает и что сравнивает.
Как устроен исторический тест
Тест берёт последние 30 дней. Для каждой точки анализа используется только история до текущего индекса, будущие бары в признаки не попадают. Это относится именно к признакам: примеры-образцы профиля могут пересекаться с тестовым периодом, поэтому полную независимость теста это не гарантирует:
historical_data = data[sym].iloc[:current_idx + 1].copy() df_with_features = calculate_features(historical_data) row = df_with_features.iloc[-1]
Следующая точка сдвигается на 96 баров M15, поэтому прогнозные окна не перекрываются. При таком шаге 30 дней дают порядка 20 прогнозов на символ и около 120 на все шесть. Для оценки устойчивости на FX этого мало.
Если MAX TURBO недоступен, тест не останавливается, а переходит на простую резервную логику на основе RSI и MACD. Для отладки остального кода это удобно, но результаты такого запуска нельзя называть тестом языковой модели. В любом отчёте нужно фиксировать, был ли use_ai=True.
Размер позиции и риск
Стартовый баланс в тесте равен 10 000 долларов, риск на сделку составляет 0.5% текущего баланса. Дистанция стопа зависит от ATR:
risk_amount = balance * 0.005 atr_points = ATR / point stop_distance = max(20, atr_points * 2) lot_size = risk_amount / (stop_distance * point_value + COMMISSION_PER_LOT)
В тесте объём ограничен диапазоном от 0.01 до 10 лотов. В реальной торговле используются настоящие ограничения символа: минимальный и максимальный объём и шаг объёма ( volume_min, volume_max и volume_step ).
В исходной версии стоимость пункта считалась как point * contract_size. Это верно только для пар, где USD стоит в котируемой валюте: EURUSD, GBPUSD, AUDUSD и NZDUSD. Для USDCHF и USDCAD результат получался в CHF и CAD. Теперь point_value берётся из trade_tick_value и trade_tick_size, то есть сразу в валюте счёта, а комиссия задаётся константой COMMISSION_PER_LOT (по умолчанию 0: впишите значение своего брокера). Лот округляется вниз до шага объёма, и если даже минимальный лот превышает 0.5%, сделка пропускается.
Теперь о терминологии. В исходной версии некоторые переменные были названы *_pips, хотя расчёты идут через symbol_info.point. Я переименовал их в *_points. У пятизнакового EURUSD один пункт равен 0.00001, а классический пипс равен 0.00010. Разница в десять раз в денежных расчётах обходится дорого, поэтому пункты и пипсы в именах лучше развести строго.
Спред, проскальзывание, своп
В тесте заданы постоянные приближённые издержки:
SPREAD_POINTS = 2 SWAP_LONG = -0.5 SWAP_SHORT = -0.3 SLIPPAGE = 10
Ещё одна исправленная ошибка: знак свопа. Классика: отрицательное значение сначала называют "стоимостью", потом вычитают, и минус на минус превращается в прибыль. Теперь своп добавляется к результату с правильным знаком:
swap_cost = SWAP_LONG if direction == "UP" else SWAP_SHORT swap_cost = swap_cost * (lot_size / 0.01) profit_usd += swap_cost
Отрицательная стоимость свопа действительно уменьшает итог. Но тест всё равно остаётся упрощённым. Значение SPREAD_POINTS = 2 (раньше переменная называлась SPREAD_PIPS ) умножается на point, то есть для пятизнакового символа это 2 пункта, примерно 0.2 пипса. Так же и SLIPPAGE = 10: это 10 пунктов, то есть 1 пипс на пятизнаке. Реальный плавающий спред из MT5 здесь не используется.
Главная проблема: тест и реальная торговля закрывают сделки по-разному
Это самая важная граница текущей версии. В реальной торговле после сигнала считаются стоп-лосс и тейк-профит:
sl = price - stop_distance * point tp = price + stop_distance * 3 * point # для SELL знаки меняются зеркально
Тест же не проверяет, что было достигнуто раньше внутри суток: стоп-лосс или тейк-профит. Он просто берёт цену закрытия через 96 баров и закрывает сделку там. Дистанция стопа влияет на размер позиции, но не на траекторию выхода.
Поэтому результат теста нельзя напрямую сравнивать с реальной торговлей: это две разные стратегии выхода под одним названием. Для строгой проверки нужно пройти по максимумам и минимумам всех 96 будущих баров и определить, что случилось первым: стоп-лосс, тейк-профит или выход по времени. Такая деталь часто важнее, чем замена одной языковой модели на другую.
Реальная торговля
После явного подтверждения YES программа раз в 24 часа обходит шесть символов. Если по символу уже есть позиция с нужным магическим числом (идентификатором ордеров этой программы), новый вход пропускается. Для сигнала берётся текущая цена покупки при покупке и цена продажи при продаже, затем отправляется рыночная заявка:
request = {
"action": mt5.TRADE_ACTION_DEAL,
"symbol": sym,
"volume": lot_size,
"type": order_type,
"price": price,
"sl": sl,
"tp": tp,
"deviation": SLIPPAGE,
"magic": MAGIC,
"comment": f"AI_{prob}%",
} Позиции дополнительно закрываются по времени, если прошло 24 часа. Итого три выхода: стоп-лосс, тейк-профит или принудительное закрытие.
Есть тонкость с данными. Вызов copy_rates_from_pos(..., 0, LOOKBACK) может захватить ещё формирующийся пятнадцатиминутный бар. В строгой версии сигнал нужно строить только по полностью закрытому бару, иначе признаки продолжат меняться после того, как решение принято. Решение простое: copy_rates_from_pos(..., 1, LOOKBACK) пропускает формирующийся бар.
Три исправления, уже вошедшие в пакет| Проблема | Исправление | Почему важно |
|---|---|---|
| Мёртвое условие ATR | ATR сравнивается со своей средней за 20 значений, умноженной на 1.3 | Ветка высокой волатильности теперь может сработать. |
| Знак отрицательного свопа | Отрицательный своп добавляется к прибыли или убытку | Он уменьшает прибыль, а не увеличивает её. |
| Размер пункта в искусственных данных | Для пятизнакового символа используется 0.00001 | Нет десятикратной ошибки масштаба. |
Что нужно проверить до реальных денег
Прежде чем сравнивать модели или говорить о преимуществе, нужен единый протокол:
- Одинаковые правила входа и выхода в тесте и в реальной торговле.
- Реальный исторический спред каждого символа вместо константы.
- Проход по максимумам и минимумам внутри 24-часового окна с честным определением, что сработало первым: стоп-лосс или тейк-профит.
- Только закрытые пятнадцатиминутные бары.
- Фиксация версии GGUF, номера сборки llama.cpp, параметров генерации, начального числа генератора, железа и брокера.
- Детерминированный режим или фиксированное начальное число генератора случайности: при temperature=0.3 повторный запуск может дать другой ответ.
- Отдельный учёт точности направления, ошибки целевой цены, прибыли или убытка после издержек, профит-фактора, максимальной просадки, распределения сделок и доверительных интервалов.
- Сравнение с простыми базами: случайный выбор направления, последняя цена, моментум, RSI и MACD без языковой модели, простая модель машинного обучения.
- Период примеров-образцов не пересекается с тестовым.
- Никакого смешивания результатов MAX TURBO и резервной логики на RSI и MACD.
Только после этого можно честно сравнивать Qwen3.5-text-0.8B с более крупной GGUF-моделью, профилем с примерами-образцами и обычной алгоритмической базой.
Ограничения
- GGUF-модели в архиве нет (не влезет в архив), она скачивается при первом запуске.
- MAX TURBO: собственная программная оболочка, но нейросеть считает llama.cpp.
- Оболочка тоже слой со своими рисками: процесс, версии, флаги, сеть.
- Режим 2 не меняет веса и не является дообучением.
- Процент уверенности: самооценка модели, а не калиброванная вероятность.
- Запрет варианта FLAT заставляет модель всегда выбирать направление: нечитаемый ответ пропускается, но осознанно отказаться от сделки модель не может. Следующий шаг: добавить явный вариант "нет сделки".
- Тест использует постоянный спред и не моделирует порядок срабатывания стоп-лосса и тейк-профита.
- Комиссии не учтены, проскальзывание задано константой.
- Тест на 30 днях слишком короткий для оценки устойчивости на FX.
- Тест может молча перейти на резервную логику на RSI и MACD, если llama.cpp недоступен.
- Примеры-образцы при неверном построении профиля могут пересекаться по времени с тестовым периодом; для проверки на независимых данных это нужно исключить.
- В версии до правки ключ кэша не включал все параметры генерации: результаты ранних запусков с кэшем могли смешивать условия.
- При temperature=0.3 ответы недетерминированы.
- Нет доказательства, что модель 0.8B превосходит простые базы.
- Универсально подтверждённой скорости в пакете нет: она зависит от железа и сборки llama.cpp.
- Исторический результат не гарантирует будущую прибыль.
Эти ограничения не обесценивают архитектуру. Они показывают, какие части уже воспроизводимы, а какие ждут строгого торгового эксперимента.
Что в итоге
Результат этой версии: не "ИИ, который знает будущую цену", а автономная локальная цепочка. Она поднимает компактную GGUF-модель без Ollama, готовит признаки, получает короткий прогноз, разбирает его, отсекает слабые ответы и связывает решение с MetaTrader 5.
Архитектура при этом модульна. Qwen можно заменить другой GGUF-моделью, набор признаков изменить, рядом с языковой моделью поставить детерминированный классификатор или оставить MAX TURBO интерпретатором уже готового количественного сигнала.

Приложенные файлы
К статье приложен пакет SHTENCO_AI_TRADER_MAX_TURBO_PACKAGE.zip. GGUF-веса в архив не входят: режим 1 загружает их отдельно. Файлов EX5 и MQ5 нет, поскольку связка работает через официальный модуль MetaTrader 5 для Python.
| Файл | Назначение | Зависимости |
|---|---|---|
| ai_trader_ultra_MAX_TURBO.py | Основная программа: оболочка для llama.cpp, признаки, набор данных, тест на истории, реальная торговля. | Python, requests, pandas, numpy, matplotlib, MetaTrader5. |
| INSTALL_WINDOWS.bat | Установка библиотек Python и попытка поставить llama.cpp через winget. | Windows, Python, менеджер пакетов winget. |
| RUN_TRADER.bat | Запуск основной программы из каталога пакета. | Python. |
| requirements.txt | Список библиотек. | pip. |
| models/shtenco_max_turbo_profile.json | Профиль модели и необязательные примеры-образцы. | Читается основной программой. |
| models/README_MODEL.txt | Путь к модели, репозиторий GGUF, переменные окружения. | Нет. |
| README_MAX_TURBO.txt | Краткая инструкция и отличия от версии с Ollama. | Нет. |
Синтаксис основного файла проверен командой python -m py_compile. Для реального запуска торгового режима нужны Windows, установленный MetaTrader 5, llama-server и GGUF-модель. Сначала запустите установочный файл: он поставит зависимости. Затем запустите основное приложение.
Запуск с нуля: от архива до первого ответа модели
Проверка py_compile говорит лишь о том, что Python может прочитать файл. Чтобы система заработала, нужны ещё несколько внешних компонентов. Ниже порядок, который я рекомендую: каждый шаг проверяется отдельно, и к следующему можно переходить, только когда предыдущий работает.
Что понадобится- Windows;
- Python (команда python --version или py --version должна показать версию);
- MetaTrader 5 вашего брокера, лучше с демо-счётом;
- пакет SHTENCO_AI_TRADER_MAX_TURBO_PACKAGE.zip;
- llama-server из проекта llama.cpp;
- GGUF-модель (по умолчанию Qwen3.5-text-0.8B-Q4_K_M, режим 1 скачает её сам).
Создайте папку, например C:\SHTENCO_AI_TRADER\, и распакуйте туда архив целиком. Запускать файлы из-под архива нельзя. В папке должны быть ai_trader_ultra_MAX_TURBO.py, INSTALL_WINDOWS.bat, RUN_TRADER.bat, requirements.txt и каталог models.
Шаг 2. MetaTrader 5Установите терминал, войдите в счёт и убедитесь, что котировки идут. Python получает данные и отправляет ордера через терминал, поэтому MetaTrader 5 должен быть запущен и авторизован всё время работы.
Откройте "Обзор рынка" и проверьте, что есть EURUSD, GBPUSD, USDCHF, USDCAD, AUDUSD и NZDUSD. Если у брокера символы с суффиксами (EURUSD.a, EURUSDm, EURUSD.pro), имена в коде придётся поправить.
Шаг 3. Установка зависимостейЗапустите INSTALL_WINDOWS.bat двойным щелчком и не закрывайте окно до конца. Скрипт поставит библиотеки из requirements.txt (requests, pandas, numpy, matplotlib, MetaTrader 5) и попробует поставить llama.cpp через winget.
Если позже увидите сообщение "No module named..." (модуль не найден), выполните в папке проекта:
python -m pip install -r requirements.txt
Шаг 4. Проверка llama-server
Откройте командную строку и выполните:
llama-server --help
Появилась справка: всё в порядке. Сообщение "is not recognized" (команда не распознана) означает, что winget не справился или программа не найдена по пути поиска (переменная PATH). Тогда скачайте подходящую сборку llama.cpp для Windows (для процессора, видеокарты NVIDIA или универсальную) и добавьте папку с llama-server.exe в переменную PATH.
Видеокарта не обязательна: модель на 0.8 миллиарда параметров работает и на процессоре, просто медленнее. Нужные флаги ускорения оболочка MAX TURBO подберёт сама по выводу --help.
Шаг 5. Запуск и проверка модели
Запускайте программу через RUN_TRADER.bat. Если окно закрывается мгновенно, откройте папку проекта, впишите cmd в адресную строку Проводника и выполните RUN_TRADER.bat оттуда: текст ошибки останется на экране.
Режимы выбираются по номеру:
| № | Режим | Когда запускать |
|---|---|---|
| 1 | Проверка модели | Первым. Проверяет GGUF, скачивает её при необходимости, поднимает llama-server и шлёт тестовый запрос. |
| 2 | Профиль модели | По желанию. Это профиль с примерами-образцами, веса не меняются. |
| 3 | Тест на истории | После успешного режима 1. |
| 4 | Реальная торговля | Только на демо-счёте и только после теста на истории. Требует ввода YES. |
| 5 | Набор данных | Не обязателен для первого запуска. |
Режим 1 считается пройденным, если модель загрузилась и вернула ответ в формате "направление, уверенность, цена". Если он не работает, дальше идти нет смысла.
Вручную запускать llama-server не нужно: MAX TURBO сам поднимает процесс, держит соединение и при сбое откатывается к безопасным параметрам.
Шаг 6. Тест на истории и демо-счётВ режиме 3 убедитесь, что история грузится, признаки считаются, а модель реально отвечает. Если MAX TURBO недоступен, тест молча переключается на резервную логику на основе RSI и MACD, и такой результат нельзя считать тестом языковой модели. Проверьте в выводе, что работала именно нейросеть.
Затем запускайте реальную торговлю на демо-счёте. Помните: тест закрывает сделки по цене закрытия через 96 баров, а реальная торговля использует стоп-лосс, тейк-профит и закрытие по времени. Результаты теста нельзя напрямую переносить на реальную торговлю.
Если что-то не работает
| Симптом | Причина | Что делать |
|---|---|---|
| Python не найден | Не установлен или не прописан в переменной PATH | Установить Python, перезапустить консоль, повторить INSTALL_WINDOWS.bat |
| "No module named..." (модуль не найден) | Библиотеки установлены не полностью | python -m pip install -r requirements.txt |
| Нет подключения к MT5 | Терминал закрыт, нет входа в счёт или нет символа | Запустить MT5, авторизоваться, проверить "Обзор рынка" и имена символов |
| "llama-server not found" (программа не найдена) | Файл не найден системой | Проверить llama-server --help, поставить сборку, добавить в PATH |
| Модель не загружается | Нет файла.gguf, неверный путь, повреждён файл, не хватает памяти или сборка llama.cpp не поддерживает модель | Сверить пути в models\README_MODEL.txt, перекачать файл, обновить сборку |
1. Распаковать архив 2. Запустить MetaTrader 5, войти в демо-счёт 3. INSTALL_WINDOWS.bat 4. llama-server --help 5. RUN_TRADER.bat → режим 1 (проверка модели) 6. Режим 3 (тест на истории) 7. Режим 4 (реальная торговля), сначала только демо
Правило одно: установка → модель → MT5 → тест на истории → демо → реальный счёт. Пока предыдущий этап нестабилен, к следующему не переходим. Так сразу видно, где ломается цепочка: в Python, MetaTrader 5, llama-server, GGUF или торговой логике.
Реальная торговля отправляет настоящие ордера. Прошлая прибыль не гарантирует будущую.
Заключение
Можно ли убрать Ollama и оставить локальную языковую модель частью торговой системы MetaTrader 5? Да, если разделить задачу на понятные слои.
MetaTrader 5 остаётся источником котировок и исполнителем. Python считает признаки и ведёт торговую логику. MAX TURBO отвечает за жизненный цикл модели: запускает llama.cpp, подбирает флаги ускорения, переиспользует контекст и кэширует одинаковые запросы. GGUF-модель превращает компактное состояние рынка в направление, уверенность и цель на сутки.
MT5 ↓ технические признаки ↓ короткий запрос ↓ оболочка MAX TURBO ↓ llama.cpp / GGUF ↓ UP / DOWN / уверенность / цель ↓ фильтр + риск ↓ ордер в MT5
Но самое важное скрыто не в названии модели и не в скорости в токенах в секунду. Настоящая проверка начинается там, где тест и реальная торговля получают одинаковые правила исполнения, реальные издержки, закрытые бары и независимый период данных. Только тогда удастся отделить ускорение инфраструктуры от торгового преимущества. Без этого разговор о преимуществе остаётся разговором об удачной демонстрации. Пока статья лишь разделяет ускорение инфраструктуры и торговое преимущество, и второе здесь не доказано.
Литература и документация
- llama.cpp. Локальный запуск моделей в формате GGUF.
- MetaTrader 5 Python Integration. Документация по Python-интерфейсу терминала.
- Hugging Face Hub. Загрузка и управление файлами моделей.
- Qwen3.5-text-0.8B-GGUF. Репозиторий GGUF, указанный в пакете как модель по умолчанию.
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.