Интеграция AI-модели в существующую торговую стратегию на MQL5
Введение
В этой статье мы рассмотрим интеграцию AI-модели в уже существующую торговую стратегию MQL5, используя Order Block в с уровнями Фибоначчи из предыдущей статьи. Многие существующие стратегии на MQL5 используют в основе набор индикаторов, заданные пороговые значения или предопределенные шаблоны. Эффективность таких решений может быть разной в разных рыночных циклах. Эти стратегии не умеют обучаться на исторических данных, распознавать сложные закономерности или динамически корректироваться в зависимости от меняющихся условий.
Добавление AI-модели в торговую стратегию может помочь преодолеть эти ограничения, добавляя возможности адаптации и принятия решений на основе машинного обучения. С помощью методов, таких как Long Short-Term Memory (LSTM) или предиктивная аналитика, AI способен анализировать большие объемы исторических и реальных данных, чтобы принимать более точные торговые решения. В отличие от жестких предопределенных стратегий, системы с AI динамически адаптируются и улучшают свои подходы, обучаясь на изменяющихся рыночных условиях. Это может давать более точное время входа и выхода, эффективное управление рисками и рост прибыльности с течением времени.
Начало работы
Для начала нам нужно преобразовать существующий код MQL5 в Python. Поскольку мы интегрируем модели в торговую стратегию, нам обязательно нужно наличие версии оригинальной логики на Python. Это позволит внедрить AI-улучшения без нарушения основной функциональности стратегии. Python-версия должна точно повторять поведение скрипта MQL5, включая логику исполнения сделок, расчет индикаторов, управление ордерами и правила управления рисками. AI-модель в этом случае будет взаимодействовать с системой, идентичной той, что работает в MetaTrader 5, что позволяет проводить точное тестирование и оптимизацию перед полной интеграцией. После выполнения этого шага можно приступать к внедрению моделей машинного обучения, обучению AI на рыночных данных и созданию интеллектуальной адаптивной торговой системы.
MQL5 code:
#include <Trade/Trade.mqh> #include <Arrays\ArrayObj.mqh> CTrade trade; #define BullOB clrLime #define BearOB clrRed //+------------------------------------------------------------------+ //| Global vars | //+------------------------------------------------------------------+ double Lots = 0.01; int takeProfit = 170; int length = 100; input double stopLoss = 350; input double Mgtn = 0.85; bool isBullishOB = false; bool isBearishOB = false; input int Time1Hstrt = 3; input int Time1Hend = 4; class COrderBlock : public CObject { public: int direction; datetime time; double high; double low; bool traded; string rectName; string tradeRectName; COrderBlock(int dir, datetime t, double h, double l) { direction = dir; time = t; high = h; low = l; traded = false; rectName = ""; tradeRectName = ""; } void draw(datetime tmS, datetime tmE, color clr) { rectName = "OB REC" + TimeToString(time); ObjectCreate(0, rectName, OBJ_RECTANGLE, 0, time, low, tmS, high); ObjectSetInteger(0, rectName, OBJPROP_FILL, true); ObjectSetInteger(0, rectName, OBJPROP_COLOR, clr); tradeRectName = "OB trade" + TimeToString(time); ObjectCreate(0, tradeRectName, OBJ_RECTANGLE, 0, tmS, high, tmE, low); ObjectSetInteger(0, tradeRectName, OBJPROP_FILL, true); ObjectSetInteger(0, tradeRectName, OBJPROP_COLOR, clr); } void removeDrawings() { if (ObjectFind(0, rectName) != -1) { ObjectDelete(0, rectName); // Delete the main rectangle } if (ObjectFind(0, tradeRectName) != -1) { ObjectDelete(0, tradeRectName); // Delete the trade rectangle } } }; // Pointer to CArrayObj // Declare the dynamic array to hold order blocks CArrayObj *orderBlocks; color OBClr; datetime T1; datetime T2; int OnInit() { orderBlocks = new CArrayObj(); // Allocate memory for the array return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { ObjectsDeleteAll(0, "OB"); // Clear and free the order blocks if (orderBlocks != NULL) { orderBlocks.Clear(); // This will delete objects inside delete orderBlocks; // Free the array memory orderBlocks = NULL; } } void OnTick() { if (isNewBar()) { static int prevDay = 0; MqlDateTime structTime; TimeCurrent(structTime); structTime.min = 0; structTime.sec = 0; structTime.hour = Time1Hstrt; datetime timestrt = StructToTime(structTime); structTime.hour = Time1Hend; datetime timend = StructToTime(structTime); getOrderB(); double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); for (int i = orderBlocks.Total() - 1; i >= 0; i--) { COrderBlock *OB = (COrderBlock *)orderBlocks.At(i); if (CheckPointer(OB) != POINTER_INVALID && !OB.traded) { if(OB.direction > 0 && Ask < OB.high){ double entry = Ask; double tp = getHigh(iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, iBarShift(_Symbol, PERIOD_CURRENT, OB.time))); double sl = NormalizeDouble(OB.low - Mgtn, _Digits); T2 = getTime(0); OB.draw(T1, T2, BullOB); trade.Buy(Lots, _Symbol, entry, sl, tp, "OB buy"); OB.traded = true; //OB.removeDrawings(); orderBlocks.Delete(i); // Delete from array delete OB; // Free memory } } if(CheckPointer(OB) != POINTER_INVALID && !OB.traded){ if (OB.direction < 0 && Bid > OB.low) { double entry = Bid; double tp = getLow(iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, iBarShift(_Symbol, PERIOD_CURRENT, OB.time))); double sl = NormalizeDouble(OB.high + Mgtn, _Digits); T2 = getTime(0); OB.draw(T1, T2, BearOB); trade.Sell(Lots, _Symbol, entry, sl, tp, "OB sell"); OB.traded = true; //OB.removeDrawings(); orderBlocks.Delete(i); // Delete from array delete OB; // Free memory } } } } } void getOrderB(){ static int prevDay = 0; MqlDateTime structTime; TimeCurrent(structTime); structTime.min = 0; structTime.sec = 0; structTime.hour = Time1Hstrt; datetime timestrt = StructToTime(structTime); structTime.hour = Time1Hend; datetime timend = StructToTime(structTime); int visibleBars = (int)ChartGetInteger(0,CHART_VISIBLE_BARS); for(int i = 1; i <= visibleBars; i++){ if(getOpen(i) < getClose(i)){ // index is i since the loop starts from i which is = 1 "for(int i = 1)..." if(getOpen(i + 2) < getClose(i + 2)){ if(getOpen(i + 3) > getClose(i + 3) && getOpen(i + 3) < getClose(i + 2)){ Print("Bullish Order Block confirmed at: ", TimeToString(getTime(i + 2), TIME_DATE||TIME_MINUTES)); //isBullishOB = true; //OB = new COrderBlock(); int direction = 1; datetime time = getTime(i + 3); double high = getHigh(i + 3); double low = getLow(i + 3); isBullishOB = true; OBClr = isBullishOB ? BullOB : BearOB; // specify strt time T1 = time; // reset BULLOB flag isBullishOB = false; // crucial COrderBlock *newOB = new COrderBlock(direction, time, high, low); orderBlocks.Add(newOB); break; //delete newOB; } } } if(getOpen(i) > getClose(i)){ if(getOpen(i + 2) > getClose(i + 2)){ if(getOpen(i + 3) < getClose(i + 3) && getOpen(i + 3) < getClose(i + 2)){ Print("Bearish Order Block confirmed at: ", TimeToString(getTime(i + 2), TIME_DATE||TIME_MINUTES)); //isBearishOB = true; //OB = new COrderBlock(); int direction = -1; datetime time = getTime(i + 3); double high = getHigh(i + 3); double low = getLow(i + 3); isBearishOB = true; OBClr = isBearishOB ? BearOB : BullOB; T1 = time; // reset the BEAROB flag isBearishOB = false; // crusssial COrderBlock *newOB = new COrderBlock(direction, time, high, low); orderBlocks.Add(newOB); break; //delete newOB; } } } } } double getHigh(int index) { return iHigh(_Symbol, _Period, index); } double getLow(int index) { return iLow(_Symbol, _Period, index); } double getOpen(int index){ return iOpen(_Symbol, _Period, index); } double getClose(int index){ return iClose(_Symbol, _Period, index); } datetime getTime(int index) { return iTime(_Symbol, _Period, index); } bool isNewBar() { // Memorize the time of opening of the last bar in the static variable static datetime last_time = 0; // Get current time datetime lastbar_time = (datetime)SeriesInfoInteger(Symbol(), Period(), SERIES_LASTBAR_DATE); // First call if (last_time == 0) { last_time = lastbar_time; return false; } // If the time differs (new bar) if (last_time != lastbar_time) { last_time = lastbar_time; return true; } // If no new bar, return false return false; } void deler(){ static int prevDay = 0; MqlDateTime structTime; TimeCurrent(structTime); structTime.min = 0; structTime.sec = 0; structTime.hour = Time1Hstrt; datetime timestrt = StructToTime(structTime); structTime.hour = Time1Hend; datetime timend = StructToTime(structTime); }
Функциональность и структуру этого кода мы обсуждали в прошлой статье. Стратегия выявляет блоки ордеров (order blocks) — специфические свечные паттерны, которые, как считается, сигнализируют о возможных разворотах рынка. Эту стратегию мы реализовали в виде полноценного советника, который сочетает анализ ценового действия с автоматическим исполнением сделок. Объектно-ориентированное программирование реализовано через класс COrderBlock, который хранит данные о паттернах (временные метки, границы цен, направление) и управляет визуализацией на графике. Динамический массив CArrayObj отслеживает активные блоки ордеров, управляет памятью и определяет паттерны в реальном времени на нескольких графиках.
Функция getOrderB() отвечает за распознавание паттернов. Она сканирует исторические свечи в поиске конкретных бычьих и медвежьих последовательностей. Когда три подряд идущие бычьи свечи следуют за медвежьей, это считается бычьим блоком. И наоборот, медвежий блок это три медвежьи свечи, идущие за бычьей. Найденный паттерны создаются как объекты COrderBlock с флагами направления (1 для бычьего, -1 для медвежьего) и сохраняются в массиве. В коде есть настраиваемые временные фильтры (Time1Hstrt, Time1Hend), которые позволяют пользователю выбрать нужные торговые сессии. Ожидается, что это повышает релевантность паттернов.
На каждой новой свече (определяется через isNewBar()) советник обрабатывает активные блоки ордеров в функции OnTick(). Если найден бычий паттерн, советник открывает длинную позицию при пробое цены выше максимума блока и ставит стоп-лоссы ниже минимума паттерна с учетом маржи (Mtgn). Медвежьи сделки совершаются активируются при пробое минимума блока, со стопами выше максимума паттерна. Советник использует CTrade для управления ордерами и рассчитывает уровни тейк-профита на основе последних локальных максимумов/минимумов. Исполненные сделки автоматически удаляют связанные блоки ордеров и графические отметки, чтобы избежать дублирования сигналов.
В системы есть настройки для защиты торговли: расстояния стоп-лоссов настраиваются под требования брокера, размер позиции фиксирован на уровне Lots, а на графике для наглядности показываются визуальные цветные прямоугольники. Для настройки доступны все нужные параметры - стоп-лосс (StopLoss), маржа прибыли (Mtgn) и время торговой сессии. То есть в коде есть и полностью алгоритмическое распознавание паттернов алгоритмическое, и настраиваемые элементы для учета брокерских ограничений, такие как минимальные расстояния стопов и спред.
Версия Python:
Прежде чем начать, как всегда, нам нужен набор исторических рыночных данных. Эти данные нужны для обучения AI-модели и проверки точности стратегии. Надеюсь, что к данному моменту вам знаком процесс получения исторических данных. Если нет, рекомендую обратиться к первой части моего руководства по интеграции MQL5 с пакетами обработки данных. Итак, мы загружаем исторические данные.
import pandas as pd # Load historical data file_path = '/home/int_junkie/Documents/DataVisuals/AI inside MQL5/XAUUSD_H1.csv' data = pd.read_csv(file_path) # Display the first few rows and column names print(data.head()) print(data.columns)
Этот Python-код отвечает за обработку исторических рыночных данных, которые будут использоваться для обучения AI-модели. Первый шаг — создать конвейер данных для загрузки, предобработки и организации исторических ценовых данных, включая ключевые характеристики: открытие, максимум, минимум, закрытие, объем и используемые технические индикаторы. Такая структура поможет модели выявлять значимые закономерности в поведении рынка.
Также добавляем функциональность для обучения LSTM-модели (Long Short-Term Memory). Это специализированная рекуррентная нейронная сеть (RNN), способная анализировать последовательные данные и учитывать долгосрочные зависимости. Процесс обучения синхронизируется с логикой покупки и продажи исходной стратегии MQL5, чтобы модель училась принимать торговые решения на основе исторических цен. Модель LSTM сопоставляет прошлые данные с соответствующими сигналами buy/sell и постепенно улучшает свои предсказательные возможности, чтобы точнее прогнозировать потенциальные движения рынка. Этот подход объединяет традиционную стратегию и AI, повышая адаптивность и точность системы.
import pandas as pd import numpy as np from datetime import datetime from keras.models import Sequential from keras.layers import LSTM, Dense import tensorflow as tf # Constants LOTS = 0.01 TAKE_PROFIT = 170 STOP_LOSS = 350 MGTN = 0.85 TIME1_HSTRT = 3 TIME1_HEND = 4 # Helper functions def get_high(data, index): return data.iloc[index]['<HIGH>'] def get_low(data, index): return data.iloc[index]['<LOW>'] def get_open(data, index): return data.iloc[index]['<OPEN>'] def get_close(data, index): return data.iloc[index]['<CLOSE>'] def get_time(data, index): return data.iloc[index]['DATETIME'] # Combined datetime column def is_new_bar(current_time, last_time): return current_time != last_time class OrderBlock: def __init__(self, direction, time, high, low): self.direction = direction self.time = time self.high = high self.low = low self.traded = False def get_order_blocks(data): order_blocks = [] visible_bars = len(data) for i in range(1, visible_bars - 3): # Adjusted to avoid index errors if get_open(data, i) < get_close(data, i): # Bullish condition if get_open(data, i + 2) < get_close(data, i + 2): if get_open(data, i + 3) > get_close(data, i + 3) and get_open(data, i + 3) < get_close(data, i + 2): print(f"Bullish Order Block confirmed at: {get_time(data, i + 2)}") direction = 1 time = get_time(data, i + 3) high = get_high(data, i + 3) low = get_low(data, i + 3) order_blocks.append(OrderBlock(direction, time, high, low)) break if get_open(data, i) > get_close(data, i): # Bearish condition if get_open(data, i + 2) > get_close(data, i + 2): if get_open(data, i + 3) < get_close(data, i + 3) and get_open(data, i + 3) < get_close(data, i + 2): print(f"Bearish Order Block confirmed at: {get_time(data, i + 2)}") direction = -1 time = get_time(data, i + 3) high = get_high(data, i + 3) low = get_low(data, i + 3) order_blocks.append(OrderBlock(direction, time, high, low)) break return order_blocks def simulate_trading(data, order_blocks): trades = [] last_time = None for i, row in data.iterrows(): current_time = row['DATETIME'] if is_new_bar(current_time, last_time): last_time = current_time bid = row['<CLOSE>'] # Assuming bid price is close price ask = row['<CLOSE>'] # Assuming ask price is close price for ob in order_blocks: if not ob.traded: if ob.direction > 0 and ask < ob.high: # Buy condition entry = ask tp = data.iloc[:i]['<HIGH>'].max() # Take profit as highest high sl = ob.low - MGTN # Stop loss trades.append({ 'time': current_time, 'direction': 'buy', 'entry': entry, 'tp': tp, 'sl': sl }) ob.traded = True if ob.direction < 0 and bid > ob.low: # Sell condition entry = bid tp = data.iloc[:i]['<LOW>'].min() # Take profit as lowest low sl = ob.high + MGTN # Stop loss trades.append({ 'time': current_time, 'direction': 'sell', 'entry': entry, 'tp': tp, 'sl': sl }) ob.traded = True return trades
Код реализует торговую стратегию на основе поиска блоков ордеров и симуляции сделок по историческим данным. Начинаем с импорта библиотек Pandas для обработки данных, NumPy для численных операций и Keras/TensorFlow для интеграции AI. Скрипт задает ключевые параметры торговли: размер лота (LOTS), тейк-профит (TAKE_PROFIT), стоп-лосс (STOP_LOSS) и коэффициент управления риском (MGTN). Вспомогательные функции получает ценовые данные OHLC и временные метки. Класс OrderBlock хранит информацию о выявленных бычьих и медвежьих блоках, которые показывают, где институциональные игроки могли разместить крупные ордера.
Функция get_order_blocks сканирует исторические данные и определяет потенциальные блоки ордеров на основе последовательностей ценовых движений. Она фиксирует время, максимум и минимум каждого блока. Когда ордер-блок найден, функция simulate_trading симулирует сделку. Она проходит по историческим данным и проверяет появление новых свечей и соответствие ценовых условий критериям для покупки или продажи. Если условие выполняется, регистрируется сделка с динамическим назначением входной цены, тейк-профита и стоп-лосса на основе прошлых экстремумов. Это позволит нам, во-первых, протестировать ни истории, а во-вторых — закладывает основу для дальнейшей интеграции AI-модели.
# Columns: ['<DATE>', '<TIME>', '<OPEN>', '<HIGH>', '<LOW>', '<CLOSE>'] data = pd.read_csv('/home/int_junkie/Documents/DataVisuals/AI inside MQL5/XAUUSD_H1.csv', delimiter='\t') # Combine DATE and TIME into a single DATETIME column data['DATETIME'] = pd.to_datetime(data['<DATE>'] + ' ' + data['<TIME>']) # Drop the original DATE and TIME columns data.drop(columns=['<DATE>', '<TIME>'], inplace=True) # Step 1: Detect order blocks order_blocks = get_order_blocks(data) # Step 2: Simulate trading based on order blocks trades = simulate_trading(data, order_blocks)
После объединения удаляем даты и время для упрощения датасета. Далее скрипт вызывает get_order_blocks(data), который выявляет потенциальные бычьи и медвежьи блоки ордеров. Когда такие блоки найдены, simulate_trading(data, order_blocks) проводит тест — проверяет, срабатывают ли эти блоки по рыночным условиям, и симулирует сделки с учетом заданных правил входа, тейк-профита и стоп-лосса. Таким образом, оценивается эффективность стратегии на исторических данных.
# Features: Historical OHLC data # Labels: Buy (1), Sell (-1), Hold (0) labels = [] for i, row in data.iterrows(): label = 0 # Hold by default for trade in trades: if trade['time'] == row['DATETIME']: label = 1 if trade['direction'] == 'buy' else -1 labels.append(label) data['label'] = labels # Step 4: Train LSTM model (example using Keras) from keras.models import Sequential from keras.layers import LSTM, Dense # Prepare data for LSTM def create_sequences(data, seq_length): X, y = [], [] for i in range(len(data) - seq_length): X.append(data.iloc[i:i + seq_length][['<OPEN>', '<HIGH>', '<LOW>', '<CLOSE>']].values) y.append(data.iloc[i + seq_length]['label']) return np.array(X), np.array(y) seq_length = 50 # Sequence length for LSTM X, y = create_sequences(data, seq_length) # Build LSTM model model = Sequential() model.add(LSTM(50, input_shape=(seq_length, 4))) # 4 features: open, high, low, close model.add(Dense(1, activation='tanh')) # Output: -1 (sell), 0 (hold), 1 (buy) model.compile(optimizer='adam', loss='mse') # Train the model model.fit(X, y, epochs=20, batch_size=32) # Save the model model.save('lstm_trading_model.h5')
Выводимая информация:


