English Русский Deutsch 日本語
preview
您应该了解的MQL5向导技巧(第七十二部分):MACD与OBV组合形态的监督学习应用

您应该了解的MQL5向导技巧(第七十二部分):MACD与OBV组合形态的监督学习应用

MetaTrader 5交易系统 |
24 0
Stephen Njuki
Stephen Njuki

引言

在前一篇文章中,我们介绍了MACD与OBV这一指标组合,并研究了由这组互补指标所产生的10种可能信号形态。我们对由双指标组合得出的这10种信号形态,统一采用前向步进测试 —— 以上一年度数据进行训练或优化,再用下一年度数据进行前向步进测试。在前一篇文章中,只有形态7这一种信号形态在前向步进中实现了盈利。我们已经分析过这组指标组合相较于本文系列中其他指标表现不佳的部分原因,而这也为我们提供了一个“契机”—— 通过机器学习来优化部分信号形态。

因此,本篇将继续探讨使用有理二次核函数的卷积神经网络(CNN) 是否能够、以及如何辅助并改善指标信号的解读与应用。有理二次核(RQ核)函数的定义公式如下:

f1

其中:

  • k(x,x′) 表示两个输入x与x′之间的核相似度值。其取值范围在0至1之间,数值越接近1,表示相似度越高。

  • x与x′是两个输入向量(例如一维信号切片、特征向量或时间位置)。它们可以是标量值(维度为1),也可以是多维向量。

  • ∥x−x‘∥²为两个输入向量之间的欧氏距离平方,用于衡量x与x′在特征空间中的距离。该距离可通过以下公式计算:
  • f2

  • l为核函数的长度尺度(或称特征尺度)。它决定相似度随距离衰减的速度:
    • 小l:衰减迅速(局部敏感);
    • 大l:衰减缓慢(全局相似)。

  • α(alpha)为尺度混合参数(有时也称为形状参数)。它控制大尺度与小尺度变化的权重分配:

    • 当α趋向于∞时,该核函数等价于平方指数核(RBF核);
    • 当α较小时,核函数具有更厚的尾部,允许长距离交互。

在我们的一维CNN 实现中,有理二次核(RQK) 用于设定CNN卷积核大小与通道数。您也可考虑该核函数在CNN中的其他应用方式。


有理二次核的替代应用与优势

首先是自适应注意力掩码。在此场景中,RQ核在CNN内部构建空间或时间注意力掩码。这有助于图像分割或时间序列预测。其原理是强化与参考(如中心窗口)相似度高的区域。RQ核的另一个可能用途是距离感知池化。在此场景中,仅对位于RQ核所定义相似度阈值范围内的激活进行池化,而非对所有值取平均数。这样实现了兼顾特征邻近性的距离感知自适应池化。

另一个应用是特征重要性缩放。对CNN通道施加可学习的平滑权重。最后,在网络输入空间中,通过RQ核减少或“修剪”CNN中由核函数衡量为影响极小的权重。该核可以应用于卷积神经网络的原因也是多方面的。关于RQ核应用于CNN的优势,总结表格如下。

对异常值鲁棒 RQ核的厚尾特性使架构对空间或时间异常更不敏感。
平滑过渡 核函数平滑衰减,层间表示变化更平缓,利于梯度流动。
动态架构 基于相似度度量,以数据驱动的方式选择CNN卷积核大小或通道扩展。

采用RQ核的一维卷积网络(Conv‑1D)设计,非常适合一维输入且局部相似度重要的场景,例如本文研究的金融时间序列。其他适用数据类型包括音频信号和二进制模式检测。使用该CNN时,输入向量必须归一化或标准化到0至1的范围内(与我们此前文章的网络实践一致)。输入形状通常为 (batch_size, input_length), 其元素值通常落在0至1之间。 

RQ核包含多个重要的超参数,其中α尤为关键,如公式注释所述,它调节尾部衰减。其值越高,行为会更接近单尺度的RBF核。然而,随着该值降低,RQ核在α的调节下表现为多个不同尺度RBF的组合。另一个超参数是长度尺度,它决定了相似性对距离的敏感度。

如果我们的网络是具有概率分布输出的分类器,则可以在训练中使用BCE损失函数。鉴于我们非常规的架构,适当的初始化和学习率调度也很重要。还可以通过在各层之间添加残差连接以改善梯度传播来进行进一步扩展。此外,可以将RQ核集成作为门控机制。也可以在层堆栈之间使用基于相似性的Dropout。

