English Deutsch 日本語
preview
Аналитическая торговля на основе профиля объема (AVPT): Архитектура ликвидности, рыночная память и алгоритмическое исполнение

Аналитическая торговля на основе профиля объема (AVPT): Архитектура ликвидности, рыночная память и алгоритмическое исполнение

MetaTrader 5Примеры |
259 9
Hlomohang John Borotho
Hlomohang John Borotho

Содержание:

  1. Введение
  2. Обзор системы и принципы работы
  3. Приступаем к работе
  4. Результаты тестирования на истории
  5. Заключение


Введение

Поскольку поток институциональных ордеров постоянно меняет ландшафт ликвидности, трейдеры должны полагаться на методы, которые отражают базовую структуру участия, а не только на ценовой шум. Аналитическая торговля на основе профиля объема (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

Прикрепленные файлы |
AVPT.mq5 (25.64 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (9)
Hlomohang John Borotho
Hlomohang John Borotho | 28 нояб. 2025 в 14:55
Cédric Olivier уровень поддержки/сопротивления

- Цена имеет тенденцию отступать к этому уровню

- **VAH (Value Area High)**: **верхняя пунктирная зеленая линия** - верхняя граница зоны стоимости
- **VAL (Value Area Low)**: **нижняя пунктирная зеленая линия** - нижняя граница зоны ценности
- Пространство между VAH и VAL представляет собой область, в которой торговалось 70% объема.

- Это считается "справедливой стоимостью" рынка за анализируемый период.

- **HVN (High Volume Nodes)**: **пунктирные синие линии** - ценовые уровни с очень высоким объемом (1,5x от медианного объема).

- Области повышенного институционального интереса

- Очень хорошие уровни поддержки/сопротивления

- **LVN (Low Volume Nodes)**: **пунктирные желтые линии** - ценовые уровни с очень низким объемом (0,3x медианного объема)

- Области с низким институциональным интересом

- Как правило, цена быстро пробивает эти уровни.

## Как использовать этот индикатор для торговли

1. **Определение ключевых областей**:

- POC - это самый важный уровень для мониторинга.

- Зона стоимости (между VAH и VAL) - это зона "справедливой стоимости".

2. **Торговые стратегии**:

- **Покупка**: Вблизи зоны ценности (VAL) или точки изменения (POC), если рынок находится в восходящем тренде.

- **Продажи**: Вблизи зоны средней стоимости (AVT) или точки изменения (POC), если рынок находится в нисходящем тренде
- **Цель**: Если цена пересекает уровень средней стоимости (LVN), она стремится продолжить движение к следующему уровню высокой стоимости (HVN).
- **Stop-loss**: Размещается за пределами значимого HVN

3. **Подтверждение**:

- Когда цена возвращается в зону стоимости после того, как покинула ее, это часто является хорошим сигналом возвращения к "справедливой стоимости".

- Цена выше AVT указывает на давление на покупку, ниже VAL - на давление на продажу.

## Настраиваемые параметры (внутри индикатора)
- Вы можете настроить процентное соотношение зоны стоимости (70% по умолчанию)
- Вы можете изменить пороговые значения для HVN и LVN в соответствии с вашими предпочтениями
- При необходимости можно включить/выключить отображение гистограммы

Этот индикатор особенно полезен. Он помогает определить, где институты торговали наиболее активно (HVN), где активность была незначительной (LVN) и где находится "справедливая" цена (Value Zone). Он высоко ценится трейдерами, придерживающимися концепции Smart Money.

Еще раз спасибо. Вместе, как сообщество, мы умнее!

Спасибо за индикатор Седрику Оливье.

Hlomohang John Borotho
Hlomohang John Borotho | 28 нояб. 2025 в 14:56
Ryan L Johnson #:

Какая эпическая статья и дискуссия... и все это всего за 3 дня.

@Hlomohang John Borotho, Спасибо.

@Cédric Olivier, Спасибо.


Я бы не стал беспокоиться о проверенном символе. К вашему сведению, это, скорее всего, не было безопасностью в техническом смысле слова, потому что iRealVolume() исключена из кода. В коде используется iVolume(), которая возвращает те же значения, что и iTickVolume()- эти функции обычно используются для внебиржевых рынков, например, FX, CFD и т.д.

Спасибо, Райан, и всем вам за отзывы, всегда пожалуйста.
Hlomohang John Borotho
Hlomohang John Borotho | 28 нояб. 2025 в 14:59
Bryan John Aldridge бэктест, чтобы подтвердить представленные результаты.

Привет, тестируемый символ - XAUUSD, и, пожалуйста, укажите период тестирования и настройки, использованные для достижения тех же результатов.

DecentOne
DecentOne | 1 дек. 2025 в 07:43
Есть ли советник для этого, который я могу скачать и использовать? Я не кодер.
Ryan L Johnson
Ryan L Johnson | 1 дек. 2025 в 13:11
DecentOne #:
Есть ли советник для этого, который я могу скачать и использовать? Я не кодер.

Он находится в конце статьи, ссылка на которую находится вверху в этом обсуждении:

Analytical Volume Profile Trading (AVPT): архитектура ликвидности, память рынка и алгоритмическое исполнение

(Так работают все обсуждения статей, автоматически размещаемые на форуме).

EA

Архитектура машинного обучения для MetaTrader 5 (Часть 7): От разрозненных экспериментов к воспроизводимым результатам Архитектура машинного обучения для MetaTrader 5 (Часть 7): От разрозненных экспериментов к воспроизводимым результатам
В последней части этой серии мы выходим за рамки отдельных методов машинного обучения и переходим к проблеме “исследовательского хаоса”, с которым сталкиваются многие количественные трейдеры. Эта статья посвящена переходу от разрозненных экспериментов в Jupyter Notebook к продуманному пайплайну промышленного уровня, обеспечивающему воспроизводимость, отслеживаемость и эффективность.
Методика рыночного позиционирования по VGT на базе тау Кендалла и дистанционной корреляции Методика рыночного позиционирования по VGT на базе тау Кендалла и дистанционной корреляции
В этой статье мы рассмотрим, как можно использовать взаимодополняющую пару индикаторов для анализа недавней 5-летней истории ETF-фонда Vanguard Information Technology Index Fund. Рассматривая два варианта алгоритмов — тау Кендалла и дистанционная корреляция, — мы стремимся выбрать не только идеальную пару индикаторов для торговли с использованием VGT, но и подходящие пары сигнальных паттернов, сочетающие эти два индикатора.
Нейросети в трейдинге: Оценка риска по несогласованности представлений (Окончание) Нейросети в трейдинге: Оценка риска по несогласованности представлений (Окончание)
В статье представлена инженерная реализация ReGEN-TAD для онлайн-обработки: единый вычислительный конвейер с магистралью (backbone) и универсальной генеративной головой прогнозирования/уточнения/реконструкции. Разобрана организация прямого и обратного прохода с запаздывающей обратной связью и контроль согласованности представлений. Тестирование в потоковом режиме иллюстрирует поведение системы и ограничения по риску; читатель получает готовую схему интеграции в торговый конвейер.
Событийная архитектура в MQL5: как превратить советник в полноценную торговую систему Событийная архитектура в MQL5: как превратить советник в полноценную торговую систему
Статья посвящена событийной архитектуре в MQL5 и описывает переход от монолитной модели OnTick к распределённой обработке. Разбираются предопределённые и пользовательские события, сервисы и обмен сообщениями между программами, а также типовые архитектурные ошибки. На практическом примере показано, как организовать взаимодействие индикаторов и советника, чтобы снизить нагрузку, повысить читаемость и упростить сопровождение.