English Русский Deutsch 日本語
preview
从新手到专家:使用 MQL5 制作动画新闻标题 (三) — 指标洞察

从新手到专家:使用 MQL5 制作动画新闻标题 (三) — 指标洞察

MetaTrader 5示例 |
20 0
Clemence Benjamin
Clemence Benjamin

目录:

  1. 概述
  2. 概念
  3. 实现
  4. 测试
  5. 结论
  6. 关键教训
  7. 附件


概述

今天,我们推出一个新的指标洞察通道 —— 一个基于规则的图表功能,旨在补充我们在前几集( )中探索的工具。如果你现在还没有注意到,核心目标很明确:优化 MetaTrader 5 终端界面,直接在图表中紧凑高效地访问基本交易资源。

大多数振荡指标传统上都显示在主图表下方的单独子窗口中,这会分割工作区并占用宝贵的像素空间。使用的指标越多,图表就越压缩,从而限制了你清晰地观察价格走势的能力。

为了解决这个问题,我们将通过使用 CCanvas 类集成图表指标洞察通道来简化这些挑战。这使我们能够通过 MQL5 API 获取和处理指标值,并在不干扰界面的情况下显示有意义的信号。我准备了一个可视化示例,说明多个指标子窗口如何缩小主图表视图。

多个指标窗口减少图表空间

此图展示了指标窗口如何影响图表。

在下一部分中,我们将在深入实现之前分解这种方法背后的概念。


概念

我们的计划是默认引入一个单一的滚动通道,显示来自四个关键振荡指标的见解 —— 这些指标为交易者提供关键信号,以指导他们的决策。这种紧凑的设计减少了图表的杂乱,并确保了更清晰、更专注的视图。不过,喜欢更详细信息的用户可以选择将信息展开到单独的通道中,每个通道专门用于一个特定的指标。

深入了解这些指标对于理解它们如何支持健全的交易策略至关重要。设置完成后,您将获得新闻标题、经济日历和实时指标分析 —— 所有这些都整合在一个智能界面中,直接显示在 MetaTrader 5 图表上。

展望未来的更新,我还在考虑增加一个“分析师见解专区”—— 一个专门展示来自专业分析师发布的精选见解的空间。通过访问他们的 API,该功能可以将专家评论和战略观点直接带到图表上,为交易者创建一个强大的、可立即做出决策的显示界面。

现在,为了帮助初学者和经验丰富的交易者,让我们花点时间来探讨一下我们将要整合的四个振荡指标在交易中的常用方法,以及它们结合起来的见解如何能显著增强您的实时决策能力。

了解交易中的 RSI、CCI、随机震荡指标和 MACD:

相对强弱指数 (RSI)

RSI(相对强弱指数)由 J. Welles Wilder 于 1978 年开发,是一种动量震荡指标,用于衡量价格变动的速度和幅度。它主要用于识别超买和超卖情况,以及潜在的趋势逆转。RSI 在区间市场特别有效,价格在支撑位和阻力位之间波动。

计算:

RSI 通常以 14 天为周期进行计算,但交易者可以调整以适应更短或更长的时间周期。公式为:

其中,RSI(相对强弱指标)是指定期间内平均收益与平均损失的比率。平均损益是根据回溯期内的价格变化计算的。

关键水平及解读:  

RSI 指数范围为 0 到 100,中点为 50。

  • 高于 70 的读数被认为是超买,表明该资产可能被高估,需要向下调整。
  • 低于 30 的读数被视为超卖,表明该资产可能被低估,并将出现向上反弹。
  • 值高于 50 通常表示看涨势头,而低于 50 则表示看跌势头。

相对强弱指数(RSI)

相对强度指数(Relative Strength Index)

