学习如何基于奥森姆(Awesome)振荡器设计交易系统

Mohamed Abdelmaaboud | 16 一月, 2023

概述

这是我们系列中的新篇章,学习如何作为初学者,如何挖掘事物的根源,并设计基于最流行技术指标的交易系统。 我们将在本文中学习一种新的技术工具,它就是奥森姆(Awesome) 振荡器指标,我们会详细地辨识它,从而了解它是什么、它测量什么、以及如何根据它背后的主要概念在简单的策略里运用它,以及如何基于这些提到的策略创建交易系统。

我们将涵盖该指标的细节,就像我们在以下主题提到的一样:

  1. 奥森姆振荡器定义
  2. 奥森姆振荡器策略
  3. 奥森姆振荡器策略蓝图
  4. 奥森姆振荡器交易系
  5. 结束语

我们将利用 MQL 5(MetaQuotes 语言 5)编写代码,并用 MetaTrader 5 交易终端来执行我们设计的交易系统。 MQL5 已内置在 MetaTrader 5 当中。 如果您想学习如何获取和使用它们,您可以阅读上一篇文章中的在 MetaEditor 中编写 MQL5 代码主题。 我还建议您下载并尝试应用您自己学到的知识,进行练习并提高您的编码技能。

免责声明:所有信息“按原样”提供仅用于教学目的,并非出于交易目的或建议。 这些信息不能保证任何结果。 如果您选择在您的任何交易账户上使用这些材料,您将自行承担风险,您是唯一的责任人。


奥森姆振荡器定义

在本主题中,我们将学习有关奥森姆振荡器(AO)指标的细节。 AO 由比尔·威廉姆斯(Bill Williams)开发,它衡量动量,可澄清买、卖双方的力量或控制权。 它取最后五根柱线(或蜡烛)的动量与更大时间帧内的最后 34 根(或蜡烛)的动量进行比较,换句话说,它取最近的动量与更大时间帧内的动量进行比较。 当我们通过另一个技术指标或工具确认 AO 信号时,它将变得更显著、且更重要。 故此,最好将其与其它技术工具配合使用。 我们如何手工计算这个指标,如此来明了和加深我们对这个指标的理解,如果我们想学习如何做到这一点,我们可以通过以下步骤来达成:

AO 是 5 周期简单移动平均线和 34 周期简单移动平均线之间的差值。 我们将在计算 AO 时使用中位价格。

MEDIAN PRICE = (HIGH + LOW) / 2 

AO = SMA (MEDIAN PRICE, 5) - SMA (MEDIAN PRICE, 34)

其中:

MEDIAN PRICE = 金融产品的中位价格

HIGH = 最高价格

LOW = 最低价格

AO = 奥森姆振荡器数值

SMA = 简单均线

如今,我们不需要再手工计算它,因为它已内置在 MetaTrader 5 当中,作为技术指标功能提供,我们所需做的只是从交易终端中选择它,即可出现在图表上。

以下是将其插入图表的方法。 在打开的 MetaTrader 5 交易终端里,按插入选项卡 --> 指标 --> 比尔·威廉姆斯 --> AO 振荡器

AO 插入

之后,我们可以找到 AO 指标的参数,如下所示:

AO 参数

其中:

1 - 向上值的颜色

2 - 直方图的宽度

3 - 向下值的颜色

判定这些参数后,我们将发现插入到图表中的指标,如下所示:

 AO 指标插入

正如我们在上一张图表中所见,在图表的下半部分,我们有一个指标,直方图条在零轴附近振荡 — 这是动量的度量。


奥森姆振荡器策略

在本主题中,我们仅出于教学目的,学习如何基于指标背后的主要概念,在一些简单策略里运用 AO 指标。 在您的实盘账户上使用它们之前,您必须测试任何策略,以确保它是有用的、有利可图的、并且适合您的交易。 根据这一点,您也许会发现提到的策略需要优化,因为这些策略的主要目的仅出于教学,故您发现这一点很正常。 最好将此指标与其它技术指标配合使用,从而获得更有效的结果,特别是如果我们配合其它技术指标或工具,可为我们提供更多见解,更多不同的视角。 顺便说一下,这是技术分析最重要和最有效的功能之一,因为我们可用许多工具从不同的角度查看和评估底层金融产品,这有助于我们做出相应的投资或交易决策,从而获得优良的结果。 在本文中,我们将结合另一个技术指标,即移动平均线,如同我们将在本主题中看到的那样,以便获得更有效的买入或卖出信号。

