English Русский Español Português
preview
在MQL5中自定义交易品种:创建三维K线自定义品种

在MQL5中自定义交易品种:创建三维K线自定义品种

MetaTrader 5指标 |
28 1
Yevgeniy Koshtenko
Yevgeniy Koshtenko

现代交易需要突破常规的数据分析思路。传统价格图表虽具备实用价值,往往无法完整呈现市场动态的全貌。价格仅为市场维度之一,成交量、波动率、时间周期规律能够帮助交易者更深度地解读市场。

MetaTrader 5平台与MQL5语言提供了强大功能 —— 自定义品种,交易者可基于任意数据构建合成标的。在本文中,我们将详细解析3DBarCustomSymbol.mq5指标,该指标能够生成展示三维K线的自定义品种。这类三维K线把价格、时间、成交量、波动率融为一体,打造出独有的分析可视化工具。

三维K线是在标准图表基础上增加多维信息的一种实现方案。交易者不仅能观察价格涨跌,还能直观地查看交易活跃度、市场波动率、时间周期规律等指标。该方式能够揭示常规K线图无法呈现的隐藏市场规律。

3DBarCustomSymbol指标完整展示了如何借助MQL5内置功能创建自定义品种,既可用于可视化行情分析,也可对接各类交易策略。



市场数据分析的发展历程

市场分析手段从纸质手绘图表,逐步发展为复杂计算机算法与微观结构研究(成交量、订单流、交易时段、集群波动率等)。但绝大多数分析手段都相互割裂,无法统一展示。

三维K线在同一张图表中融合了四大核心维度:

  • 价格:开盘价/最高价/最低价/收盘价(OHLC)数据、行情涨跌速率与加速度、价格分布统计;
  • 成交量:总成交量、分价位成交量分布、交易活跃度、量价异常、主动买入/卖出成交占比;
  • 时间:日内周期循环、K线生成速率、时序相关性、季节性特征;
  • 波动率:局部波动率、全局波动率、波动聚集效应、脉冲式异动、成交量与波动率联动关系。

这套体系能够完整还原市场全貌,快速识别行情规律与异常信号。此外,三维K线在视觉上更易于处理和识别,降低了交易者的信息处理负担,加快了决策速度,尤其适用于高频交易场景。该自定义指标可无缝接入MetaTrader 5,适配从剥头皮到长线持仓等各类交易策略。



三维K线概念的数学定义

三维K线在数学上可抽象为高维空间中的向量:

B₃D = (P, V, T, σ)

其中:

  • P — 价格向量(开盘价、最高价、最低价、收盘价、典型价格)
  • V — 成交量向量(总成交量、成交量分布、成交量加速度)
  • T — 时间向量(时间正弦特征、时间余弦特征、时间加速度特征)
  • σ — 波动率向量(局部波动率、全局波动率、波动率变动幅度)

每一组向量分量均包含静态(历史)数据与动态(实时)数据两部分。



指标架构

该指标的架构遵循关注点分离原则:

初始化模块负责以下功能:

  • 校验源交易品种的可用性;
  • 验证输入合法性;
  • 初始化全局变量;
  • 创建所需的数据结构。

品种创建模块包含以下功能:

  • 创建自定义品种函数;
  • 交易品种属性配置;
  • 交易时段设置;
  • 元数据赋值。

数据处理模块包含以下功能:

  • 各项指标的计算算法;
  • 数据归一化与缩放函数;
  • 统计运算逻辑;
  • 异常处理机制。

数据更新模块实现以下功能:

  • 实时监控新增行情数据;
  • 重新计算当前各项指标;
  • 更新自定义品种;
  • 程序运行优化。



输入参数详解

该指标支持自定义输入参数,配置方式灵活。以下为代码中的参数定义示例:

input string   SourceSymbol = "EURUSD";        // Source symbol
input string   CustomSymbolName = "EURUSD_3D"; // Custom symbol name
input int      LookbackPeriod = 20;            // Lookback period
input int      HistoryDays = 100;              // Number of history days
input bool     CreateWindow = true;            // Create a chart window
input bool     UpdateInRealTime = true;        // Update in real time
input bool     ShowPrice = true;               // Show a regular price
input double   MinSpreadMultiplier = 45;       // Spread multiplier
input double   VolumeBrick = 500;              // Volume block size
input double   ScaleMin = 3.0;                 // Minimum scale value
input double   ScaleMax = 9.0;                 // Maximum scale value