研究表明,RQ核可定义Conv1D权重,从数据中提取特定模式。这种应用可显著减少总参数量、提升可解释性,但与可学习核相比,其适应性可能受限。有证据显示,该核在高斯过程层与CNN超参数优化中效果更佳,例如《带卷积核的深度高斯过程》一文所述。 

使用固定尺寸核可减少可学习参数、缓解过拟合,尤其在数据量有限时。这在本文所涵盖的木薯病害分类研究中得到了验证。然而,尽管预设核的可解释性有助于理解特征提取过程(与黑箱式的可学习核形成鲜明对比),但其适应性存在隐忧。固定核对数据的适配能力通常弱于可学习核,在复杂任务中可能会表现不佳。上述木薯研究显示,混合核性能优于单一RQ核,部分研究结果如下:

核类型 准确率
RQ核 88.5%
平方指数核 88.0%
混合核 90.1%

上述木薯研究数据表明,可学习核与固定核之间存在性能上的权衡,推荐采用混合方案。尽管早期RQ核的应用尚不明确,但是上述多项研究揭示了其在深度高斯过程(尤其图像数据)与Conv‑1D适配中的价值。木薯病害研究则支持采用预定义权重,以在固定核与可学习核之间取得平衡。

在网络设计中,卷积核大小与超参数长度尺度l相关联。多通道捕捉不同尺度,符合CNN采用不同感受野的实践,最终通过采用全局平均池化来保证灵活性。这确保了输出与序列长度无关,且适配0至1范围内的标量输出。


网络

我们的网络实现使用Python,因为正如我们在之前文章中所论述的,在Python中进行编码和训练比在MQL5中执行相同任务更高效。我们在Python中实现CNN,其核和通道使用RQ核进行缩放,具体如下:

import torch
import torch.nn as nn
import torch.nn.functional as F

import pandas as pd
import numpy as np

class RationalQuadraticConv1D(nn.Module):
    def __init__(self, alpha=1.0, length_scale=1.0, input_length=100):
        super(RationalQuadraticConv1D, self).__init__()
        self.alpha = alpha
        self.length_scale = length_scale
        self.input_length = input_length

        # Deeper and wider design
        self.kernel_sizes, self.channels = self._design_architecture()

        self.conv_layers = nn.ModuleList()
        in_channels = 1

        for i, (out_channels, kernel_size) in enumerate(zip(self.channels, self.kernel_sizes)):
            layer = nn.Sequential(
                nn.Conv1d(in_channels, out_channels, kernel_size=kernel_size, padding=kernel_size // 2),
                nn.BatchNorm1d(out_channels),
                nn.ReLU(),
                nn.Dropout(0.2)
            )
            self.conv_layers.append(layer)
            in_channels = out_channels

        # Fully connected head to increase parameter count
        self.head = nn.Sequential(
            nn.AdaptiveAvgPool1d(1),
            nn.Flatten(),
            nn.Linear(in_channels, 128),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, 1),
            nn.Sigmoid()
        )

    def _rq_kernel(self, x, x_prime):
        dist_sq = (x - x_prime) ** 2
        return (1 + dist_sq / (2 * self.alpha * self.length_scale ** 2)) ** -self.alpha

    def _design_architecture(self):
        x = torch.linspace(0, 1, self.input_length)
        center = 0.5
        responses = self._rq_kernel(x, center)
        thresholded = responses[responses > 0.01]  # allow more spread

        num_layers = 10
        kernel_sizes = [3 + (i % 4) * 2 for i in range(num_layers)]  # cyclic 3, 5, 7, 9
        channels = [32 * (i + 1) for i in range(num_layers)]  # 32, 64, ..., 320

        return kernel_sizes, channels

    def forward(self, x):
        x = x.unsqueeze(1)  # (B, 1, L)
        for layer in self.conv_layers:
            x = layer(x)
        return self.head(x)

我们首先定义一个自定义的PyTorch模块,其输入为RQ核公式中涉及的关键参数。我们将该类命名为RationalQuadraticConv1D,它继承自nn.Module —— 正如我们在之前文章中提到的,nn.Module是所有PyTorch神经网络模块的基类。构造函数初始化三个重要的RQ核参数:α、length‑scale(长度尺度)与 input‑length(输入长度)。前文提到的α控制核函数的形状;length‑scale决定核函数相似度随距离衰减的范围;input‑length用于捕获输入向量的预期尺寸/长度。