基于 RSI 的交易策略:  

  • 超买/超卖信号:交易者经常将 RSI 突破 30 视为潜在的买入信号,表明该资产正在走出超卖区域。相反,跌破 70 可能意味着卖出,表明正在走出超买状态。
  • 背离:RSI 指标可以通过背离发出潜在的反转信号。例如,当价格创出新高,但 RSI 指标创出更低的新高时,就会出现看跌背离,这表明动能减弱。当价格创出新低,而 RSI 指标创出更高低点时,就会出现看涨背离。
  • 趋势确认:在上升趋势中,RSI 指标通常应保持在 50 以上;而在下降趋势中,RSI 指标通常应保持在 50 以下,这有助于交易者确认趋势方向。
  • 失败的波动:威尔德将“失败波动”视为市场反转的强烈信号,例如 RSI 在达到 76 后未能突破 70,然后跌破 72,这预示着潜在的反转。

应用示例:

如果 RSI 指标在超卖区域(低于 30)之后向上突破 30,则可能发出买入机会,尤其是在伴随其他看涨指标(如移动平均线交叉)的情况下。反之,如果 RSI 在超买后跌破 70,则可能发出卖出信号。

商品通道指数 (CCI)

CCI 是一种动量震荡指标,最初旨在识别商品的周期性转折,但现在已应用于包括股票和货币在内的各种资产类别。它衡量当前价格水平相对于给定时期内平均价格水平的相对程度,帮助交易者识别超买/超卖情况和趋势强度。它是由唐纳德·兰伯特于 1980 年提出的。

计算:

CCI 通常按 20 个周期数的时间周期计算,但可以进行调整。公式为:

其中:

Typical Price = (High + Low + Close) / 3
SMA = 指定周期内典型价格(Typical Price)的简单移动平均值
Mean Deviation = 典型价格与简单移动平均线绝对偏差的平均值

为了便于阅读,使用系数 0.015 对结果进行缩放。

关键水平及解读:  

  • CCI 在零附近波动,没有上限或下限。
  • 读数高于 +100 表示超买状态,提示可能存在卖出机会。
  • 读数低于 -100 表示超卖情况,提示存在潜在的买入机会。
  • 在强劲的趋势中,CCI 可以超过 +200 或 -200,表明动能极大。

商品通道指数(CCI)

商品通道指数

值得注意的是,当商品通道指数 (CCI) 跌破 -100 或突破 +100 时,并不一定意味着立即出现交易机会。通常,在执行订单之前,其他指标或价格行为分析的确认是必不可少的。例如,在上面的例子中,即使 CCI 跌破 -100,价格在反转方向之前仍然继续下跌了几个点。

这种行为并非 CCI 所独有;其他振荡指标,如随机振荡指标,也会出现类似的模式,尤其是在其预定义的阈值水平附近。虽然这些交叉信号可能很有价值,但单独依赖它们可能会导致过早入场。更稳健的方法是将振荡指标信号与额外的技术确认相结合,以加强决策。

基于 CCI 的交易策略:  

  • 超买/超卖信号:CCI 指数高于 +100 可能预示着潜在的卖出机会,而低于 -100 则可能预示着买入机会。交易者通常会等待 CCI 指数回落至 +100 下方或 -100 上方来确认信号。
  • 趋势强度:持续高于 +100 表明强劲的上升趋势,而低于 -100 则表明强劲的下降趋势。这可以帮助交易者更长时间地坚持跟随趋势。
  • 背离:与 RSI 类似,CCI 可以通过背离发出潜在的反转信号,例如价格创出新高而 CCI 创出更低的新高,表明动能减弱。
  • 交叉:一些交易者使用 CCI 指标与零线的交叉作为趋势信号,向上交叉表示看涨势头,向下交叉表示看跌势头。

应用示例:

如果 CCI 向上突破 +100,可能预示着强劲的上升趋势,但如果 CCI 开始下降并再次跌破 +100,交易者就应该注意趋势反转。同样,如果 CCI 低于 -100,但开始上升并突破 -100,则可能发出买入机会。

随机振荡指标

