English Русский Deutsch 日本語
preview
借助成交量精准洞悉交易动态:超越传统OHLC图表

借助成交量精准洞悉交易动态:超越传统OHLC图表

MetaTrader 5示例 |
48 3
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

概述

在技术分析领域,交易者历来主要依赖价格波动作为市场活动的主要指标。本文提出了一种独特的方法,将先进的成交量数学分析与机器学习技术相结合,重点探讨成交量模式如何为理解市场动态提供更深入地认知。我们提供了一个复杂的系统,该系统通过将LSTM神经网络与基于微积分的成交量衍生指标相结合,超越了传统的技术分析方法。

文章分为三个主要部分:第一部分讨论成交量分析的基本重要性及其数学基础;第二部分探讨成交量衍生指标和LSTM预测在识别市场机会中的实际应用;第三部分解释如何利用成交量背离分析、趋势确认和突破验证来优化交易决策。


理解成交量的核心功能

特定时间段内交易的股票或合约总数称为成交量,它是市场活动和流动性的关键指标。价格显示市场方向,而成交量则显示市场走势背后的信心,突显趋势的潜在强度和持久性。成交量是价格走势背后的驱动力,能够支持或反驳价格走势,因为成交量大的显著价格变化往往比成交量小的价格变化显示出更高的市场信心。此外,成交量模式通常能够预测价格变化,因此对于那些懂得如何将其与价格走势和市场背景相结合使用的交易者来说,成交量模式是宝贵的指标。


成交量的重要性

简单示例:

成交量分析的至关重要性可以通过一种超越标准分析的复杂数学技术来证明,该技术为交易者提供了一个比仅使用传统指标更先进的框架来理解市场动态。通过仅关注成交量动态(独立于OHLC数据),我们可以利用微积分和机器学习(特别是成交量衍生指标和LSTM神经网络)发现重要的市场洞察。这种新颖的方法利用复杂的数学概念来识别交易和市场参与度的微小变化,在价格走势显现之前提供可能市场走势的早期预警。

通过观察成交量变化率(一阶导数)及其加速度(二阶导数),并结合机器学习预测,交易者可以比使用传统成交量分析技术更精确地识别新趋势和可能的反转。当正确应用时,这种数学基础为市场分析提供了一种强大的方法,在当今算法驱动的市场中尤其有用,因为传统技术分析可能不够充分。

该方法考察三个重要的成交量组成部分:一阶导数(成交量变化率)、二阶导数(成交量变化加速度)以及确认相同成交量衍生指标的未来成交量LSTM预测。EA从标准的MetaTrader声明开始。 

EA从标准的MetaTrader声明开始。包括用于订单管理的Trade库和用于预测的自定义Volume_LSTM库。indicator_separate_window属性表示该指标将在单独窗口中显示,并为可视化分配了三个指标缓冲区。
#property copyright "Your Name"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#include <Trade\Trade.mqh>
#include <Volume_LSTM.mqh>
CTrade trade;

参数按逻辑组进行了划分。LSTM配置部分控制神经网络的行为,而入场参数则管理交易规则。每个参数都有其特定用途:LSTM参数控制预测模型的复杂度和记忆能力。交易参数用于定义仓位规模和盈利目标,风险管理参数则设定止损限额和追踪止损。

input group "Configuración LSTM"
input bool     UseLSTM = true;              
input int      LSTMHiddenSize = 32;         
input int      LSTMLookback = 10;           

input group "Entry Parameters"
input double   Lots = 0.1;         
input double   TPPoints = 100;      
input int      Periods = 4;         
input int      AccelBars = 4;       
input int      MaxBarsInTrade = 2; 
input double   ProfitClose = 15;    
input double   MaxDailyLoss = -25; 
input double   TrailingStart = 5;  
input double   TrailingStep = 5;

该函数用于计算成交量的变化率(一阶导数)以及成交量变化的加速度(二阶导数)。它会移动现有导数数据以保留历史记录,将当前成交量与前一成交量之差计算为新的一阶导数,将一阶导数的变化量计算为新的二阶导数,从而为洞察成交量的动量和加速度提供依据。

通过观察成交量的一阶导数,我们本质上是在追踪交易活动随时间推移是增加还是减少。这种成交量波动的模式为我们提供了对市场动量的第一层洞察。持续为正的一阶导数表明市场兴趣在增加,而持续为负的一阶导数则表明市场参与度在下降。