其中:

  • SourceSymbol(源品种) —— 用于分析的基础金融标的。支持MetaTrader 5内全部交易品种,包括货币对、股票、商品、指数与加密货币。
  • CustomSymbolName(自定义品种名称) —— 所创建自定义品种的唯一名称。建议使用表意名称,能够直观体现数据转换逻辑。
  • LookbackPeriod(回溯周期) —— 用于统计指标计算的滑动窗口大小。该参数决定指标对短期行情变化的敏感度。较小数值(5至10)提供更高的灵敏度,较大数值(50至100)提供更平滑的输出信号。
  • HistoryDays(历史天数) —— 初始化加载的历史数据深度。影响加载速度与长期统计数据的精准度。根据分析需求,最优取值范围为30至365天。
  • MinSpreadMultiplier(最小点差乘数)与VolumeBrick(成交量块阈值) —— 核心参数,分别控制算法对价格波动和成交量变化的敏感度。
  • ScaleMin和ScaleMax(最小和最大缩放值) —— 所有指标数据的归一化区间。3至9这一区间是基于数字象征/数秘学层面的考虑选定的,同时也有助于提升可视化的可解释性。

OnInit函数负责完成初始化配置工作:校验源品种是否存在,根据点差计算价格区块尺寸,创建自定义品种并载入历史数据。其核心代码段如下:

int OnInit()
{
   if(!SymbolSelect(SourceSymbol, true))
   {
      Print("Error: symbol ", SourceSymbol, " not found!");
      return INIT_FAILED;
   }
   
   double spread = SymbolInfoDouble(SourceSymbol, SYMBOL_ASK) - SymbolInfoDouble(SourceSymbol, SYMBOL_BID);
   double point = SymbolInfoDouble(SourceSymbol, SYMBOL_POINT);
   minPriceBrick = spread * MinSpreadMultiplier * point;
   
   if(!Create3DBarSymbol())
   {
      Print("Error creating custom symbol!");
      return INIT_FAILED;
   }
   
   if(!GenerateHistorical3DBars())
   {
      Print("Error generating historical data!");
      return INIT_FAILED;
   }
   
   if(CreateWindow)
   {
      OpenCustomChart();
   }
   
   if(UpdateInRealTime)
   {
      EventSetTimer(5);
   }
   
   Print("3D bars symbol ", CustomSymbolName, " successfully created!");
   return(INIT_SUCCEEDED);
}

Create3DBarSymbol函数用于配置自定义品种的各项属性,例如精度、最小报价单位、计价货币等,同时将交易时段设置为全天候24/7运行。例如:

bool Create3DBarSymbol()
{
   if(SymbolSelect(CustomSymbolName, true))
   {
      CustomRatesDelete(CustomSymbolName, 0, 0);
      Print("Symbol ", CustomSymbolName, " already exists. History deleted.");
      return true;
   }
   
   int digits = (int)SymbolInfoInteger(SourceSymbol, SYMBOL_DIGITS);
   double point = SymbolInfoDouble(SourceSymbol, SYMBOL_POINT);
   double tickSize = SymbolInfoDouble(SourceSymbol, SYMBOL_TRADE_TICK_SIZE);
   double contractSize = SymbolInfoDouble(SourceSymbol, SYMBOL_TRADE_CONTRACT_SIZE);
   string baseCurrency = SymbolInfoString(SourceSymbol, SYMBOL_CURRENCY_BASE);
   string profitCurrency = SymbolInfoString(SourceSymbol, SYMBOL_CURRENCY_PROFIT);
   
   if(!CustomSymbolCreate(CustomSymbolName))
   {
      Print("Error creating custom symbol: ", GetLastError());
      return false;
   }
   
   CustomSymbolSetInteger(CustomSymbolName, SYMBOL_DIGITS, digits);
   CustomSymbolSetDouble(CustomSymbolName, SYMBOL_POINT, point);
   CustomSymbolSetDouble(CustomSymbolName, SYMBOL_TRADE_TICK_SIZE, tickSize);
   CustomSymbolSetDouble(CustomSymbolName, SYMBOL_TRADE_CONTRACT_SIZE, contractSize);
   CustomSymbolSetString(CustomSymbolName, SYMBOL_CURRENCY_BASE, baseCurrency);
   CustomSymbolSetString(CustomSymbolName, SYMBOL_CURRENCY_PROFIT, profitCurrency);
   
   string description = "3D bars (price, time, volume, volatility). Lookback: " + IntegerToString(LookbackPeriod);
   CustomSymbolSetString(CustomSymbolName, SYMBOL_DESCRIPTION, description);
   
   for(int day=0; day<7; day++)
   {
      datetime start_time = 0;
      datetime end_time = 24*60*60-1;
      CustomSymbolSetSessionQuote(CustomSymbolName, (ENUM_DAY_OF_WEEK)day, 0, start_time, end_time);
      CustomSymbolSetSessionTrade(CustomSymbolName, (ENUM_DAY_OF_WEEK)day, 0, start_time, end_time);
   }
   
   return true;
}

GenerateHistorical3DBars函数负责处理历史数据,计算价格收益率、价格加速度、成交量变化以及波动率等指标。该函数使用M15(15分钟)周期作为基础数据源。部分代码如下:

bool GenerateHistorical3DBars()
{
   datetime endTime = TimeCurrent();
   datetime startTime = endTime - HistoryDays * 24 * 60 * 60;
   
   MqlRates rates[];
   int copiedRates = CopyRates(SourceSymbol, PERIOD_M15, startTime, endTime, rates);
   
   if(copiedRates <= 0)
   {
      Print("Error copying historical data: ", GetLastError());
      return false;
   }
   
   MqlRates threeDBars[];
   ArrayResize(threeDBars, copiedRates);
   int validCount = 0;
   
   double typicalPrices[], priceReturns[], priceAccelerations[], volumeChanges[], volatilities[];
   ArrayResize(typicalPrices, copiedRates);
   ArrayResize(priceReturns, copiedRates);
   ArrayResize(priceAccelerations, copiedRates);
   ArrayResize(volumeChanges, copiedRates);
   ArrayResize(volatilities, copiedRates);
   
   for(int i = 0; i < copiedRates; i++)
   {
      typicalPrices[i] = (rates[i].high + rates[i].low + rates[i].close) / 3.0;
      
      if(i > 0)
      {
         priceReturns[i] = (typicalPrices[i] - typicalPrices[i-1]) / typicalPrices[i-1];
         priceAccelerations[i] = i > 1 ? priceReturns[i] - priceReturns[i-1] : 0;
      }
      else
      {
         priceReturns[i] = 0;
         priceAccelerations[i] = 0;
      }
      
      volumeChanges[i] = i > 0 ? (rates[i].tick_volume - rates[i-1].tick_volume) / (rates[i-1].tick_volume + 1e-10) : 0;
      
      if(i >= LookbackPeriod)
      {
         double returns[];
         ArrayResize(returns, LookbackPeriod);
         for(int j = 0; j < LookbackPeriod; j++)
            returns[j] = priceReturns[i - LookbackPeriod + j + 1];
         volatilities[i] = CalculateStdDev(returns);
      }
      else
      {
         volatilities[i] = 0;
      }
   }
   // Next comes filling the 3D bars and adding them to the history
}

如果启用了UpdateInRealTime参数,UpdateCurrent3DBar函数会每5秒刷新一次当前K线。它会为当前K线计算相同的各项指标,并更新自定义品种。

double ScaleValue(double value, double &values[], int start, int end)
{
   double minVal = values[start];
   double maxVal = values[start];
   
   for(int i = start; i <= end; i++)
   {
      if(values[i] < minVal) minVal = values[i];
      if(values[i] > maxVal) maxVal = values[i];
   }
   
   if(maxVal == minVal) return ScaleMin;
   
   return ScaleMin + (ScaleMax - ScaleMin) * (value - minVal) / (maxVal - minVal);
}