这些初始步骤至关重要,它们奠定了模型的基础,并允许对核函数的行为进行自定义配置。同时也确保模型架构与输入向量维度相匹配。α与length‑scale的参数调节用于调整核函数对输入差异的敏感度。例如,较小的length‑scale会聚焦于局部模式,而较大的值则能捕捉更广泛的相似性。与之前相同,input‑length需要与输入数据的尺寸严格匹配。 

初始化完成后,我们动态分配卷积层的卷积核大小与通道数。代码调用_design_architecture方法(后文会涵盖),该方法基于RQ核在输入空间的相似度分布,计算卷积核大小与通道数。这是本网络的核心设计思路:与传统固定架构的CNN不同,该方法使模型结构自适应数据特征,有望提升特征提取的效率与效果。这种自适应特性使模型适用于相似度结构多变的数据集。需要监控_design_architecture方法的输出,以确保架构与任务复杂度相匹配。

随后,我们构建一组具备动态属性的灵活卷积层栈。使用nn.ModuleList()函数创建一个容器,以容纳数量可变的卷积层。循环遍历out‑channels(输出通道数)与kernel‑size(卷积核大小)的配对,二者分别从self.channels与self.kernel‑sizes中读取。每个nn.Conv1D层的 in‑channels(输入通道数) 初始为1(第一层),输出至out‑channels,并使用kernel‑size与padding(填充)以保持输入长度不变。接下来,将in‑channels更新为当前层的out‑channels,供下一层使用,形成链式结构。

这种动态构建方式允许模型拥有定制化的层数与参数量。 同时,padding确保输出长度与输入长度一致 —— 这是处理序列数据的关键基础。较大的kernel‑size倾向于捕捉输入数据更广泛的模式,而更多的out‑channels则增加从数据中提取特征的多样性。如果无需完全保持长度(如进行下采样),可调整填充值(例如设置为0)。

接下来,我们定义最终网络层,将卷积输出处理为单一的类概率值。该层序列包含:nn.AdaptiveAvgPool1D、nn.Flatten、nn.Linear与nn.Sigmoid。它们的作用分别是:通过对序列进行全局平均,将空间维度压缩至1;将张量展平为一维向量;将展平后的特征映射至单个输出;输出0至1范围内的标量,更适合二分类或区间受限输出场景。 

最后这一步整合所有特征并生成特定任务的输出,使模型可用于二分类或概率估计。如果是用于多分类任务,可将线性层与Sigmoid层分别替换为nn.Linear(in_channels, num_classes) 与nn.Softmax()。回归任务则需移除Sigmoid,因为它更适用于分类场景。

在类内部,我们实现了一个计算数据点或向量间相似度的函数,即_rq_kernel函数。该函数按前文所述的RQ核公式计算相似度,其核心是计算x与 x′之间的欧氏距离。在α与length‑scale超参数的调控下,相似度随距离增大而降低。RQ核量化输入数据间的相似度,以此作为CNN架构设计的基础。

该核函数具备灵活性,可同时捕捉局部与全局模式。较大的α近似高斯核,较小的α则提供更高灵活性。调整length‑scale以控制衰减速度同样重要 —— 较小值会强化局部相似性。

这样引出了前文提及的_design_architecture函数。该函数利用RQ核的衰减特性,动态设计CNN架构。首先创建输入位置的归一化范围,即x;设定相似度计算的参考点center(中心);计算每个位置相对于中心的RQ核响应值responses;过滤出响应值大于0.2的位置,以聚焦显著区域。

完成上述步骤后,我们基于位置缩放卷积核大小(起始为3),距离center越远则核越大。倒数第二步,为相似度较低的区域分配更多通道(起始为4)。最后返回架构设置,将层数限制为3层。

该函数使CNN适配数据的相似度结构。更大的卷积核利于捕捉广泛模式,更多的通道则支持更复杂的特征提取。阈值、卷积核缩放因子和通道缩放因子均为可调参数。对于需要更深层特征提取的任务,可增加层数,但需权衡计算成本。

最后,前向传播方法定义RationalQuadraticConv1D类的逻辑。它执行从输入到输出的模型计算流程:为输入添加通道维度,以适配nn.Conv1D的输入格式;依次应用每个卷积层,并紧跟ReLU激活函数以引入非线性;再传入最终层,得到输出结果。前向步进函数定义了模型的数据流向,通过动态设计的架构提取用于预测的特征。