随机振荡指标是一种基于动量的指标,旨在通过比较交易品种的收盘价与其最近的交易区间来突出市场行为的潜在转折点。通常设置为 14 个周期的窗口,它在发现超买和超卖情况方面尤其有效。通过关注价格变化率,它旨在预测趋势反转的发生。

这一强大的工具由 George Lane 于 20 世纪 50 年代引入,其原理至今仍在指导交易者寻找市场动能转变的早期线索。

计算:

随机振荡指标由两条线组成:%K(快线)和 %D(慢线)。%K 线的计算方法如下:

其中:

Close = 当前收盘价
Lowest Low = 指定期间内的最低低点
Highest High = 指定时间段内的最高峰值

%D 线是 %K 的移动平均值,通常为 3 周期简单移动平均值,以平滑波动。

关键水平及解读:  

  • 随机震荡指标的取值范围为 0 到 100。
  • 读数高于 80 即被视为超买,表明存在潜在的卖出机会。
  • 读数低于 20 表示超卖,表明存在潜在的买入机会。
  • %D 线作为信号线,%K 线和 %D 线的交叉提供交易信号。

随机振荡指标

随机振荡指标(Stochastic Oscillator)

基于随机振荡指标的交易策略:  

  • 超买/超卖信号:交易员们将 %K 向上突破 20 视为潜在的买入信号,表明该资产正在脱离超卖区域。相反,跌破 80 可能发出卖出信号,表明市场处于超买状态。
  • 交叉:当 %K 向上穿过 %D 时,尤其是在超卖区域(低于 20)中,就会出现看涨信号。当 %K 向下穿过 %D 时,尤其是在超买区域(高于 80)中,就会出现看跌信号。
  • 背离:随机振荡指标可以通过背离来发出潜在的反转信号,例如,当价格创出更低的低点,而 %K 创出更高的低点时,就出现了看涨背离,这表明下跌动能减弱。
  • 趋势确认:在上升趋势中,随机振荡指标通常应保持在 50 以上;而在下降趋势中,随机振荡指标通常应保持在 50 以下,这有助于确认趋势方向。

应用示例:

如果 %K 向上穿过 %D,而两者都低于 20,则可能发出强烈的买入信号,尤其是在伴随其他看涨信号(如突破阻力位)的情况下。反之,如果 %K 在 80 以上时向下穿过 %D,则可能发出卖出信号,表明可能从超买状态反转。

移动平均收敛/发散指标 (MACD)

MACD 是一种广泛使用的趋势跟踪动量指标,它通过分析两条 EMA 之间的差异来比较短期和长期价格趋势。它有助于检测市场动量、趋势方向和潜在进入或退出点的变化,使其成为许多技术交易系统的重要组成部分。

MACD 由 Gerald Appel 于 20 世纪 70 年代末开发,至今仍是交易者用来识别趋势强度和可能反转的最值得信赖的工具之一。

计算:

MACD 的计算方法是用 12 个周期的 EMA 减去 26 个周期 EMA:

然后,将 MACD 线的 9 周期 EMA 绘制为“信号线”。MACD 线和信号线之间的差异通常显示为直方图,直观地表示动量强度。

关键水平及解读:  

  • MACD 围绕零值波动,没有上限或下限。
  • MACD 值为正值表示看涨势头强劲,而值为负值表示看跌势头强劲。
  • MACD 线与信号线交叉提供交易信号:MACD 线向上穿过信号线时为看涨信号,向下穿过信号线时为看跌信号。
  • 零轴交叉也具有重要意义:向上交叉零轴表示潜在的上升趋势,向下交叉零轴表示潜在的下降趋势。

移动平均收敛/发散

移动平均收敛/发散指标(MACD)