策略一: AO 零轴交叉

基于此策略,我们需要根据当期 AO 值与零轴之间的交叉获得看涨或看跌信号。 如果当期 AO 值大于零轴,则为看涨信号。 如果当期 AO 值低于零轴,则为看跌信号。

简而言之,

当期 AO > 0 --> 看涨

当期 AO < 0 --> 看跌

策略二: AO 强度

根据该策略,我们需要基于当期 AO 的位置和最后 AO 值的 5 周期平均值获得 AO 走势强度的信号。 如果当期 AO 值大于均值,则表示 AO 走势强劲。 如果当期 AO 值低于均值,则表示 AO 走势疲软。

简而言之,

当期 AO > AO 的 5 周其均值 --> AO 强劲

当期 AO < AO 的 5 周其均值 --> AO 疲软

策略三:AO & MA 策略

根据此策略,我们为了获得买入和卖出信号,需要基于当期 AO 值相对零轴的位置,此外还需要收盘价相对于 50 周期指数移动平均线的位置。 如果当期 AO 值大于零轴,同时收盘价大于 50 周期均线,则为买入信号。 如果当期 AO 值低于零轴,同时收盘价低于 50 周期均线,则为卖出信号。

简而言之,

当期 AO > 零轴,且 收盘价 > 50-周期 EMA --> 买入信号

当期 AO < 零轴,且 收盘价 < 50-周期 EMA --> 卖出信号

奥森姆振荡器策略蓝图

我们将为每个提到的策略设计一个分步蓝图,来帮助我们规划我们的思路,并轻松创建我们的交易系统。

策略一: AO 零轴交叉

根据这个策略,我们需要创建一个交易系统,该系统能够连续比较两个值,并有基于此生成看涨或看跌信号,它们是当期 AO 值和 AO 指标的零轴,以便判定每个值的位置,并决定市场的状态。 如果 AO 值大于零轴,我们要求交易系统在图表上生成含有以下值的注释:

在另一种场景下,如果当期 AO 值低于零轴,我们要求交易系统在图表上返回含有以下值的注释:

以下是此交易系统的分步蓝图:

算法-交易-系统-蓝图1

策略二: AO 强度

根据此策略,我们需要创建一个交易系统,该系统可连续比较两个值,并基于此生成 AO 走势强度的信号,即当期 AO 和当期 AO 值之前的最后五个 AO 值的平均值,来判定哪个更大。 如果当期 AO 值大于均值,我们要求交易系统返回含有以下值的注释(信号和产生此信号的值):

在另一种场景下,如果当期 AO 值低于平均值,我们要求交易系统返回含有以下值的注释:

以下是该交易系统的分步蓝图:

 算法-交易-系统-蓝图11

策略三:AO & MA 策略

基于我们在上一个主题中学到的相同策略,我们需要创建一个交易系统,该系统可在图表上返回含有相应买入和卖出信号的注释,基于连续比较四个值,它们是:

如果当期 AO 大于零轴,且收盘价大于 50 周期 MA,我们要求交易系统返回以下值作为图表上的注释:

在另一种场景下,如果当期 AO 值低于零轴,收盘价低于 50 周期均线,我们要求交易系统在图表上返回含有以下值的注释:

以下是该交易系统的分步蓝图:

算法-交易-系统-蓝图111

奥森姆振荡器交易系

在本主题中,我们将学习本文中最有趣的内容,因为我们将会为我们拟议的交易策略创建交易系统。 首先,我们将创建一个简单的交易系统,该系统将生成一个含有当期 AO 值的信号作为图表上的注释,我们将以它作为其它交易系统的基础。

以下是如何逐步为这个所需信号创建交易系统:

创建 double 数据类型的数组 aoArray:

double aoArray[];

调用 “ArraySetAsSeries” 函数为 aoArray 设置排序标志 AS_SERIES,返回 true 或 false 作为布尔值。 其参数为:

ArraySetAsSeries(aoArray,true);

调用 “iAO” 函数定义 AO 指标,并返回 AO 振荡器指标的句柄。 其参数为:

int aoDef = iAO(_Symbol,_Period);