void CalculateDerivatives() {
    for(int i = 0; i < ArraySize(volumes)-1; i++) {
        firstDerivative[i] = firstDerivative[i+1];
        secondDerivative[i] = secondDerivative[i+1];
    }

    firstDerivative[ArraySize(volumes)-1] = volumes[ArraySize(volumes)-1] - volumes[ArraySize(volumes)-2];
    secondDerivative[ArraySize(volumes)-1] = firstDerivative[ArraySize(volumes)-1] - firstDerivative[ArraySize(volumes)-2];
}

这些函数负责管理交易的生命周期,其中TrackNewTrade函数在首个可用位置记录新开仓位,RemoveTrade函数则在仓位平仓时清除相应记录。这两个函数共同维护了交易跟踪系统的完整性。

void TrackNewTrade(ulong ticket) {
    for(int i = 0; i < ArraySize(openTrades); i++) {
        if(openTrades[i].ticket == 0) {
            openTrades[i].ticket = ticket;
            openTrades[i].openTime = TimeCurrent();
            openTrades[i].barsOpen = 0;
            break;
        }
    }
}

void RemoveTrade(ulong ticket) {
    for(int i = 0; i < ArraySize(openTrades); i++) {
        if(openTrades[i].ticket == ticket) {
            openTrades[i].ticket = 0;
            openTrades[i].openTime = 0;
            openTrades[i].barsOpen = 0;
            break;
        }
    }
}

该盈亏跟踪函数的功能如下:

  1. 识别当前交易日
  2. 计算已平仓交易的已实现盈亏
  3. 累加未平仓头寸的未实现盈亏
  4. 跨多笔交易维持每日盈亏跟踪记录
  5. 协助执行每日亏损限额控制
double GetDailyProfit() {
    datetime today = StringToTime(TimeToString(TimeCurrent(), TIME_DATE));

    if(lastDayChecked != today) {
        lastDayChecked = today;
        dailyProfit = 0;

        HistorySelect(today, TimeCurrent());
        int deals = HistoryDealsTotal();

        for(int i = 0; i < deals; i++) {
            ulong ticket = HistoryDealGetTicket(i);
            if(ticket > 0) {
                if(HistoryDealGetString(ticket, DEAL_SYMBOL) == _Symbol)
                    dailyProfit += HistoryDealGetDouble(ticket, DEAL_PROFIT);
            }
        }
    }
    
    // Add floating P/L
    double floatingProfit = 0;
    for(int i = PositionsTotal() - 1; i >= 0; i--) {
        ulong ticket = PositionGetTicket(i);
        if(ticket > 0 && PositionSelectByTicket(ticket)) {
            if(PositionGetString(POSITION_SYMBOL) == _Symbol)
                floatingProfit += PositionGetDouble(POSITION_PROFIT);
        }
    }

    return dailyProfit + floatingProfit;
}

该追踪止损函数的功能如下:

  1. 遍历所有未平仓头寸
  2. 计算每个头寸的点数盈利
  3. 根据盈利情况更新止损水平
  4. 实施追踪机制以锁定利润
  5. 分开处理买入和卖出头寸
void ApplyTrailingStop(double point) {
    for(int i = PositionsTotal() - 1; i >= 0; i--) {
        ulong ticket = PositionGetTicket(i);
        if(ticket <= 0) continue;

        if(PositionSelectByTicket(ticket)) {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
            double currentSL = PositionGetDouble(POSITION_SL);
            long posType = PositionGetInteger(POSITION_TYPE);

            // Calculate and update trailing stop
            double profitPoints;
            if(posType == POSITION_TYPE_BUY) {
                profitPoints = (currentPrice - openPrice) / point;
                if(profitPoints >= TrailingStart) {
                    double newSL = openPrice + (profitPoints - TrailingStep) * point;
                    if(currentSL < newSL || currentSL == 0) {
                        trade.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP));
                    }
                }
            }
            // Similar logic for SELL positions
        }
    }
}

成交量的二阶导数通过展示交易活动的加速或放缓,提供了更为详尽的信息。当二阶导数为正值时,这强烈表明市场动量正在增强,因为它显示成交量不仅在上升,而且上升的速度还在加快。由于这种成交量加速现象表明市场参与者的兴趣正在迅速增加,因此它往往发生在显著的市场波动之前。通过将这些导数与LSTM神经网络对未来成交量模式的预测相结合,我们为预测市场行为提供了一个强有力的框架。LSTM能够识别成交量序列中的复杂模式,这为我们的研究增添了额外的一层验证,有助于判断观察到的成交量趋势是否可能持续。