基于 MACD 的交易策略:  

  • 交叉:交易者在 MACD 线越过信号线时买入,表明看涨势头,在 MACD 线上越过信号线下方时卖出,表明看跌势头。
  • 零线交叉:MACD 指标上穿零轴表明可能出现上升趋势,而下穿零轴则表明可能出现下降趋势,可用于确认趋势。
  • 直方图分析:直方图的高度反映了动量强度。直方图变宽表明动能增强,而直方图变窄则表明动能减弱,可能预示着趋势反转。
  • 背离:MACD 可以通过背离发出潜在的反转信号,例如,当价格创出更低的低点,而 MACD 创出更高的低点时,就出现了看涨背离,这表明下跌动能减弱。

应用示例:

如果 MACD 线向上穿过信号线,并且直方图变宽,则可能发出买入信号,尤其是在突破关键阻力位的情况下。相反,如果 MACD 线向下穿过信号线且直方图变窄,则可能发出卖出信号,表明可能出现反转。

指标 用途 关键水平 主要信号 最佳应用
RSI 衡量动量并识别超买/超卖情况 >70(超买),<30(超卖),50(中点) 向上突破 30(买入),向下突破 70(卖出),背离,失败波动 区间震荡市场
CCI 识别周期性转折点和趋势强度 >+100(超买),<-100(超卖),零线 在 +100 上方交叉(卖出),在 -100 下方交叉(买入),背离,零线交叉 趋势市场
随机振荡指标 衡量动量并识别潜在反转 >80(超买),<20(超卖) %K/%D交叉点(当 %K 向上穿过低于 20 的 %D 时买入,当 %K 向下穿过高于 80 的 %D 时卖出),背离 横盘整理和趋势市场
MACD 指标 趋势跟踪和动量指标 零线、信号线交叉 MACD线向上穿过信号线(买入),向下穿过信号线(卖出),零轴交叉,直方图变化 趋势市场
我们对一些最常用的指标进行了更深入的探索,在下一步中,我们将深入研究代码,以了解这些概念是如何详细实现的。



实现

可以通过“句柄 → 缓冲区 → 释放”三步序列获得当前图表上显示的交易品种和时间周期的内置指标值。首先,通过调用相关的 MQL5 函数(例如 iRSI 或 iMACD)来创建指标句柄,同时省略显式交易品种和时间周期参数,以便使用图表的上下文。接下来,对该句柄调用 CopyBuffer,从一个或多个指标的输出缓冲区中提取最新值。最后调用 IndicatorRelease 来释放句柄和相关资源。将这些步骤封装在辅助例程中,可确保高效、按需检索 RSI、MACD、随机振荡指标、CCI 或任何其他标准指标,而无需生成额外的图表窗口。

以下步骤概述了将指标洞察功能集成到 News Headline EA 的过程,并实际演示了如何使用 MQL5 与内置指标配合使用。

将指标洞察整合到 EA 交易中

1.用户输入声明

通过将 InpSeparateLanesInpInsightSpeed 与其他输入一起显示,您可以让交易者选择是否查看组合指标的单个滚动通道。

input bool   InpSeparateLanes    = false; // combined vs separate insights
input int    InpInsightSpeed     = 3;     // scroll speed for insight text

2.全局变量和画布句柄

我们事先会声明合并画布和单个画布。它们的滚动偏移量驱动动画。在 MQL5 中,画布句柄必须全局保存,以便在定时器回调后仍然存在。通过将这些句柄与其他状态变量(如图表宽度和重新加载时间戳)一起组织起来,我们将所有跨分时报价状态保存在一个地方。

//--- Globals ---------------------------------------------
CCanvas   combinedCanvas;        // holds all four insights in one lane
CCanvas   rsiCanvas, stochCanvas, macdCanvas, cciCanvas;  // separate lanes
int       offCombined, offRSI, offStoch, offMACD, offCCI;

3.指标计算辅助工具

每个辅助函数都遵循“句柄 → 缓冲区 → 释放”模式,确保我们每个指标句柄在每个周期只构建一次,读取最新值,然后立即释放系统资源。集中进行格式设置可以保持主绘图循环的简洁性和高性能。将四个信号合并成一个字符串以实现组合通道模式,可以进一步简化渲染逻辑。