调用 “CopyBuffer” 函数从 AO 指标的缓冲区获取数据。 其参数为: 

CopyBuffer(aoDef,0,0,3,aoArray);

在为 aoVal 创建双精度变量后定义 AO 值,并调用 “NormalizeDouble” 对其进行规范化。 "Normalizedouble" 的参数是:

double aoVal = NormalizeDouble(aoArray[0],7);

调用 “Comment” 函数在图表上返回含有当期 AO 值的注释。

Comment("AO Value is ",aoVal);

如此,以下是创建此交易系统的完整代码:

//+------------------------------------------------------------------+
//|                                                    Simple AO.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
  void OnTick()
  {
   double aoArray[];
   ArraySetAsSeries(aoArray,true);
   int aoDef = iAO(_Symbol,_Period);
   CopyBuffer(aoDef,0,0,3,aoArray);
   double aoVal = NormalizeDouble(aoArray[0],7);
   Comment("AO Value is ",aoVal);
  }
//+------------------------------------------------------------------+

编译此代码,并确保没有错误后,我们将在导航器窗口中找到它的智能系统,如下所示:

简单 AO nav

将这个智能系统拖放到所需的图表上,我们将看到该智能系统的窗口,如下所示:

简单 AO 窗口

勾选“允许算法交易”,并按“确定”后,我们会发现智能系统已加载到图表上,如下所示:

简单 AO 加载

正如我们在右上角的图表上所见,我们的智能系统已加载。 现在,我们已准备好接收所需的信号,它将与以下内容相同:

简单 AO 信号

正如我们在上一张图表中所见,我们在左上角得到期望的当期 AO 信号作为注释。

策略一: AO 零轴交叉

我们将基于此策略创建一个交易系统,接收所需信号,它的完整代码将与以下内容相同:

//+------------------------------------------------------------------+
//|                                            AO Zero Crossover.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   double aoArray[];
   ArraySetAsSeries(aoArray,true);
   int aoDef = iAO(_Symbol,_Period);
   CopyBuffer(aoDef,0,0,3,aoArray);
   double aoVal = NormalizeDouble(aoArray[0],7);
   if(aoVal > 0)
     {
      Comment("Bullish","\n"
              "AO Value is ",aoVal);
     }

   if(aoVal < 0)
     {
      Comment("Bearish","\n"
              "AO Value is ",aoVal);
     }
  }
//+------------------------------------------------------------------+

此代码中的区别。

该策略的条件,

看涨情况:

   if(aoVal > 0)
     {
      Comment("Bullish","\n"
              "AO Value is ",aoVal);
     }

看跌情况:

   if(aoVal < 0)
     {
      Comment("Bearish","\n"
              "AO Value is ",aoVal);
     }

编译此代码,并确保没有错误后,我们就能像之前一样把它加载到图表中。 因此,它将如下加载:

AO 零轴交叉加载

正如我们在图表上所见,我们的智能系统加载到图表上,与右上角显示的相同。 现在,我们准备好接收所需的信号。

在看涨信号的情况下:

AO 零轴交叉 - 看涨信号

正如我们在上一张图表中所见,我们在左上角得到一条注释,其中包含以下值:

看跌信号情况:

AO 零轴交叉 - 看跌信号

正如我们在上一张图表中所见,我们在图表上得到一条信号注释,含有以下数值:

如此,在看涨和看跌的情况下,我们基于此策略获得了所需的信号。

策略二: AO 强度

以下是该交易系统的完整代码:

//+------------------------------------------------------------------+
//|                                                  AO Strength.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   double aoArray[];
   ArraySetAsSeries(aoArray,true);
   int aoDef = iAO(_Symbol,_Period);
   CopyBuffer(aoDef,0,0,6,aoArray);


   double aoCurrVal = NormalizeDouble(aoArray[0],6);
   double aoFifthVal = NormalizeDouble(aoArray[1],6);
   double aoFourthVal = NormalizeDouble(aoArray[2],6);
   double aoThirdVal = NormalizeDouble(aoArray[3],6);
   double aoSecondVal = NormalizeDouble(aoArray[4],6);
   double aoFirstVal = NormalizeDouble(aoArray[5],6);

   double aoAvgVal = NormalizeDouble((aoFifthVal+aoFourthVal+aoThirdVal+aoSecondVal+aoFirstVal)/5,6);

   if(aoCurrVal > aoAvgVal)
     {
      Comment("AO Movement is strong","\n",
              "AO CurrVal : ",aoCurrVal,"\n",
              "AO FirstVal : ",aoFifthVal,"\n",
              "AO SecondVal : ",aoFourthVal,"\n",
              "AO ThirdVal : ",aoThirdVal,"\n",
              "AO FourthVal : ",aoSecondVal,"\n",
              "AO FifthVal : ",aoFirstVal,"\n",
              "AO AvgVal : ",aoAvgVal
             );
     }

   if(aoCurrVal < aoAvgVal)
     {
      Comment("AO Movement is Weak","\n",
              "AO CurrVal : ",aoCurrVal,"\n",
              "AO FirstVal : ",aoFifthVal,"\n",
              "AO SecondVal : ",aoFourthVal,"\n",
              "AO ThirdVal : ",aoThirdVal,"\n",
              "AO FourthVal : ",aoSecondVal,"\n",
              "AO FifthVal : ",aoFirstVal,"\n",
              "AO AvgVal : ",aoAvgVal
             );
     }

  }
//+------------------------------------------------------------------+

此代码中的区别:

调用 “NormalizeDouble” 函数,我们将定义以下来自 AO 的前五个值:

   double aoCurrVal = NormalizeDouble(aoArray[0],6);
   double aoFifthVal = NormalizeDouble(aoArray[1],6);
   double aoFourthVal = NormalizeDouble(aoArray[2],6);
   double aoThirdVal = NormalizeDouble(aoArray[3],6);
   double aoSecondVal = NormalizeDouble(aoArray[4],6);
   double aoFirstVal = NormalizeDouble(aoArray[5],6);

定义 AO 的 5 周期均值:

double aoAvgVal = NormalizeDouble((aoFifthVal+aoFourthVal+aoThirdVal+aoSecondVal+aoFirstVal)/5,6);

此策略的条件。

AO 走势强劲情况:

   if(aoCurrVal > aoAvgVal)
     {
      Comment("AO Movement is strong","\n",
              "AO CurrVal : ",aoCurrVal,"\n",
              "AO FirstVal : ",aoFifthVal,"\n",
              "AO SecondVal : ",aoFourthVal,"\n",
              "AO ThirdVal : ",aoThirdVal,"\n",
              "AO FourthVal : ",aoSecondVal,"\n",
              "AO FifthVal : ",aoFirstVal,"\n",
              "AO AvgVal : ",aoAvgVal
             );
     }

AO 走势疲软情况:

   if(aoCurrVal < aoAvgVal)
     {
      Comment("AO Movement is Weak","\n",
              "AO CurrVal : ",aoCurrVal,"\n",
              "AO FirstVal : ",aoFifthVal,"\n",
              "AO SecondVal : ",aoFourthVal,"\n",
              "AO ThirdVal : ",aoThirdVal,"\n",
              "AO FourthVal : ",aoSecondVal,"\n",
              "AO FifthVal : ",aoFirstVal,"\n",
              "AO AvgVal : ",aoAvgVal
             );
     }

编译后,确保没有错误,并加载智能系统。 我们会发现它与以下内容相同:

AO 强度加载

正如我们在右上角的图表上所见,智能系统已加载。

强劲情况:

AO 强度 - 强劲信号

正如我们在左上角的图表上所见,我们得到一条含有以下值的注释:

疲软情况:

AO 强度 - 疲软信号

正如我们在左上角的图表上所见,我们得到一条含有以下值的注释:

现在,我们基于该策略的交易系统获得了所需的信号。

策略三:AO & MA 策略

以下是该交易系统的完整代码。