需确保输入形状为(batch_size, input_length),且激活函数类型适配当前任务。此类网络易出现形状不匹配问题,因此,关键是在每一步打印输入数据的形状以进行调试。现在,我们将结合Python实现的MACD与OBV指标,探讨如何设置网络输入。


MACD指标

尽管已有现成库与模块可实现部分指标,但我们仍用Python从基础代码开始实现指标。这样可以获得更流畅的编译与执行过程,并降低内存占用。使用MACD指标计算MACD线、信号线与柱状图,三者共同用于分析资产价格走势。在Python中的具体实现如下:

def MACD(df, fast_period: int = 12, slow_period: int = 26, signal_period: int = 9) -> pd.DataFrame:
    """
    Calculate Moving Average Convergence Divergence (MACD) and append it to the input DataFrame.

    The MACD line is the difference between a fast and slow EMA.
    The Signal line is an EMA of the MACD line.
    The Histogram is the difference between the MACD and Signal lines.
    
    Args:
        df (pd.DataFrame): DataFrame with a 'close' column.
        fast_period (int): Lookback period for the fast EMA. Default is 12.
        slow_period (int): Lookback period for the slow EMA. Default is 26.
        signal_period (int): Lookback period for the Signal line EMA. Default is 9.
        
    Returns:
        pd.DataFrame: Input DataFrame with new 'MACD', 'Signal_Line', and 'MACD_Histogram' columns.
    """
    # Input validation
    if 'close' not in df.columns:
        raise ValueError("DataFrame must contain a 'close' column")
    if not all(p > 0 for p in [fast_period, slow_period, signal_period]):
        raise ValueError("All period values must be positive integers")
    if fast_period >= slow_period:
        raise ValueError("fast_period must be less than slow_period")

    # Create a copy to avoid modifying the original DataFrame
    result_df = df.copy()
    
    # Calculate Fast and Slow Exponential Moving Averages (EMA)
    ema_fast = result_df['close'].ewm(span=fast_period, adjust=False).mean()
    ema_slow = result_df['close'].ewm(span=slow_period, adjust=False).mean()
    
    # Calculate MACD line
    result_df['MACD'] = ema_fast - ema_slow
    
    # Calculate Signal line (EMA of MACD)
    result_df['Signal_Line'] = result_df['MACD'].ewm(span=signal_period, adjust=False).mean()
    
    # Calculate MACD Histogram
    result_df['MACD_Histogram'] = result_df['MACD'] - result_df['Signal_Line']
    
    return result_df

我们的函数沿用一贯的编写格式:接收含收盘价列的Pandas数据框,以及三个可选整型参数:快速周期(默认值为12)、慢速周期(默认值为26)、信号周期(默认值为9)。和之前一致,函数输入采用数据表格式,适配MT5 Python模块导入的行情数据。该函数会返回输入数据表的副本,并在其中新增MACD值、MACD线和信号线三列计算结果。

代码起始部分会校验输入数据表是否包含收盘价列 —— 该列是计算指数移动平均线(EMA)的核心数据来源。另外,程序会校验所有周期参数均为正整数(周期参数代表回溯统计周期),并校验快速周期小于慢速周期,以确保MACD指标能够准确反映短期与长期趋势的差值变化。该校验机制可规避程序运行报错,保证指标逻辑严谨统一。重要的一点是避免因参数异常导致指标失真,进而产生错误的交易决策。 

接下来,程序会复制一份输入数据表,用于存储计算结果,保留原始数据不变。该开发规范可保证原始数据表可被多个函数复用、分析数据不被篡改,从而提升Python代码的模块化与复用性。完成复制数据表后,程序调用Pandas指数加权移动平均函数,基于收盘价分别计算快速周期与慢速周期的EMA。计算时将adjust参数设置为False,严格遵循标准EMA计算公式,并通过span参数设定统计窗口大小。span参数直接决定指标灵敏度:数值越小,EMA对价格变动越灵敏;数值越大,平滑降噪效果越强。

完成快慢EMA计算后,程序在输出数据表中新增一列MACD序列,该值由快速EMA减去慢速EMA得出,即为核心MACD线。MACD线是判断长短周期价格走势收敛、发散的核心指标,数值为正代表多头上涨趋势,数值为负代表空头下跌趋势。通过监测MACD线的运行方向与数值大小,可判断趋势强弱,而交叉拐点则作为趋势反转信号。