//+------------------------------------------------------------------+
//| Compute indicator insights                                       |
//+------------------------------------------------------------------+
string ComputeRSIInsight()
{
  int h=iRSI(NULL,PERIOD_CURRENT,14,PRICE_CLOSE);
  if(h==INVALID_HANDLE) return "["+Symbol()+"] RSI err";
  double b[]; CopyBuffer(h,0,1,1,b); IndicatorRelease(h);
  double v=b[0]; string s=DoubleToString(v,1);
  string m=v<30?"Oversold("+s+")":v>70?"Overbought("+s+")":"Neutral("+s+")";
  return "["+Symbol()+"] RSI:"+m;
}

string ComputeStochInsight()
{
  int h=iStochastic(NULL,PERIOD_CURRENT,14,3,3,MODE_SMA,STO_LOWHIGH);
  if(h==INVALID_HANDLE) return "["+Symbol()+"] Stoch err";
  double b[]; CopyBuffer(h,0,1,1,b); IndicatorRelease(h);
  double v=b[0]; string s=DoubleToString(v,1);
  string m=v<20?"Oversold("+s+")":v>80?"Overbought("+s+")":"Neutral("+s+")";
  return "["+Symbol()+"] Stoch:"+m;
}

string ComputeMACDInsight()
{
  int h=iMACD(NULL,PERIOD_CURRENT,12,26,9,PRICE_CLOSE);
  if(h==INVALID_HANDLE) return "["+Symbol()+"] MACD err";
  double m[],g[]; CopyBuffer(h,0,1,1,m); CopyBuffer(h,1,1,1,g); IndicatorRelease(h);
  double d=m[0]-g[0]; string s=DoubleToString(d,2);
  string m2=d>0?"Bull("+s+")":d<0?"Bear("+s+")":"Neu(0)";
  return "["+Symbol()+"] MACD:"+m2;
}

string ComputeCCIInsight()
{
  int h=iCCI(NULL,PERIOD_CURRENT,14,PRICE_TYPICAL);
  if(h==INVALID_HANDLE) return "["+Symbol()+"] CCI err";
  double b[]; CopyBuffer(h,0,1,1,b); IndicatorRelease(h);
  double v=b[0]; string s=DoubleToString(v,1);
  string m=v<-100?"Oversold("+s+")":v>100?"Overbought("+s+")":"Neutral("+s+")";
  return "["+Symbol()+"] CCI:"+m;
}

string ComputeAllInsights()
{
  return ComputeRSIInsight() + "  |  " +
         ComputeStochInsight() + "  |  " +
         ComputeMACDInsight() + "  |  " +
         ComputeCCIInsight();
}

4.在 OnInit 中创建画布

在 OnInit 中,我们连接新的通道。在独立通道模式下,我们初始化四个画布;在组合通道模式下,只有一个画布,并带有静态的 “Indicator Insights:” 标签。调用初始更新可确保即使在第一个计时器滴答之前,交易者也能看到上下文 —— 这是加载大型 EA 时一个重要的可用性细节。

int OnInit()
{
  // … existing canvases for events & news …

  if(InpSeparateLanes)
  {
    rsiCanvas.CreateBitmapLabel("RsiC",0,0,canvW,lineH);
    stochCanvas.CreateBitmapLabel("StoC",0,0,canvW,lineH);
    macdCanvas.CreateBitmapLabel("MacC",0,0,canvW,lineH);
    cciCanvas.CreateBitmapLabel("CciC",0,0,canvW,lineH);
    // set transparency…
  }
  else
  {
    combinedCanvas.CreateBitmapLabel("AllC",0,0,canvW,lineH);
    combinedCanvas.TransparentLevelSet(120);
    // static label at x=5: “Indicator Insights:”
    combinedCanvas.FontSizeSet(-120);
    combinedCanvas.TextOut(5, (lineH-combinedCanvas.TextHeight("Indicator Insights:"))/2,
                           "Indicator Insights:", XRGB(200,200,255), ALIGN_LEFT);
    combinedCanvas.Update(true);
  }

  // … remainder of OnInit …
}