主要交易逻辑:

  1. 检查新K线是否形成
  2. 核实每日亏损限额
  3. 更新交易信息
  4. 执行成交量分析
  5. 如果启用,则生成LSTM预测
  6. 基于多种因素做出交易决策
  7. 当满足条件时开仓
void OnTick() {
    static datetime lastBar = 0;
    datetime currentBar = iTime(_Symbol, PERIOD_CURRENT, 0);

    if(lastBar == currentBar) return;
    lastBar = currentBar;

    if(GetDailyProfit() < MaxDailyLoss) {
        CloseAllPositions();
        return;
    }

    // Update and calculate
    UpdateTradesInfo();
    CheckTimeBasedClose();
    
    if(!CanTrade()) return;

    // Volume analysis and LSTM prediction
    // ... volume calculations ...
    
    if(UseLSTM && volumePredictor != NULL) {
        // LSTM prediction logic
        // ... prediction calculations ...
    }

    CalculateDerivatives();
    
    // Trading decisions based on calculations
    if(consecutiveAccel >= AccelBars) {
        if((!UseADX && !UseOBV) || ConfirmLongSignal()) {
            // Open buy position
        }
    }
    else if(consecutiveAccel <= -AccelBars) {
        if(!UseADX && !UseOBV || ConfirmShortSignal()) {
            // Open sell position
        }
    }
}

技术指标计算流程:

  1. 为指标值设置数据缓冲区
  2. 从指标句柄中复制指标数据
  3. 用新值更新本地数组
  4. 维护用于决策的指标数据
void CalculateADX() {
    if(!UseADX) return;

    double adx_buffer[];
    double plusdi_buffer[];
    double minusdi_buffer[];
    ArraySetAsSeries(adx_buffer, true);
    ArraySetAsSeries(plusdi_buffer, true);
    ArraySetAsSeries(minusdi_buffer, true);

    CopyBuffer(adx_handle, MAIN_LINE, 0, ArraySize(adx_main), adx_buffer);
    CopyBuffer(adx_handle, PLUSDI_LINE, 0, ArraySize(adx_plus), plusdi_buffer);
    CopyBuffer(adx_handle, MINUSDI_LINE, 0, ArraySize(adx_minus), minusdi_buffer);

    ArrayCopy(adx_main, adx_buffer);
    ArrayCopy(adx_plus, plusdi_buffer);
    ArrayCopy(adx_minus, minusdi_buffer);
}

各组件协同工作,共同构建了一个全面的交易系统。该系统融合了成交量分析、LSTM预测和传统技术指标,同时保持了稳健的风险管理实践。

Volume_LSTM.mqh文件实现了一个专门用于预测交易成交量的长短期记忆(LSTM)神经网络。

代码从基础的Matrix2D结构开始,该结构用于处理二维矩阵运算:

struct Matrix2D {
    double values[];
    int rows;
    int cols;
    
    void Init(int r, int c) {
        rows = r;
        cols = c;
        ArrayResize(values, rows * cols);
        ArrayInitialize(values, 0);
    }
    // ... other methods
}

实现完成后,LSTM单元将作为一个完整的结构体系:

struct LSTMCell {
    double forget_gate[];
    double input_gate[];
    double cell_state[];
    double output_gate[];
    double hidden_state[];
    
    Matrix2D Wf;  // Forget gate weights
    Matrix2D Wi;  // Input gate weights
    Matrix2D Wc;  // Cell state weights
    Matrix2D Wo;  // Output gate weights
    
    double bf[];  // Forget gate bias
    double bi[];  // Input gate bias
    double bc[];  // Cell state bias
    double bo[];  // Output gate bias
    
    int hidden_size;
    int input_size;
};

该实现过程包含标准的神经网络激活函数:

double Sigmoid(double x) {
    return 1.0 / (1.0 + MathExp(-x));
}

double Tanh(double x) {
    return (MathExp(x) - MathExp(-x)) / (MathExp(x) + MathExp(-x));
}

采用Xavier/Glorot初始化方法的变体对权重进行初始化:

void InitializeWeights() {
    double scale = MathSqrt(2.0 / (lstm.input_size + lstm.hidden_size));
    
    // Initialize weight matrices
    lstm.Wf.Init(lstm.hidden_size, lstm.input_size);
    lstm.Wi.Init(lstm.hidden_size, lstm.input_size);
    // ... other initializations

    // Random initialization with scaling
    for(int i = 0; i < lstm.hidden_size; i++) {
        for(int j = 0; j < lstm.input_size; j++) {
            lstm.Wf.Set(i, j, (MathRand() / 32768.0 - 0.5) * scale);
            // ... other weight initializations
        }
    }
}

该实现包含数据标准化处理:

void NormalizeVolumes() {
    volume_mean = 0;
    double sum_squared = 0;
    
    // Calculate mean
    for(int i = 0; i < ArraySize(historical_volumes); i++) {
        volume_mean += historical_volumes[i];
    }
    volume_mean /= ArraySize(historical_volumes);
    
    // Calculate standard deviation
    for(int i = 0; i < ArraySize(historical_volumes); i++) {
        sum_squared += MathPow(historical_volumes[i] - volume_mean, 2);
    }
    volume_std = MathSqrt(sum_squared / ArraySize(historical_volumes));
    
    // Normalize volumes
    if(volume_std == 0) volume_std = 1;  // Prevent division by zero
    for(int i = 0; i < ArraySize(historical_volumes); i++) {
        historical_volumes[i] = (historical_volumes[i] - volume_mean) / volume_std;
    }
}

核心预测逻辑:

double PredictNextVolume() {
    if(!is_initialized) return 0;
    
    double input1 = historical_volumes[ArraySize(historical_volumes)-1];
    
    // LSTM forward pass
    for(int h = 0; h < lstm.hidden_size; h++) {
        double ft = 0, it = 0, ct = 0, ot = 0;
        
        // Calculate gates
        for(int i = 0; i < lstm.input_size; i++) {
            ft += lstm.Wf.Get(h, i) * input1;
            it += lstm.Wi.Get(h, i) * input1;
            ct += lstm.Wc.Get(h, i) * input1;
            ot += lstm.Wo.Get(h, i) * input1;
        }
        
        // Apply gates and calculate states
        lstm.forget_gate[h] = Sigmoid(ft + lstm.bf[h]);
        lstm.input_gate[h] = Sigmoid(it + lstm.bi[h]);
        double c_tilde = Tanh(ct + lstm.bc[h]);
        lstm.cell_state[h] = lstm.forget_gate[h] * lstm.cell_state[h] + 
                            lstm.input_gate[h] * c_tilde;
        lstm.output_gate[h] = Sigmoid(ot + lstm.bo[h]);
        lstm.hidden_state[h] = lstm.output_gate[h] * Tanh(lstm.cell_state[h]);
    }
    
    // Calculate final prediction
    double prediction = 0;
    for(int h = 0; h < lstm.hidden_size; h++)
        prediction += lstm.hidden_state[h];
    prediction /= lstm.hidden_size;
    
    return prediction * volume_std + volume_mean;  // Denormalize
}


结果

EURUSD(欧元兑美元),这是欧元兑美元在30分钟时间周期下的交易结果。相关设置为Setting_eurusd.set

设置

图形

回测

GBPUSD(英镑兑美元),时间框架为30分钟。

GBPUSD settings.set

图形

回测

对主要货币对进行大规模优化可能会带来更好的交易结果,但受限于时间,本文无法进一步展开阐述。我强烈建议针对每个货币对进行大规模优化,并希望部分用户能在评论区分享新的可能配置方案。


高级技巧

趋势确认

价格上涨时成交量高,表明市场支撑强劲,趋势很可能延续。相反,价格下跌时成交量高,反映出强大的抛售压力,证实了负面趋势。价格波动时成交量低,则反映出趋势疲软或不可持续,往往预示着假突破或市场操纵。

突破验证

高成交量下的突破证实了市场决心,将导致价格持续变化。低成交量下的突破往往产生虚假信号,如“多头陷阱”或“空头陷阱”,且很可能失败。突破时成交量激增有力地验证了这一走势,并表明市场支撑强劲。

成交量背离

成交量背离,即价格和成交量趋势不同,预示着趋势可能反转或趋弱。价格上涨但成交量下降,表明上升趋势正在减弱;而价格下跌但成交量下降,则表明抛售压力减轻,市场可能触底。这些模式与其他指标结合使用时,有助于识别转折点。


