Аналитическая торговля на основе профиля объема (AVPT): Архитектура ликвидности, рыночная память и алгоритмическое исполнение
Содержание:
Введение
Поскольку поток институциональных ордеров постоянно меняет ландшафт ликвидности, трейдеры должны полагаться на методы, которые отражают базовую структуру участия, а не только на ценовой шум. Аналитическая торговля на основе профиля объема (AVPT) выходит далеко за рамки простых индикаторов, анализируя где фактически торговался рынок, а не только его движение. Благодаря взаимодействию уровней высокого объёма, уровней низкого объёма, зон стоимости и важнейших точек максимального объёма AVPT раскрывает скрытые слои рыночной памяти, точно показывая, на каких уровнях институциональные участники принимали рыночную цену, где отвергали её и где накапливали позиции.
Поскольку алгоритмическая торговля все больше доминирует на мировых рынках, понимание распределения объема по уровням цен становится решающим преимуществом. AVPT сочетает в себе анализ микроструктуры рынка с автоматизацией, позволяя трейдерам интерпретировать дисбалансы ликвидности в режиме реального времени и совершать сделки с хирургической точностью. Превращая необработанный объем в действенную структуру, этот подход превращает хаотичную рыночную активность в читаемую модель для определения тренда, ожидания пробоя и определения времени разворота.
Обзор системы и принципы работы
Ключевые компоненты профилирования объема:
| Компонент | Описание |
|---|---|
| Точка максимального объёма (POC) | Уровень цен с наибольшим объемом торгов, часто выступающий в качестве опорной точки для ценового движения. |
| Уровень высокого объёма (HVN) | Уровни цен, на которых происходит значительная торговая активность, указывающие на сильную поддержку или сопротивление. |
| Уровень низкого объёма (LVN) | Уровни цен с минимальной торговой активностью, на которых цены могут быстро изменяться из-за низкой ликвидности. |
| Зона стоимости | Диапазон ценовых уровней, в пределах которого осуществлялся определенный процент (обычно 70%) объема торгов. |
Аналитическая торговля на основе профиля объема (AVPT) представляет собой сложный подход к анализу рынка, выходящий за рамки традиционных технических индикаторов, основанных на ценах, и фокусирующийся на важнейшем параметре объема торгов на конкретных ценовых уровнях. По своей сути, AVPT визуализирует рынок как динамичный ландшафт, где ценовое движение взаимодействует с зонами поддержки и сопротивления, основанными на объемах. Гистограмма профиля объема, обычно отображаемая в виде горизонтальной гистограммы в правой части графика, показывает, где в течение определенного периода наблюдалась значительная торговая активность. Эта визуализация создает четкую карту рыночного консенсуса, показывая уровни цен, на которых институциональные участники и крупные трейдеры накапливали позиции (уровни высокого объёма), в сравнении с областями с минимальным участием (уровни низкого объёма). Точка максимального объёма (POC) действует как гравитационный центр этого ландшафта, представляя уровень цен с наибольшим торговым объемом и часто служа мощным магнитом для возврата цен.
Стратегическая логика AVPT основана на понимании того, как цена взаимодействует с этими структурами, основанными на объемах торгов. При приближении к уровням высокого объёма цена обычно сталкивается с сильной поддержкой или сопротивлением, поскольку эти уровни представляют собой зоны значительного институционального интереса и ликвидности. И наоборот, уровни низкого объёма функционируют как зоны ускорения, где цена может быстро изменяться из-за отсутствия значимого интереса к торговле. Зона стоимости, охватывающая приблизительно 70% объема за период, определяет диапазон "справедливой стоимости", в котором происходило большинство сделок. Визуализация этих компонентов создает всеобъемлющую торговую карту: трейдеры могут определить потенциальные зоны разворота вблизи границ стоимости, возможности пробоя через области низкого объема и целевые показатели прибыли в POC. Этот трехмерный анализ рынка, объединяющий цену, объем и время, обеспечивает значительное преимущество перед традиционным двухмерным анализом цен.
Практическая реализация AVPT предполагает мониторинг того, как текущее движение цены соотносится с установленными структурами объемов. На колеблющихся рынках трейдеры могут использовать стратегии возврата к среднему значению, покупая вблизи нижней границы зоны стоимости (VAL) со стопами ниже ближайших LVN и фиксируя прибыль в POC. В условиях тренда стратегии пробоя становятся применимыми, когда цена движется через зоны LVN с импульсом, нацеленным на расширение за пределы зоны стоимости. Визуализация делает управление рисками особенно интуитивно понятным — стоп-лоссы, естественно, находятся за пределами LVN, где пробои могут привести к аннулированию торговой предпосылки, в то время как размер позиции может адаптироваться в зависимости от ширины зоны стоимости и расстояния до ключевых уровней объема. Этот комплексный подход к анализу, срокам входа и управлению рисками создает систематическую методологию, которая согласуется с тем, как институциональные денежные потоки фактически формируют движение рынка.