OpenCustomChart函数会打开自定义品种的图表,根据ShowPrice参数,可将其显示为K线图或折线图。



实际应用

该指标可用于分析波动率、识别成交量或价格加速度中的异常形态,并可将自定义品种集成到交易系统中。

首先在MetaEditor中编译代码,然后将指标加载到图表上(例如EURUSD M15)。设置CustomSymbolName和LookbackPeriod等参数后,指标会自动创建一个自定义品种,可在独立窗口中打开。如果启用ShowPrice参数,图表将显示标准价格并叠加相关指标,否则仅显示合成的三维K线。

典型效果图如下:

交易者可借助三维K线识别可能对应新闻事件的高波动阶段,同时捕捉成交量骤增等各类市场异常信号。该自定义品种可搭配均线等各类技术指标使用,也可接入智能EA,实现自动化交易。

可对该指标进行迭代升级:新增一小时、日线等更大周期,用于分析中长期行情走势;加入资产相关性等拓展指标,进一步提升数据分析维度与信息量。对于配置较低的电脑,可适当缩减历史数据天数(HistoryDays),降低设备负载以优化性能;可叠加布林带等可视化指标,或添加异常筛选器,精准高亮波动率极端的K线形态,优化可视化效果。

批量生成大量历史数据会占用大量系统资源,建议从较小的历史数据天数开始调试。M15适用于绝大多数交易品种,低流动性标的建议选用更长的时间周期。实盘交易前,务必在模拟账户中测试指标运行稳定性。解读三维K线需要一定的经验,建议先通过历史数据熟悉其行情表现规律。



结论

3DBarCustomSymbol指标充分展现了MQL5自定义品种的强大功能。通过整合价格、时间、成交量、波动率四大核心市场维度,打造出独一无二的行情分析工具。三维K线既适用于可视化行情分析,也可用于搭建交易系统、挖掘隐藏的市场规律。可根据您自身的交易需求,自定义调整参数,并通过模拟账户反复测试优化。MQL5为量化交易创新提供了无限可能,而3DBarCustomSymbol正是依托该平台功能、打造高效专业分析工具的典型示例。 

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/18681

附加的文件 |
3D_Bars_EA.mq5 (39.53 KB)
最近评论 | 前往讨论 (1)
Andy An
Andy An | 17 7月 2025 在 08:34
该指标在在线模式下无法正常工作。
极值优化(EO) 极值优化(EO)
本文介绍极值优化算法(EO),这是一种受Bak-Sneppen(巴克–斯内彭)自组织临界性模型启发的优化方法,通过淘汰系统中表现最差的组件来实现演化。该算法的改进种群版本表明,其设计已从理论原则转向更注重实际效率,由此构建出高效的计算工具。
市场模拟(第 23 部分):SQL 入门(六) 市场模拟(第 23 部分):SQL 入门(六)
在本文中,我们将探讨如何可视化一个数据库,并借此了解其结构。这是通过分析数据库的内部结构来实现的。虽然乍一看这似乎没有必要,但如果我们真的想成为数据库管理员,那么这样做是完全合理的。毕竟,有些人以维护和设计数据库为生。
您应该了解的MQL5向导技巧(第 75 部分):动量震荡指标与包络线的应用 您应该了解的MQL5向导技巧(第 75 部分):动量震荡指标与包络线的应用
比尔・威廉姆斯的动量震荡指标(AO)与包络线通道是一对可以在 MQL5 智能交易系统(EA)中互补使用的指标组合。我们利用动量震荡指标识别趋势的能力,同时引入包络线通道来定义支撑位和阻力位。在探索这组指标组合的过程中,我们使用 MQL5 向导来构建并测试二者可能具备的交易潜力。
因果推断与量化交易中的回归模型探索 因果推断与量化交易中的回归模型探索
本文探究了将回归模型应用于算法交易的可行性。与二分类模型不同,回归模型能够通过量化价格的预期波动幅度,构建灵活性更强的交易策略。