结论

通过将前沿的机器学习方法和传统的成交量分析相结合,基于成交量的交易EA提供了一种先进的算法交易方法。该系统不仅利用LSTM神经网络进行成交量预测,还结合了ADX和OBV等传统技术指标,展现出强大的市场研究和交易执行能力。

该EA采用的多层次风险管理策略是其最大亮点,包括严格的每日亏损限额、动态追踪止损以及全面的仓位跟踪。这种对风险管理的重视,加上可调节的入场参数和灵活的交易时段管理,为交易者提供了一个灵活的工具,使其能够适应不同的市场状况,同时遵循严格的交易流程。

最重要的是,通过将成交量导数分析与LSTM预测相结合,构建了一个独特的混合系统。基于这种结合,该EA或许在市场变化完全显现之前就能够察觉到,并且传统指标的验证有助于减少虚假信号。模块化的代码结构也使得未来的优化和易于维护成为可能。

然而,用户应当注意,由于系统复杂,在实盘部署前必须进行精细的回测和参数调整。尽管LSTM组件功能强大,但它需要大量的处理能力和合适的训练数据。尽管存在这些问题,但该EA因其致力于将尖端技术与经过验证的交易理念相结合,对于希望自动化其基于成交量的交易方法的交易者来说,仍是一个有用的工具。

我希望本文有助于从认识到运用OHLCV(开盘价、最高价、最低价、收盘价和成交量)数据,而不仅仅是价格数据。


文件名 说明
MQL5/Profiles/Tester/Setting_eurusd.set 以欧元兑美元为例的输入设置
MQL5/Profiles/Tester/GBPUSD_settings.set
以英镑兑美元为例的输入设置
MQL5/Experts/Volume_high_low_difference_LSTM.mq5 示例中使用的EA
MQL5/Include/Volume_LSTM.mqh 包含.mqh文件。请记住在EA中更改保存路径


本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/16445

最近评论 | 前往讨论 (3)
TaiKingFX
TaiKingFX | 25 11月 2024 在 19:54
您是一位天才。我一直在寻找用交易量进行这种级别分析的方法。是否考虑过使用 "之 "字形指标 来分析价格方向,以及少量的需求和折扣区?如果时间允许,我会尝试这样做。
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera | 27 11月 2024 在 10:47
TaiKingFX 之 "字形指标 来分析价格方向,以及少量的需求和折扣区?如果时间允许,我会尝试这样做。

嗨,谢谢!我不太确定基因......但觉得这很有趣。我会写一篇文章,介绍人字形指标和交易量。我还将继续使用交易量制定更多策略。我正在搬家,需要一些时间来做更多的工作。

Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera | 17 12月 2024 在 18:56
TaiKingFX 之 "字形指标 来分析价格方向,以及少量的需求和折扣区?如果时间允许,我会尝试这样做。

你好,我花了几天时间研究交易量和之字形指标,但只得到了盈亏平衡的结果......以后我可能会花更多时间研究,但现在我觉得还不足以写成一篇文章。请你自己试试看,如果这是个好办法,请指正我。)(我发现有趣的是带有 ZigZag 的 ADX ...我可能会用它写一篇文章......刚刚开始......)......我保证以后会再用 ZigZag 检查成交量。

交易策略 交易策略
各种交易策略的分类都是任意的,下面这种分类强调从交易的基本概念上分类。
MQL5 交易管理面板开发指南(第六部分):交易管理面板(续篇) MQL5 交易管理面板开发指南(第六部分):交易管理面板(续篇)
在本文中,我们对多功能管理面板的“交易面板”进行升级。我们引入一个强大的辅助函数,大幅简化代码,提高可读性、可维护性与运行效率。同时演示如何无缝集成更多按钮,并优化界面,以支持更广泛的交易任务。无论是持仓管理、订单调整,还是简化交互,本文将助您打造稳健且易用的交易管理面板。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
您应当知道的 MQL5 向导技术(第 43 部分):依据 SARSA 进行强化学习 您应当知道的 MQL5 向导技术(第 43 部分):依据 SARSA 进行强化学习
SARSA 是 “State-Action-Reward-State-Action” 的缩写,是另一种能在实现强化学习时运用的算法。故此,正如我们在 Q-学习 和 DQN 中看到的那样,我们考察了如何在向导汇编的智能系统中探索和实现它,将其作为独立模型,而不仅仅是一种训练机制。