接下来,我们计算输出数据框中信号线的pandas序列。计算MACD线在signal-period上的EMA作为信号线。信号线用于平滑MACD线的波动,为交易信号提供稳定参考依据,MACD线与信号线的交叉是关键交易决策信号。默认9周期的信号线兼顾了指标灵敏度与平滑效果,可根据交易品种特性进一步微调优化。

最后,程序在输出数据表中新增MACD柱状图序列,数值为MACD线与信号线的差值。此计算有助于可视化动量强度,正值为看涨,负值为看跌。柱状图的正负切换往往预示行情反转。将以上三组指标序列全部写入数据表后,函数执行完毕并返回最终数据表。


OBV能量潮指标

该函数用于计算能量潮指标(OBV),这是一类通过关联价格波动与成交量变化进行行情分析的成交量指标。在Python中的具体实现如下:

def OBV(df) -> pd.DataFrame:
    """
    Calculate On-Balance Volume (OBV) and append it as an 'OBV' column 
    to the input DataFrame.

    OBV is a momentum indicator that uses volume flow to predict changes in stock price.
    
    Args:
        df (pd.DataFrame): DataFrame with 'close' and 'volume' columns.
        
    Returns:
        pd.DataFrame: Input DataFrame with a new 'OBV' column.
    """
    # Input validation
    if not all(col in df.columns for col in ['close', 'tick_volume']):
        raise ValueError("DataFrame must contain 'close' and 'volume' columns")

    # Create a copy to avoid modifying the original DataFrame
    result_df = df.copy()
    # print(result_df.columns)
    
    # Calculate the direction of price change
    # np.sign returns 1 for positive, -1 for negative, and 0 for zero change
    direction = np.sign(result_df['close'].diff())
    
    # Calculate the OBV
    # Multiply the volume by the direction of price movement
    # Then calculate the cumulative sum
    obv = (result_df['tick_volume'] * direction).cumsum()
    
    # The first value of diff() is NaN, so the first OBV will be NaN.
    # We can fill it with the first day's volume or 0. A common practice is to start at 0.
    result_df['OBV'] = obv.fillna(0)
    
    return result_df

以上源代码首先会对数据表进行校验,确保其包含必需的close(收盘价)列与tick_volume(分时成交量)列。我们之所以使用分时成交量,是因为该数据在绝大多数资产类别中都更容易获取;而外汇品种由于交易去中心化,真实成交量往往难以获得。校验完成后,我们会创建一份输入数据表的副本 —— 因为后续需要追加计算列,而如之前MACD函数所述,保留原始数据的完整性是更稳妥的做法。 

接下来,我们计算收盘价的变动方向。计算基于连续周期进行,使用np.sign函数标记:+1代表价格上涨;-1代表价格下跌;0代表价格无变化。这一步用于确定价格运行方向,而方向直接决定OBV中成交量的累计方式。此步骤还通过将价格趋势分析转换为离散符号形式,简化与成交量数据的集成。 

得到方向序列后,我们开始计算OBV:用成交量乘以价格方向,再做累计求和,以跟踪随时间变化的OBV。OBV的原理是在上涨行情中累加成交量,在下跌行情中递减成交量。因此,OBV值反映了市场的买入或卖出压力。OBV的趋势比其绝对数值更重要,对比其符号与价格方向,有助于确认趋势的有效性。

下一行代码用于处理因diff()计算产生的首个OBV空值(NaN),避免后续比较出错。同时将计算好的OBV值作为新列加入输出数据表。这里将初始OBV设置为0是合理的,因为0代表中性,即多空双方均无成交量偏向。这与直接给移动平均线缓冲区赋值0并非同一概念。


此前说明

在前一篇介绍MACD与OBV指标组合的文章中,大部分信号形态在前向步进中都无法盈利,只有形态7通过了前向步进。考虑到我们常规测试的10种形态中通常至少有6种可以盈利,这一表现明显偏弱。因此,我们挑选上一篇中表现极差的几种形态,尝试通过监督学习提升效果。本文选取了此前9个表现不佳形态中的3个,分别为形态2、形态3和形态5。

形态2

我们在Python中实现形态2的逻辑如下:

def feature_2(macd_df, obv_df, price_df):
    """

    """
    feature = np.zeros((len(macd_df), 2))
    
    feature[:, 0] = ((price_df['low'] < price_df['low'].shift(1)) &
                     (macd_df['MACD_Histogram'] > macd_df['MACD_Histogram'].shift(1)) &
                     (obv_df['OBV'] > obv_df['OBV'].shift(1))).astype(int)
    
    feature[:, 1] = ((price_df['high'] > price_df['high'].shift(1)) &
                     (macd_df['MACD_Histogram'] < macd_df['MACD_Histogram'].shift(1)) &
                     (obv_df['OBV'] < obv_df['OBV'].shift(1))).astype(int)
    
    feature[0, :] = 0
    feature[1, :] = 0
    
    return feature

简单回顾一下:该形态基于价格与指标的背离:价格创更低低点但MACD走高,为隐性看涨背离;价格创更高高点但MACD走低,为隐性看跌背离。同时结合成交量确认:上升的OBV代表资金在吸筹,为看涨信号;下降的OBV代表资金在派发,为看跌信号。总而言之,该形态旨在通过量能流向,验证价格虽创极值但由动能衰减所形成的背离信号。

因此,该形态用于识别趋势中的延续形态,在已经确立的趋势中(如明确的上涨或下跌趋势)可靠性最高。通常还需要两根K线确认,才能正式入场。我们使用基于有理二次核(RQ‑Kernel)构建架构的CNN网络,对该形态的信号进行测试:测试品种为英镑兑日元(GBPJPY),周期为4小时;训练与优化区间为2023.01.01至2024.01.01;样本外测试区间为2023.01.01至2025.01.01。测试报告如下:

r2

c2

与前一篇文章相比,本次效果明显有所提升,因此可以认为,我们的监督学习模型确实带来了改善。与之前相同,读者在将本文所述思路应用到实盘账户之前,务必进行更细致的研究和独立测试。尽管本系列文章主要面向自动化交易,但对部分读者而言,可视化我们描述的形态在图表上实际呈现的效果,会更有参考价值。形态2的看涨信号示例如下:

p2

形态3

我们在Python中实现该形态的代码如下:

def feature_3(macd_df, obv_df, price_df):
    """
    """
    feature = np.zeros((len(macd_df), 2))
    
    feature[:, 0] = ((macd_df['MACD_Histogram'] > macd_df['MACD_Histogram'].shift(1)) &
                     (macd_df['MACD_Histogram'].shift(1) < macd_df['MACD_Histogram'].shift(2)) &
                     (obv_df['OBV'] > obv_df['OBV'].shift(1))).astype(int)
    
    feature[:, 1] = ((macd_df['MACD_Histogram'] < macd_df['MACD_Histogram'].shift(1)) &
                     (macd_df['MACD_Histogram'].shift(1) > macd_df['MACD_Histogram'].shift(2)) &
                     (obv_df['OBV'] < obv_df['OBV'].shift(1))).astype(int)
    
    feature[0, :] = 0
    feature[1, :] = 0
    
    return feature

该形态通过寻找MACD柱状图的反转来识别信号:对于看涨信号,柱状图先下降后回升,形成底部拐点;对于看跌信号,柱状图先上升后回落,形成顶部拐点。柱状图用于捕捉动量转折点。为了有效识别底/顶形态并减少虚假信号,该形态需要三根K线来确认。

与此同时,使用OBV指标验证趋势:成交量方向应与价格趋势一致,OBV上行确认看涨信号,OBV下行确认看跌信号。理论上可作为机构参与的一个佐证。采用与上述形态2相同的条件进行测试,得到如下报告,结果显示该形态具备前向步进盈利能力:

r3

c3

该信号形态适用于趋势反转,在超买/超卖拐点位置效果较好。它需要至少三根K线的历史数据,因此,将序列中的前两根K线设置为0,因为没有可对比的数据。该形态在图表上的看涨信号示例如下:

p3

形态5

我们在Python中对该形态进行编码实现,代码如下:

def feature_5(macd_df, obv_df, price_df):
    """

    """
    feature = np.zeros((len(macd_df), 2))
    
    feature[:, 0] = ((macd_df['MACD_Histogram'] > macd_df['MACD_Histogram'].shift(1)) &
                     (macd_df['MACD_Histogram'] < 0.0) &
                     (obv_df['OBV'] > obv_df['OBV'].shift(1))).astype(int)
    
    feature[:, 1] = ((macd_df['MACD_Histogram'] < macd_df['MACD_Histogram'].shift(1)) &
                     (macd_df['MACD_Histogram'] > 0.0) &
                     (obv_df['OBV'] < obv_df['OBV'].shift(1))).astype(int)
    
    feature[0, :] = 0
    feature[1, :] = 0
    
    return feature