5.OnTimer 中的滚动逻辑

这是 EA 的核心:每个计时器滴答都会重新定位画布、重新加载数据、处理任何图表大小调整,然后对每个通道(无论是事件、新闻还是指标)运行计算和绘制周期。通过在最后批量处理所有更新调用,我们可以最大限度地减少闪烁,并保持图层之间的滚动完美同步。使用辅助函数来包装偏移量,使代码保持 DRY(Don't Repeat Yourself,不要重复自己)。

//+------------------------------------------------------------------+
//| OnTimer: redraw                                                  |
//+------------------------------------------------------------------+
void OnTimer()
{
  // reposition canvases
  SetCanvas("EvC",InpPositionTop,InpTopOffset);
  SetCanvas("NwC",InpPositionTop,InpTopOffset+3*lineH);

  if(InpSeparateLanes)
  {
    SetCanvas("RsiC",InpPositionTop,InpTopOffset+4*lineH);
    SetCanvas("StoC",InpPositionTop,InpTopOffset+5*lineH);
    SetCanvas("MacC",InpPositionTop,InpTopOffset+6*lineH);
    SetCanvas("CciC",InpPositionTop,InpTopOffset+7*lineH);
  }
  else
  {
    SetCanvas("AllC",InpPositionTop,InpTopOffset+4*lineH);
  }

  // refresh data
  ReloadEvents();
  FetchAlphaVantageNews();

  // resize if needed
  int wNew=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
  if(wNew!=canvW)
  {
    canvW=wNew;
    ObjectSetInteger(0,"EvC",OBJPROP_WIDTH,canvW);
    ObjectSetInteger(0,"NwC",OBJPROP_WIDTH,canvW);
    if(InpSeparateLanes)
    {
      ObjectSetInteger(0,"RsiC",OBJPROP_WIDTH,canvW);
      ObjectSetInteger(0,"StoC",OBJPROP_WIDTH,canvW);
      ObjectSetInteger(0,"MacC",OBJPROP_WIDTH,canvW);
      ObjectSetInteger(0,"CciC",OBJPROP_WIDTH,canvW);
    }
    else
    {
      ObjectSetInteger(0,"AllC",OBJPROP_WIDTH,canvW);
    }
  }

  // draw events
  DrawAll();

  // draw news
  newsCanvas.Erase(ARGB(170,0,0,0));
  string nt = totalNews>0?newsHeadlines[0]:placeholder;
  newsCanvas.TextOut(offNews,(lineH-newsCanvas.TextHeight(nt))/2,
                     nt,XRGB(255,255,255),ALIGN_LEFT);
  offNews-=InpNewsSpeed;
  if(offNews+newsCanvas.TextWidth(nt)<-20) offNews=canvW;

  // draw insights
  if(InpSeparateLanes)
  {
    string t;
    t=ComputeRSIInsight();
    rsiCanvas.Erase(ARGB(120,0,0,0));
    rsiCanvas.TextOut(offRSI,(lineH-rsiCanvas.TextHeight(t))/2,
                      t,XRGB(180,220,255),ALIGN_LEFT);
    offRSI-=InpInsightSpeed;
    if(offRSI+rsiCanvas.TextWidth(t)<-20) offRSI=canvW;

    t=ComputeStochInsight();
    stochCanvas.Erase(ARGB(120,0,0,0));
    stochCanvas.TextOut(offStoch,(lineH-stochCanvas.TextHeight(t))/2,
                        t,XRGB(180,220,255),ALIGN_LEFT);
    offStoch-=InpInsightSpeed;
    if(offStoch+stochCanvas.TextWidth(t)<-20) offStoch=canvW;

    t=ComputeMACDInsight();
    macdCanvas.Erase(ARGB(120,0,0,0));
    macdCanvas.TextOut(offMACD,(lineH-macdCanvas.TextHeight(t))/2,
                       t,XRGB(180,220,255),ALIGN_LEFT);
    offMACD-=InpInsightSpeed;
    if(offMACD+macdCanvas.TextWidth(t)<-20) offMACD=canvW;

    t=ComputeCCIInsight();
    cciCanvas.Erase(ARGB(120,0,0,0));
    cciCanvas.TextOut(offCCI,(lineH-cciCanvas.TextHeight(t))/2,
                      t,XRGB(180,220,255),ALIGN_LEFT);
    offCCI-=InpInsightSpeed;
    if(offCCI+cciCanvas.TextWidth(t)<-20) offCCI=canvW;
  }
  else
  {
    combinedCanvas.Erase(ARGB(120,0,0,0));
    string txt=ComputeAllInsights();
    combinedCanvas.TextOut(offCombined,(lineH-combinedCanvas.TextHeight(txt))/2,
                           txt,XRGB(180,220,255),ALIGN_LEFT);
    offCombined-=InpInsightSpeed;
    if(offCombined+combinedCanvas.TextWidth(txt)<100) offCombined=canvW;
  }

  // batch update
  eventsCanvas.Update(true);
  newsCanvas.  Update(true);
  if(InpSeparateLanes)
  {
    rsiCanvas.  Update(true);
    stochCanvas.Update(true);
    macdCanvas. Update(true);
    cciCanvas.  Update(true);
  }
  else
  {
    combinedCanvas.Update(true);
  }
}

6.OnDeinit 中的清理

正确的清理操作可以防止出现孤立的位图和残留的计时器。OnInit 中的每个 CreateBitmapLabel 都对应 OnDeinit 中的一个 Destroy 和 ObjectDelete,并且计时器会被终止,以避免任何多余的回调。明确删除所有动态对象(如事件实例)完善了稳健的清理阶段。

//+------------------------------------------------------------------+
//| OnDeinit: cleanup                                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  EventKillTimer();
  eventsCanvas.Destroy(); ObjectDelete(0,"EvC");
  newsCanvas.Destroy();   ObjectDelete(0,"NwC");
  if(InpSeparateLanes)
  {
    rsiCanvas.Destroy();  ObjectDelete(0,"RsiC");
    stochCanvas.Destroy();ObjectDelete(0,"StoC");
    macdCanvas.Destroy(); ObjectDelete(0,"MacC");
    cciCanvas.Destroy();  ObjectDelete(0,"CciC");
  }
  else
  {
    combinedCanvas.Destroy();ObjectDelete(0,"AllC");
  }
  for(int i=0;i<ArraySize(highArr);i++) delete highArr[i];
  for(int i=0;i<ArraySize(medArr);i++)   delete medArr[i];
  for(int i=0;i <ArraySize(lowArr);i++)   delete lowArr[i];
  ArrayResize(newsHeadlines,0);
}

 通过将新组件与上一篇文章中的现有代码适当集成,我们现在有了一个升级版本的程序,该程序具有实时指标洞察功能。在下一节中,我们将介绍这些新添加功能的测试结果,然后总结开发过程中的关键要点和结论。