В этой части мы обучаем LSTM-модель прогнозировать торговые решения на основе исторических цен. Датасет размечен тремя сигналами: 1 (покупка), -1 (продажа), 0 (удержание). Такое обозначение присваивается по временным меткам: если в данный момент была сделка, показываем ее направление, иначе — 0. Это позволяет провести обучение с учителем, чтобы модель научилась сопоставлять последовательности рыночных данных с будущими действиями.
Для обучения LSTM структурируем данные в последовательности по 50 шагов из цен OHLC. Каждая последовательность используется для предсказания сигнала на следующем шаге. Архитектура модели включает:
- LSTM-слой (50 единиц) для анализа временных закономерностей в параметре из четырех признаков (OHLC).
- Плотный выходной слой с функцией активации tanh для получения прогнозов в диапазоне от -1 до 1.
Модель обучается 20 эпох с функцией оптимизации Adam и функцией потерь MSE. После обучения сохраняем ее как lstm_trading_model.h5. Теперь модель готова и ее можно добавлять в стратегию для генерации сигналов в реальном времени.
Развертывание модели
После сериализации LSTM-модели в формате .h5 следующий шаг — добавить ее в экосистему MQL5. Прямой интеграции Python в MQL5 нет, поэтому создаем слой взаимодействия между ML-фреймворком Python и нативной торговой инфраструктурой MQL5. Стандартное решение — развертывание Python-микросервиса (например, Flask или FastAPI), хранящего обученную модель. Этот сервер выступает в виде эндпоинта. Он принимает данные рынка от MQL5, выполняет LSTM-инференс и возвращает торговые сигналы в реальном времени. На стороне MQL5 советник использует интерфейс WebRequest() для передачи данных и обработки JSON-ответов, преобразуя прогнозы в действия.
После внедрения следующий шаг — интеграция стратегии в реальном времени. Советник отправляет последовательности данных (например, 50 баров OHLC) на сервер инференса через настраиваемые интервалы. Python-сервис предобрабатывает данные, выполняет LSTM-вычисления и возвращает вероятностные торговые рекомендации (buy/sell/hold) с показатель уверенности. Эти сигналы передаются в пайплайн советника, где учитываются параметры риска — динамические стоп-лоссы, цели по прибыли и алгоритмы расчета объемов позиций. Для снижения операционных рисков рекомендуется поэтапное развертывание: проверка в демо-среде, мониторинг задержки инференса, а также внедрение резервных сценариев (например, возврат к стратегиям на технических индикаторах) для сохранения функциональности при сбоях сервера или аномалиях прогнозов.
Заключение
В этом проекте мы взяли существующую стратегию MQL5 и улучшили ее, интегрировав процесс принятия решений на основе AI с использованием LSTM. Сначала мы перевели основную логику MQL5 в Python, воспроизводя поведение стратегии с использованием исторических данных OHLC. Затем мы выявили ключевые торговые сигналы по блокам ордеров (order blocks) и симулировали сделки для генерации размеченных данных для обучения AI. После этого мы обучили LSTM на последовательностях исторических цен для предсказания действий: купить, продать или удерживать. В конце сохранили модель в формате .h5, после этого она готова к применению в трейдинге.
Интеграция AI в традиционную стратегию дает сильные преимущества. В отличие от статической логики с фиксированными условиями, LSTM-модель способна обучаться сложным закономерностям ценового поведения и адаптироваться к меняющимся рыночным условиям. Это делает стратегию более гибкой, потенциально более точной и менее подверженной ложным сигналам. Трейдер получает систему, которая сочетает структуру и надежность технических правил с адаптивностью и обучаемостью машинного обучения.
Гибридный подход улучшает решения по входам и выходам и открывает возможности для более интеллектуального, основанного на данных управления рисками в реальном времени. В отличие от статической логики с фиксированными условиями, LSTM-модель способна обучаться сложным закономерностям ценового поведения и адаптироваться к меняющимся рыночным условиям. Это делает стратегию более гибкой, потенциально более точной и менее подверженной ложным сигналам. Трейдер получает систему, которая сочетает структуру и надежность технических правил с адаптивностью и обучаемостью машинного обучения. Гибридный подход улучшает решения по входам и выходам и открывает возможности для более интеллектуального, основанного на данных управления рисками в реальном времени.
| Название файла | Описание |
|---|---|
| FIB_OB.mq5 | Файл с исходной стратегией MQL5 |
| FIB_OB to AI.ipynb | Файл, содержащий Notebook для преобразования логики стратегии, обучения модели и ее сохранения |
| XAUUSD_H1.csv | Файл с историческими данными о цене XAUUSD |
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/16973
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Разработка инструментария для анализа движения цен (Часть 20): Внешние библиотеки (IV) — Correlation Pathfinder
Создание торговой панели администратора на MQL5 (Часть IX): Организация кода (V). Класс AnalyticsPanel
Знакомство с языком MQL5 (Часть 28): Освоение API и функции WebRequest в языке MQL5 (II)
Улучшенная оптимизация сталкивающихся тел — Enhanced Colliding Bodies Optimization (ECBO)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Возможно ли заставить ИИ обучаться на постоянной основе?