//+------------------------------------------------------------------+
//|                                             AO & MA Strategy.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates pArray[];
   double aoArray[];
   double maArray[];

   int Data=CopyRates(_Symbol,_Period,0,1,pArray);
   ArraySetAsSeries(aoArray,true);
   ArraySetAsSeries(maArray,true);
   
   int aoDef = iAO(_Symbol,_Period);
   int maDef = iMA(_Symbol,_Period,50,0,MODE_EMA,PRICE_CLOSE);

   CopyBuffer(aoDef,0,0,3,aoArray);
   CopyBuffer(maDef,0,0,3,maArray);

   double closingPrice = pArray[0].close;
   double aoVal = NormalizeDouble(aoArray[0],7);
   double maVal = NormalizeDouble(maArray[0],7);

   if(aoVal > 0 && closingPrice > maVal)
     {
      Comment("Buy","\n"
              "Closing Price is ",closingPrice,"\n",
              "AO Value is ",aoVal,"\n",
              "MA Value is ",maVal);
     }

   if(aoVal < 0 && closingPrice < maVal)
     {
      Comment("Sell","\n"
              "Closing Price is ",closingPrice,"\n",
              "AO Value is ",aoVal,"\n",
              "MA Value is ",maVal);
     }

  }
//+------------------------------------------------------------------+

代码中的差异。

创建 pArray、aoArray 和 maArray 三个数组。 我们为提到的数组定义 double 数据类型,除了 pArray,我们将其定义为 MqlRates 数据结构,该结构存储有关价格、交易量和点差的信息。

   MqlRates pArray[];
   double aoArray[];
   double maArray[];

对于 (aoArray) 和 (maArray) 设置 AS_SERIES 标志,就像我们之前提到的一样。 调用 “CopyRates” 函数定义数据,获取 MqlRates 结构的历史数据,其参数为:

   int Data=CopyRates(_Symbol,_Period,0,1,pArray);
   ArraySetAsSeries(aoArray,true);
   ArraySetAsSeries(maArray,true);

定义 AO、MA:

如前述调用 "iOA" 函数定义 AO 句柄。

调用 "iMA" 函数定义 MA 句柄,其参数:

   int aoDef = iAO(_Symbol,_Period);
   int maDef = iMA(_Symbol,_Period,50,0,MODE_EMA,PRICE_CLOSE);

调用 “CopyBuffer” 函数从 AO 和 MA 指标的缓冲区获取数据。

   CopyBuffer(aoDef,0,0,3,aoArray);
   CopyBuffer(maDef,0,0,3,maArray);

定义收盘价, aoArray, 和 maArray。

   double closingPrice = pArray[0].close;
   double aoVal = NormalizeDouble(aoArray[0],7);
   double maVal = NormalizeDouble(maArray[0],7);

策略的条件。

买入信号的情况

   if(aoVal > 0 && closingPrice > maVal)
     {
      Comment("Buy","\n"
              "Closing Price is ",closingPrice,"\n",
              "AO Value is ",aoVal,"\n",
              "MA Value is ",maVal);
     }

卖出信号情况:

   if(aoVal < 0 && closingPrice < maVal)
     {
      Comment("Sell","\n"
              "Closing Price is ",closingPrice,"\n",
              "AO Value is ",aoVal,"\n",
              "MA Value is ",maVal);
     }

编译并附加此代码后,我们可以看到它加载到图表,并与以下内容相同:

 AO & MA 加载

如我们所见,我们已将指标加载到图表的左上角。 我们已准备就绪接收信号。

买入信号情况:

 AO & MA - 买入信号

如我们所见,我们在左上角得到信号作为注释,含有以下值:

卖出情况:

 AO & MA - 卖出信号

我们看到在此情况下的注释,含有以下值的信号:


结束语

现在,推测您已详细理解了奥森姆振荡器指标,您已学习了什么是 AO、它测量什么、我们如何手工计算它,以及如何从 MetaTrader 5 的内置指标将其插入图表当中。 在明晰它之后,我们还学习了如何基于其背后主要概念在简单策略里运用它,这些策略是:

之后,我们为每个拟议的策略设计了一个分步蓝图,以便组织我们的思路,并轻松、流畅、有效地创建一个交易系统。 然后,我们为每个拟议的策略创建了一个交易系统,以便能在 MetaTrader 5 交易终端中执行它们,并获得自动信号。

我希望您能尝试应用自己学到的知识,因为如果我们需要发展和提升我们的技能,这是任何学习过程中非常重要的一步,此外,这也能令您对所学内容,或任何相关主题有更多见解。 我需要在这里再次确认,您必须在使用之前测试任何提到的策略,并确保它适合您的交易,因为没有任何策略适合所有人。

我希望这篇文章能对您有用,如果您想阅读更多类似的文章,您可以阅读本系列中有关如何基于最流行的技术指标设计交易系统的其它篇章。