测试

在 MetaTrader 5 中,您可以从导航器面板的“EA 交易”部分将其拖到图表上进行测试。从 1.04 版本开始,News Headline EA 现在包含了集成指标洞察。下图展示了如何通过 EA 的输入设置,在默认的单通道视图和分离通道视图之间切换。请注意,出于安全考虑,API 密钥已特意留空,使用前应手动输入。

测试指标综合洞察和单独通道的结果。

测试新功能

添加 Alpha Vantage API 密钥后,新闻标题将与我们新集成的指标洞察一起显示,如下所示。

以指标洞察为特色的新闻头条 EA

新闻标题 EA 及其指标洞察

我使用策略测试器测试了 EA,虽然画布通道显示出来了,但没有显示任何数据。这可能是因为所需的信息(例如新闻和指标值)必须实时获取,而测试器并不完全支持这一点。


结论

总而言之,我们成功地将我们的想法变成了现实。我们证明了创建集成式图表工具的可行性,该工具在一个紧凑、易于理解的界面中提供重要的交易信息 —— 经济日历事件、财经新闻标题和基于规则的指标见解。

对于交易者而言,指标洞察的加入尤其有价值,因为它能提供市场状况的即时背景信息,帮助用户做出明智的决策,而无需在多个指标窗口或图表之间切换。这样既能提高效率,又能节省宝贵的屏幕空间。