Приступаем к работе
//+------------------------------------------------------------------+ //| AVPT.mq5 | //| GIT under Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com/ru/users/johnhlomohang/ | //+------------------------------------------------------------------+ #property copyright "GIT under Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/ru/users/johnhlomohang/" #property version "1.00" #include <Trade/Trade.mqh> //+------------------------------------------------------------------+ //| Input Parameters | //+------------------------------------------------------------------+ input group "=== Volume Profile Settings ===" input int VP_LookbackBars = 500; // Volume Profile Lookback Bars input double VA_Percentage = 70.0; // Value Area Percentage input double HVN_Threshold = 1.5; // HVN Volume Threshold (x median) input double LVN_Threshold = 0.3; // LVN Volume Threshold (x median) input group "=== Trading Settings ===" input double LotSize = 0.1; // Trade Lot Size input bool UseAtrSL = true; // Use ATR for Stop Loss input double AtrMultiplier = 2.0; // ATR Multiplier for SL input int AtrPeriod = 14; // ATR Period input double RiskRewardRatio = 1.5; // Risk/Reward Ratio input bool UseTrailingStop = true; // Enable Trailing Stop input double TrailingStep = 0.0010; // Trailing Stop Step input group "=== Strategy Settings ===" input bool EnableReversion = true; // Enable Reversion Strategy input bool EnableBreakout = false; // Enable Breakout Strategy input int MinBarsBetweenTrades = 3; // Minimum Bars Between Trades
Начнем с определения всех настраиваемых входных параметров, определяющих работу механизма профилирования объема и торговой логики. Первая группа параметров определяет параметры, связанные с профилем, такие как количество анализируемых ретроспективных баров, процент, используемый для вычисления зоны стоимости, а также пороговые значения для идентификации уровней высокого объёма и уровней низкого объёма торгов. В разделе настроек торговли затем устанавливаются параметры управления рисками и позициями, включая размер лота, стоп-лосс на основе ATR, соотношение риска и прибыли, а также поведение трейлинг-стопа, что обеспечивает советнику гибкость при адаптации к волатильности. Наконец, группа настроек стратегии включает или отключает ключевые режимы AVPT, такие как торговля на развороте или пробое, обеспечивая при этом минимальный интервал между сделками для более четкого исполнения и снижения уровня шума сигнала.
//+------------------------------------------------------------------+ //| Enumerations | //+------------------------------------------------------------------+ enum ENUM_LEVEL_POSITION{ BELOW, ABOVE }; enum ENUM_DIRECTION{ UP, DOWN }; //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ CTrade trade; // Volume Profile Arrays double volumeProfile[]; double priceLevels[]; int profileBins; // Key Levels double pocPrice; double vahPrice; double valPrice; double hvnLevels[]; double lvnLevels[]; // Trading datetime lastTradeTime; int atrHandle; double currentAtr;
Затем определим основные перечисления и глобальные переменные, поддерживающие логику советника и структуры данных. Перечисление обеспечивает четкую классификацию направлений и позиций, используемую во всей стратегии, в то время как глобальные переменные хранят основные торговые компоненты, такие как объект CTrade, динамически создаваемые массивы профилей объемов и ключевые уровни, такие как POC, VAH, VAL, HVN и LVN. Дополнительные переменные отслеживают торговую логистику, включая временную метку последней открытой сделки, и поддерживают доступ к таким индикаторам, как ATR, что позволяет советнику в режиме реального времени использовать данные о волатильности для определения стоп—лосса и принятия решений по управлению рисками.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Initialize ATR indicator atrHandle = iATR(_Symbol, _Period, AtrPeriod); if(atrHandle == INVALID_HANDLE) { Print("Error creating ATR indicator"); return(INIT_FAILED); } // Initialize volume profile arrays InitializeVolumeProfile(); // Set up timer for periodic updates EventSetTimer(60); // Update every minute return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(atrHandle); EventKillTimer(); CleanUpChartObjects(); }
На этапе инициализации советник настраивает все необходимые компоненты, сначала создавая индикатор ATR, используемый для расчета стоп-лосса на основе волатильности, и проверяя правильность его загрузки. Затем подготавливает массивы профилей объёма с помощью специальной функции инициализации и устанавливает повторяющийся таймер, чтобы система могла обновлять свой профиль и логику каждую минуту. В процессе деинициализации советник безопасно освобождает индикатор ATR, останавливает таймер и удаляет все созданные во время выполнения объекты графика, чтобы обеспечить корректное завершение работы и предотвратить утечки ресурсов.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Update ATR value UpdateAtrValue(); // Update volume profile every new bar if(IsNewBar()) { UpdateVolumeProfile(); CalculateKeyLevels(); UpdateChartObjects(); // Check for trading signals CheckTradingSignals(); } // Manage open positions ManagePositions(); } //+------------------------------------------------------------------+ //| Volume Profile Engine | //+------------------------------------------------------------------+ void InitializeVolumeProfile() { profileBins = 200; // Number of price bins ArrayResize(volumeProfile, profileBins); ArrayResize(priceLevels, profileBins); ArrayInitialize(volumeProfile, 0); }
В основном цикле выполнения советник непрерывно обновляет значение ATR на каждом тике для поддержания точных показателей волатильности. При формировании нового бара запускаются основные этапы обработки: обновление профиля объема, пересчет ключевых уровней, таких как границы POC и зоны стоимости, а также обновление визуальных объектов на графике. После обновления структурного анализа советник оценивает, выполняются ли какие-либо торговые условия на основе последних сигналов профиля объема, а затем отдельно управляет всеми открытыми позициями, чтобы стопы, логика трейлинга и выходы из позиций менялись в соответствии с рыночными условиями.
Механизм профилирования объема начинается с инициализации структуры данных, которая будет хранить распределение торгуемых объемов по ценовым уровням. Задав фиксированное количество интервалов и соответствующим образом изменив размер массивов, EA подготавливает чистый контейнер для сбора данных об объеме во время выполнения. Это гарантирует, что каждый новый бар может быть отнесён к соответствующему столбцу гистограммы объёма, что позволяет точно определять ключевые уровни, такие как HVN, LVN и Точку максимального объёма на более поздних этапах процесса.
void UpdateVolumeProfile() { // Clear previous profile ArrayInitialize(volumeProfile, 0); // Get price range for current lookback double highPrice = GetHighestPrice(VP_LookbackBars); double lowPrice = GetLowestPrice(VP_LookbackBars); double priceRange = highPrice - lowPrice; double binSize = priceRange / profileBins; // Initialize price levels for(int i = 0; i < profileBins; i++) { priceLevels[i] = lowPrice + (i * binSize); } // Distribute volume across price bins for(int bar = 0; bar < VP_LookbackBars; bar++) { double open = iOpen(_Symbol, _Period, bar); double high = iHigh(_Symbol, _Period, bar); double low = iLow(_Symbol, _Period, bar); double close = iClose(_Symbol, _Period, bar); long volume = iVolume(_Symbol, _Period, bar); DistributeVolumeToBins(open, high, low, close, volume, lowPrice, binSize); } } void DistributeVolumeToBins(double open, double high, double low, double close, long volume, double basePrice, double binSize) { double bodyLow = MathMin(open, close); double bodyHigh = MathMax(open, close); for(int i = 0; i < profileBins; i++) { double binLow = basePrice + (i * binSize); double binHigh = binLow + binSize; // Check if price bin was touched by this candle if(!(high < binLow || low > binHigh)) { // Weight volume by time spent in price zone (simplified) double overlap = MathMin(high, binHigh) - MathMax(low, binLow); double candleRange = high - low; if(candleRange > 0) { double weight = overlap / candleRange; // Additional weight for body area if(binLow <= bodyHigh && binHigh >= bodyLow) { double bodyOverlap = MathMin(bodyHigh, binHigh) - MathMax(bodyLow, binLow); weight += (bodyOverlap / candleRange) * 0.3; } volumeProfile[i] += volume * weight; } } } }
Функция UpdateVolumeProfile() восстанавливает все распределение объемов для заданного окна ретроспективного анализа, сначала сбрасывая гистограмму, а затем определяя ценовой диапазон, который необходимо профилировать. Она рассчитывает размер интервала на основе этого диапазона и инициализирует каждый ценовой уровень, соответствующий интервалу объема. После определения этих структурных границ функция перебирает исторические бары за ретроспективный период, извлекая значения OHLC каждой свечи и объема, а затем передает их в механизм распределения. Это гарантирует, что профиль всегда будет отражать самую актуальную и релевантную активность на рынке.
Функция DistributeVolumeToBins() выполняет основную логику распределения объема свечей по соответствующим ценовым интервалам. Для каждого интервала проверяется, взаимодействовал ли диапазон свечи с ним, и если да, то оценивается, какой объем торговой активности, вероятно, произошел в этой ценовой зоне. В этой оценке используется взвешенный метод, основанный на пропорциональном перекрытии между интервалом и диапазоном максимума-минимума свечи, при этом дополнительное внимание уделяется телу свечи, где обычно происходит более концентрированная торговля. Накопив эти взвешенные составляющие, советник формирует более реалистичный и детализированный профиль объёма, отражающий институциональные следы по ценовой шкале.
//+------------------------------------------------------------------+ //| Key Levels Calculation | //+------------------------------------------------------------------+ void CalculateKeyLevels() { CalculatePOC(); CalculateValueArea(); CalculateHVNLVN(); } void CalculatePOC() { double maxVolume = 0; int pocIndex = 0; for(int i = 0; i < profileBins; i++) { if(volumeProfile[i] > maxVolume) { maxVolume = volumeProfile[i]; pocIndex = i; } } pocPrice = priceLevels[pocIndex]; } void CalculateValueArea() { double totalVolume = 0; for(int i = 0; i < profileBins; i++) { totalVolume += volumeProfile[i]; } double targetVolume = totalVolume * (VA_Percentage / 100.0); int pocIndex = FindPriceIndex(pocPrice); double currentVolume = volumeProfile[pocIndex]; int upperIndex = pocIndex; int lowerIndex = pocIndex; while(currentVolume < targetVolume && (upperIndex < profileBins - 1 || lowerIndex > 0)) { bool canExpandUp = (upperIndex < profileBins - 1); bool canExpandDown = (lowerIndex > 0); double upVolume = canExpandUp ? volumeProfile[upperIndex + 1] : 0; double downVolume = canExpandDown ? volumeProfile[lowerIndex - 1] : 0; if(upVolume > downVolume && canExpandUp) { upperIndex++; currentVolume += upVolume; } else if(canExpandDown) { lowerIndex--; currentVolume += downVolume; } else if(canExpandUp) { upperIndex++; currentVolume += upVolume; } } vahPrice = priceLevels[upperIndex]; valPrice = priceLevels[lowerIndex]; } void CalculateHVNLVN() { ArrayResize(hvnLevels, 0); ArrayResize(lvnLevels, 0); // Calculate median volume double tempVolumes[]; ArrayCopy(tempVolumes, volumeProfile); ArraySort(tempVolumes); double medianVolume = tempVolumes[profileBins / 2]; double hvnThreshold = medianVolume * HVN_Threshold; double lvnThreshold = medianVolume * LVN_Threshold; for(int i = 0; i < profileBins; i++) { if(volumeProfile[i] >= hvnThreshold) { int size = ArraySize(hvnLevels); ArrayResize(hvnLevels, size + 1); hvnLevels[size] = priceLevels[i]; } else if(volumeProfile[i] <= lvnThreshold && volumeProfile[i] > 0) { int size = ArraySize(lvnLevels); ArrayResize(lvnLevels, size + 1); lvnLevels[size] = priceLevels[i]; } } }
Модуль расчёта ключевых уровней начинает с определения трёх основных компонентов профиля объема: точки максимального объёма, вычисления границ зоны стоимости, а также выявления уровней высокого объёма и уровней низкого объёма. Такой модульный подход позволяет каждому методу сосредоточиться на конкретном структурном элементе, обеспечивая корректную и понятную иерархию уровней ликвидности. Разделение логики позволяет легко отлаживать, расширять и оптимизировать систему по мере добавления новых стратегий или фильтров.
Расчеты POC и зоны стоимости совместно определяют центр тяжести рынка. POC определяется путем сканирования гистограммы объемов торгов для ценового интервала с наибольшим объемом сделок, отражающим уровень максимального принятия цены рынком. Затем зона стоимости расширяется от этой POC путем накопления объема в обоих направлениях до тех пор, пока совокупный объем не достигнет заданного процента. Эта логика расширения отдает приоритет ценовым уровням с большим объемом торгов, что позволяет советнику определять верхнюю границу зоны стоимости (VAH)) и нижнюю границу зоны стоимости (VAL) в качестве границ, представляющих район, где происходила наибольшая торговая активность.
Наконец, расчет HVN/LVN позволяет выявить зоны с исключительно высоким и необычно низким уровнем участия по сравнению со средним объемом. После вычисления медианы на основе отсортированной копии профиля, советник применяет заданные пользователем множители для обнаружения значимых кластеров (HVN) и зон отвержения (LVN). HVN отражают сильное принятие там, где цена имеет тенденцию к паузе, застою или развороту, в то время как LVN выделяют области с низкой ликвидностью, где цена часто ускоряется или пробивается. В совокупности эти уровни служат опорой для решений советника и позволяют применять адаптивные стратегии, основанные на структуре ликвидности и рыночной памяти.
//+------------------------------------------------------------------+ //| Trading Signal Logic | //+------------------------------------------------------------------+ void CheckTradingSignals() { if(!IsTradeAllowed()) return; // Check minimum bars between trades if(Bars(_Symbol, _Period, lastTradeTime, TimeCurrent()) < MinBarsBetweenTrades) return; double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_LAST); if(EnableReversion) { CheckReversionSignals(currentPrice); } if(EnableBreakout) { CheckBreakoutSignals(currentPrice); } } void CheckReversionSignals(double currentPrice) { MqlRates currentRates[]; CopyRates(_Symbol, _Period, 0, 3, currentRates); // Buy signal: Price rejects VAL with bullish confirmation if(IsNearLevel(currentPrice, valPrice) && IsBullishRejection(currentRates)) { double sl = FindNearestLVN(BELOW); double tp = pocPrice; OpenTrade(ORDER_TYPE_BUY, sl, tp); } // Sell signal: Price rejects VAH with bearish confirmation if(IsNearLevel(currentPrice, vahPrice) && IsBearishRejection(currentRates)) { double sl = FindNearestLVN(ABOVE); double tp = pocPrice; OpenTrade(ORDER_TYPE_SELL, sl, tp); } } void CheckBreakoutSignals(double currentPrice) { // Breakout above VAH with confirmation if(currentPrice > vahPrice && IsBreakoutConfirmed(UP)) { double sl = FindNearestHVN(BELOW); double tp = CalculateBreakoutTP(UP); OpenTrade(ORDER_TYPE_BUY, sl, tp); } // Breakout below VAL with confirmation if(currentPrice < valPrice && IsBreakoutConfirmed(DOWN)) { double sl = FindNearestHVN(ABOVE); double tp = CalculateBreakoutTP(DOWN); OpenTrade(ORDER_TYPE_SELL, sl, tp); } }
Затем логика торгового сигнала обеспечивает соответствие условиям для исполнения — подтверждает возможность открытия сделки, проверяет, что прошло достаточное количество баров с момента последней сделки, и фиксирует текущую рыночную цену. После выполнения этих условий советник оценивает, какие режимы стратегии активированы, и обрабатывает ценовое движение в соответствующих логических модулях. Если активна модель реверсии, советник проверяет, взаимодействует ли цена с границами зоны стоимости таким образом, что это указывает на отвержение; если активна модель пробоя, он ищет решающие движения за пределы уровней стоимости, подтвержденные структурным анализом.
В рамках каждой стратегии советник выполняет более детальные проверки для подтверждения сетапов сделки. Для анализа разворотов тренда система ищет бычьи или медвежьи паттерны отвержения вблизи уровней VAL или VAH, а затем рассчитывает уровни стоп-лосса и тейк-профита, используя ближайшие уровни LVN и POC в качестве естественного магнита. В отношении пробоев логика подтверждает, что цена четко вышла за пределы VAH или VAL, затем использует расположенные поблизости HVN в качестве защитных стопов и вычисляет целевые уровни по направлению на основе силы пробоя. Такая многоуровневая структура гарантирует, что сигналы основаны на архитектуре ликвидности, определяемой профилем объема, и формируют сделки, соответствующие как структуре рынка, так и контексту, основанному на объеме.
//+------------------------------------------------------------------+ //| Trade Execution & Risk Management | //+------------------------------------------------------------------+ void OpenTrade(ENUM_ORDER_TYPE type, double sl, double tp) { double price = (type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID); if(UseAtrSL) { double atrSl = currentAtr * AtrMultiplier; sl = (type == ORDER_TYPE_BUY) ? price - atrSl : price + atrSl; // Calculate TP based on risk/reward double risk = MathAbs(price - sl); tp = (type == ORDER_TYPE_BUY) ? price + (risk * RiskRewardRatio) : price - (risk * RiskRewardRatio); } // Execute trade using CTrade if(trade.PositionOpen(_Symbol, type, LotSize, price, sl, tp, "VolumeProfileEA")) { lastTradeTime = iTime(_Symbol, _Period, 0); Print("Trade executed: ", EnumToString(type), " Price: ", price, " SL: ", sl, " TP: ", tp); } else { Print("Trade failed: ", trade.ResultRetcodeDescription()); } } void ManagePositions() { for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket) && PositionGetString(POSITION_COMMENT) == "VolumeProfileEA") { if(UseTrailingStop) { ApplyTrailingStop(ticket); } // Check exit condition: price re-enters Value Area if(ShouldExitEarly(ticket)) { ClosePosition(ticket); } } } } void ApplyTrailingStop(ulong ticket) { if(PositionSelectByTicket(ticket)) { double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_LAST); double currentSL = PositionGetDouble(POSITION_SL); ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double newSL = currentSL; double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); if(type == POSITION_TYPE_BUY) { newSL = currentPrice - (currentAtr * TrailingStep); if(newSL > currentSL + point && newSL < currentPrice - point) { if(trade.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP))) { Print("Trailing SL updated for BUY: ", newSL); } } } else if(type == POSITION_TYPE_SELL) { newSL = currentPrice + (currentAtr * TrailingStep); if(newSL < currentSL - point && newSL > currentPrice + point) { if(trade.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP))) { Print("Trailing SL updated for SELL: ", newSL); } } } } } void ClosePosition(ulong ticket) { if(PositionSelectByTicket(ticket)) { ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double volume = PositionGetDouble(POSITION_VOLUME); if(type == POSITION_TYPE_BUY) { trade.PositionClose(ticket); } else if(type == POSITION_TYPE_SELL) { trade.PositionClose(ticket); } Print("Position closed early: ", ticket); } }
Логика открытия сделки начинается с формирования четкого, контролируемого с точки зрения риска ордера на основе типа сигнала, текущей рыночной цены и условий динамической волатильности. Если включен стоп-лосс на основе ATR, советник пересчитывает как стоп-лосс, так и тейк-профит, используя множитель ATR и настроенное соотношение риска и прибыли, обеспечивая адаптацию каждой позиции к текущей волатильности вместо использования фиксированных расстояний. После установки окончательных параметров советник использует объект CTrade для отправки ордера на сервер и регистрирует, было ли открытие успешным или неудачным. Этот структурированный рабочий процесс гарантирует, что сделки заключаются с одинаковым размером позиций, защитой от волатильности и логичными целевыми уровнями для фиксации прибыли, заложенными в архитектуре стратегии.
Затем механизм управления позициями контролирует все активные сделки VolumeProfileEA, применяя динамические трейлинг-стопы и оценивая необходимость досрочного выхода из сделки. Трейлинг-стоп корректируется с использованием движения на основе ATR, что позволяет стоп-лоссу эффективно отслеживать цену, не закрывая сделку слишком рано. Тем временем, логика досрочного выхода отслеживает, входит ли цена обратно в зону стоимости — что указывает на возможное ослабление первоначального торгового тезиса — и закрывает позицию для сохранения капитала. Эта двухуровневая система выхода, сочетающая логику отслеживания с проверками на недействительность структурных условий, гарантирует, что каждая позиция будет адаптироваться к рыночным условиям, одновременно ограничивая риски и фиксируя прибыль.
Результаты тестирования на истории
Тестирование на истории было проведено на таймфрейме H4 в течение примерно 2-месячного периода тестирования (с 01 сентября 2025 года по 03 ноября 2025 года) со следующими настройками:

Ниже представлена кривая эквити и результаты тестирования на истории:


Заключение
Таким образом, мы разработали процедуру аналитической торговли на основе профиля объема (AVPT), проанализировав, как архитектура ликвидности, распределение объемов и рыночная память формируют истинную структуру движения цен. Мы исследовали, как зоны больших объемов, зоны высокой ликвидности и неэффективность при низких объемах торгов формируют повторяющуюся модель того, где рынки останавливаются, расширяются или разворачиваются вспять. Затем мы преобразовали эту структурную логику в алгоритмическое исполнение, разработав схему, показывающую, как советник может считывать зоны профиля объема, предвидеть события, связанные с ликвидностью, и согласовывать точки входа с наиболее заметными следами институционального участия, а не с поверхностным движением цены.
В заключение, AVPT предоставляет трейдерам более интеллектуальный и контекстно-ориентированный подход к исполнению сделок: сделки больше не инициируются исключительно паттернами или индикаторами, а основаны на понимании того, где находится реальная ликвидность и как рынки “помнят” прошлые дисбалансы. Благодаря интеграции рыночной памяти, кластеризации объемов и алгоритмического принятия решений трейдеры получают систему, которая повышает точность, улучшает размещение рисков и снижает влияние шума в сигналах.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/20327
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Архитектура машинного обучения для MetaTrader 5 (Часть 7): От разрозненных экспериментов к воспроизводимым результатам
Методика рыночного позиционирования по VGT на базе тау Кендалла и дистанционной корреляции
Нейросети в трейдинге: Оценка риска по несогласованности представлений (Окончание)
Событийная архитектура в MQL5: как превратить советник в полноценную торговую систему
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Еще раз спасибо. Вместе, как сообщество, мы умнее!
Спасибо за индикатор Седрику Оливье.
Какая эпическая статья и дискуссия... и все это всего за 3 дня.
@Hlomohang John Borotho, Спасибо.
@Cédric Olivier, Спасибо.
Я бы не стал беспокоиться о проверенном символе. К вашему сведению, это, скорее всего, не было безопасностью в техническом смысле слова, потому что iRealVolume() исключена из кода. В коде используется iVolume(), которая возвращает те же значения, что и iTickVolume()- эти функции обычно используются для внебиржевых рынков, например, FX, CFD и т.д.
Привет, тестируемый символ - XAUUSD, и, пожалуйста, укажите период тестирования и настройки, использованные для достижения тех же результатов.
Есть ли советник для этого, который я могу скачать и использовать? Я не кодер.
Он находится в конце статьи, ссылка на которую находится вверху в этом обсуждении:
Analytical Volume Profile Trading (AVPT): архитектура ликвидности, память рынка и алгоритмическое исполнение
(Так работают все обсуждения статей, автоматически размещаемые на форуме).