形态5基于MACD的零轴(0线)位置构建。该形态追求提前入场:当MACD处于零轴下方的空头区域时,触发看涨信号;当MACD处于零轴上方的多头区域时,触发看跌信号。在该形态信号出现时,结合第三方指标来提示动能转向,有助于规避虚假信号。同时,成交量方向过滤器应与量能动能转向保持一致,以此确认机构资金动向。

对于该形态,看涨信号通常出现在超卖区域,伴随动能回升,但信号容易衰竭;看跌信号通常出现在超买区域,伴随动能减弱,信号同样容易失效。该形态在震荡市场中效果更优,且需要MACD出现拐点或处于回升阶段。我们采用与上述另外两个形态相同的训练与优化方式对该形态进行测试,得到的测试报告如下:

r5

c5

在本次测试的三个形态中,该形态依然是前向步进表现最差的一个。原因可能在于入场时机过早,且缺乏独立的动能拐点确认,导致MACD信号出现较多虚假读数。该形态的图表示例如下:

p5



结论

总体而言,我们重新探究了上一篇文章中介绍的MACD与OBV指标组合,旨在改善其中部分信号形态表现不佳的问题。通过采用有理二次核动态设定卷积核与通道尺寸的监督学习CNN,在重新测试的三个形态中,有两个形态的效果得到了明显的改善。至于第三个形态(形态5)的表现依然不佳,我们认为原因在于入场点偏弱,需要更多的确认条件。

名称 描述
WZ-72.mq5 向导组装式EA,其头文件显示组装中所包含的文件
SignalWZ_72.mqh 向导组装中使用的自定义信号类文件
72_2.onnx Python导出的信号形态2网络模型
72_3.onnx
Python导出的信号形态3网络模型
72_5.onnx
Python导出的信号形态5网络模型
随附的自定义信号文件,可通过MQL5向导组装生成EA。新手读者可点击此处查看相关操作教程。

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

附加的文件 |
WZ-72.mq5 (6.91 KB)
SignalWZ_72.mqh (13.67 KB)
72_2.onnx (7541.91 KB)
72_3.onnx (7541.91 KB)
72_5.onnx (7541.91 KB)
按小时、星期几和每月日期分析的季节性指标 按小时、星期几和每月日期分析的季节性指标
本文介绍如何开发一款用于分析金融市场中重复性价格模式的工具 —— 可按每月日期(1-31 日)、星期几(周一至周日)或每日小时(0-23 时)进行分析。该指标分析历史数据,计算每个周期的平均收益率,并以直方图形式展示结果并附带预测。指标包含可自定义参数:季节性类型、分析 K 线数量、以百分比或绝对值显示、图表颜色等。
数据科学与机器学习(第四十五部分):利用Facebook的Prophet模型进行外汇时间序列预测 数据科学与机器学习(第四十五部分):利用Facebook的Prophet模型进行外汇时间序列预测
Prophet模型由Facebook研发,是一款稳健的时间序列预测工具,能够自动捕捉趋势、季节性与节假日效应,且几乎无需人工调整。该模型已被广泛应用于需求预测与商业规划。在本文中,我们将探讨Prophet模型在外汇交易品种波动率预测中的效果,展示其如何应用于传统商业场景之外的任务。
开发多币种 EA(第 27 部分):多行文本显示组件 开发多币种 EA(第 27 部分):多行文本显示组件
如果需要在图表上显示文本,我们可以使用 Comment() 函数。但它的功能相当有限。因此,在本文中,我们将自行开发一个组件 — 一个全屏对话框,该对话框能够显示多行文本,支持灵活的字体设置和滚动功能。
市场模拟(第 21 部分):SQL 入门(四) 市场模拟(第 21 部分):SQL 入门(四)
你们中的许多人可能比我更有数据库工作经验,因此可能会有不同的看法。由于有必要解释数据库为何以这样的方式设计,以及SQL为何具有这样的形式 — 尤其是主键和外键为何出现 — 因此有些内容必须保持一定的抽象性。