从开发角度来看,我们加深了对如何使用 MQL5 API 从 MetaTrader 5 的内置指标中检索和操作数据的理解。通过利用 CCanvas 类的灵活性,我们能够以视觉上独特和简化的格式呈现这些数据,从而增强用户体验。该项目展示了 MQL5 中程序化界面定制的强大功能,也为未来的增强铺平了道路,例如分析师见解或用户定义的指标集成,这可能会进一步提高该工具的实用性。

我准备了一个总结表,突出了从这次讨论中吸取的关键经验教训。您还可以在本文末尾找到完整的源代码。欢迎您通过在评论中分享您的想法和反馈来加入对话 —— 您的意见非常宝贵!



关键教训

教训 描述
关注点分离 为事件、新闻和指标洞察使用不同的画布可以提高代码的模块化程度,并允许灵活的布局和样式。
CCanvas 的使用 它能够在图表上流畅地呈现自定义文本和图形,允许在默认 MetaTrader 5 对象之外进行独特的界面增强。
滚动动画逻辑 管理偏移变量有助于创建平滑的水平滚动文本元素 —— 非常适合新闻推送和指标摘要等动态显示。
DRY 原则 创建诸如 SetCanvas 之类的辅助函数,可以避免重复,从而使代码保持简洁、可重用且更易于维护。
API 集成 使用 WebRequest 获取外部数据展示了如何通过金融新闻提供商等第三方服务来扩展 MetaTrader 5。
实时数据约束 经济事件和市场新闻等实时数据通常需要实时访问,这在策略测试器环境中可能不起作用。
使用内置指标 通过访问和解释 RSI、MACD 和 CCI 等标准指标的缓冲区,可以直接在代码中自动生成洞察。
紧凑的用户界面设计 将多个数据流整合到一个可滚动的通道中,有助于减少图表混乱,同时在一个地方提供所有必要信息。
动态画布定位 根据用户偏好和图表尺寸重新定位画布对象,可确保布局的响应性和适应性。
版本控制和功能跟踪 保持清晰的版本号有助于跟踪更改、记录进度,并有效地向用户和开发人员传达更新。


附件

文件 版本 描述 
News Headline EA.mq5 1.04 EA 交易使用内置的 MQL5 Canvas 和 Alpha Vantage API,直接在图表上显示经济日历事件和实时市场新闻标题,以及指标技术见解。

返回目录

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

附加的文件 |
交易策略 交易策略
各种交易策略的分类都是任意的,下面这种分类强调从交易的基本概念上分类。
数据科学和机器学习(第 34 部分):时间序列分解,剖析股票市场的核心 数据科学和机器学习(第 34 部分):时间序列分解,剖析股票市场的核心
在一个充斥着杂乱且不可预测数据的世界里,识别有意义的形态可能颇具挑战性。在本文中,我们将探讨季节性分解,这是一种强力分析技术,有助于把数据拆分为关键成分:趋势、季节性形态、和噪声。以该途径拆解数据,我们能够揭示隐藏的洞见,并配以更清晰、更易解读的信息工作。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
用Python构建一个远程外汇风险管理系统 用Python构建一个远程外汇风险管理系统
我们将用Python构建一个远程外汇风险管理系统,并逐步将其部署到服务器上。在本文中,我们将学习如何通过编程管理外汇风险,以及如何避免外汇账户资金再次损失殆尽。