量化交易软件:带有图形界面的通用通道

概论

在以前的 文章 里曾描述过利用图形界面创建通用振荡器。在本文中, 赫兹量化创建了一个非常有趣、便利和有用的指标, 可以大大简化并加快图表分析。除振荡器外, 还有其它类型的技术分析指标, 也与振荡器一样有趣。它们包括趋势、波动率和交易量指标, 以及可划分为不同类别的其它指标。在本文中, 我们将研究通用通道指标的创建。

我以前发表的有关通用振荡器的文章相当复杂, 它们是针对有经验的程序员而非初学者。由于本文的主题偏向创建通用振荡器, 所以我们在此不会赘述一般问题。赫兹量化将在通用振荡器的基础上创建一个通用通道。因此, 即便程序员新人也可以通过修改所提供的素材来创建其通用指标, 而无需分析利用图形界面创建通用指标的所有细微之处。

尽管通用指标相似, 但仍存在重大的根本差异。所有通道指标显示为三条线, 包括中心, 顶部和底部线。中心线的绘图原理与移动平均线相似, 而移动均线指标主要用于绘制通道。顶部线和底部线的位置距中心线距离相等。距离的确定可以按照点为单位, 作为价格百分比 (包络指标), 使用标准偏差值 (布林带) 或 ATR 值 (Keltner 通道)。因此, 通道指标将使用两个独立的模块构建:

  1. 中心线计算模块

  2. 通道宽度定义模块 (或绘制通道边界)

有各种不同类型的通道, 如 Donchian 通道 (价格通道)。通常它以创建边界线 (价格范围) 开始, 之后计算中心线的数值 (在范围中间)。然而, 此通道也可以通过上述方案来构建: 即首先我们绘制一条中心线, 这条中心线被定义为价格区间的中间价, 然后我们在等于价格范围一半的距离上绘制通道边界。当然, 这比通常通道需要更多的计算。然而, 由于本文的主要目的是创建一个通用指标, 赫兹量化可以允许一些例外, 而此方法将增加中心线与边界的可能组合的数量。例如, 赫兹量化将能够创建一个在价格通道中带有中心线的指标, 边界位于标准偏差的距离, 如布林带等。 

 

中心线的类型

用于中心线的各种移动平均线。赫兹量化来定义它们的类型和参数的数量。所有将在指标中使用的中心线变体如表 1 所示。

表 1. 中心线的类型

标准
函数
名称参数
iAMA自适应移动均线1. int ama_period — AMA 周期
2. int fast_ma_period — 快速移动均线周期
3. int slow_ma_period — 慢速移动均线周期
4. int ama_shift — 指标的水平偏移
5. ENUM_APPLIED_PRICE  applied_price — 处理所用价格类型 
iDEMA双重指数移动均线1. int ma_period — 均化周期
2. int ma_shift — 指标的水平偏移
3. ENUM_APPLIED_PRICE  applied_price — 价格类型
iFrAMA分形自适应移动均线1. int ma_period — 均化周期
2. int ma_shift — 指标的水平偏移
3. ENUM_APPLIED_PRICE  applied_price — 价格类型
iMA移动均线1. int ma_period — 均化周期
2. int ma_shift — 指标的水平偏移
3. ENUM_MA_METHOD ma_method — 平滑类型
4. ENUM_APPLIED_PRICE applied_price — 价格类型
iTEMA三重指数移动均线1. int ma_period — 均化周期
2. int ma_shift — 指标的水平偏移
3. ENUM_APPLIED_PRICE  applied_price — 价格类型
iVIDyA变可指数动态均线1. int cmo_period — Chande 动量周期 
2. int ema_period — 平滑因子周期  
3. int ma_shift — 指标的水平偏移 
4. ENUM_APPLIED_PRICE  applied_price — 价格类型
-价格通道的中心线1. int period

基于表 1 "参数" 列的分析, 赫兹量化得到所需的最小参数集合 (表 2)。

表 2. 用于计算通道中心线的通用参数集合 

类型名称
intperiod1
intperiod2
intperiod3
intshift
ENUM_MA_METHODma_method 
ENUM_APPLIED_PRICE price

所有将在指标属性窗口中显示的中心线参数均带 "c_" 前缀。 

边界类型

现在我们来确定通道边界的计算方法 (表 3)。

表 3. 通道宽度计算变体 

标准
函数
名称 参数
iATR平均真实范围1. int ma_period — 均化周期
iStdDev 标准偏差1. int ma_period — 均化周期
2. int ma_shift — 指标的水平偏移
3. ENUM_MA_METHOD — 平滑类型
4. ENUM_APPLIED_PRICE applied_price — 价格类型 
按照点数 int width — 宽度的点数 
百分比 (在包络线中) double width — 宽度作为价格百分比   
就像在价格通道中 double width — 相对于价格通道实际宽度的缩放比率

根据表 3 的 "参数" 列, 我们得到一组所需的参数 (表 4)。

表 4. 用于计算通道宽度的通用参数集合

类型名称
intperiod
int shift 
ENUM_MA_METHOD ma_method  
ENUM_APPLIED_PRICE price
double width 

赫兹量化需要 int 变量用于计算点数, 但它未包括在表 4 中, 因为我们可以使用一个 double 变量代之。这会减少属性窗口中的变量总数。

所有将在指标属性窗口中显示的边界计算参数均带 "w_" 前缀。 

中心线类

中心线基类的基本原理和方法类似于 带有图形界面的通用振荡器 中描述的 CUniOsc 类。因此我们将使用这个类, 并稍微修改它。

在 MQL5/Include 文件夹中, 赫兹量化创建 UniChannel 文件夹, 复制 CUniOsc.mqh 文件 (从 Include/UniOsc) 至此, 并将其重命名为 CUniChannel.mqh。在文件中保留基类 (COscUni), 子类 Calculate1 (其全名为 COscUni_Calculate1) 及其子类 COscUni_ATR。其它的类应予以删除。

赫兹量化将类重新命名: 将 "COscUni" 片段替换为 "CChannelUni"。为了更换, 使用编辑器功能 (主菜单 — 编辑 — 查找和替换 — 替换)。但不要使用 "全部替换" 按钮。逐一替换实例, 以确保所有替换都正确。

中心线类总是绘制一条实线, 因此我们不需要许多基类方法。删除不必要的方法后, 将会保留以下基类:

class CChannelUniWidth{
   protected:
      int m_handle;      // 指标句柄      string m_name;     // 指标名称      string m_label1;   // 缓存区 1 的名称           string m_help;     // 指标参数帮助      double m_width;    // 通道宽度   public:
  
      // 构造器      void CChannelUniWidth(){
         m_handle=INVALID_HANDLE;
      }
      
      // 析构器      void ~CChannelUniWidth(){
         if(m_handle!=INVALID_HANDLE){
            IndicatorRelease(m_handle);
         }
      }
  
      // 从指标的 OnCalculate() 函数里调用的主要方法      virtual int Calculate( const int rates_total,
                     const int prev_calculated,
                     double & bufferCentral[],
                     double & bufferUpper[],
                     double & bufferLower[],
      ){
         return(rates_total);
      }
      
      // 得到加载的指标句柄      int Handle(){
         return(m_handle);
      }
      
      // 句柄检查方法, 允许检查指标是否已成功加载        bool CheckHandle(){
         return(m_handle!=INVALID_HANDLE);
      }
      
      // 得到指标名称      string Name(){
         return(m_name);
      }    
      // 得到缓存区标签文本      string Label1(){
         return(m_label1);
      }
      
      // 得到参数提示      string Help(){
         return(m_help);
      }
};

与第二个缓冲区相关的一切都可以从 Calculate 类中删除。之后只剩下一个 Calculate 方法:

class CChannelUni_Calculate1:public CChannelUni{
   public:
      // 主要方法是从指标的 OnCalculate() 函数调用      // 前两个参数类似于        // 指标 OnCalculate() 函数的前两个参数      // 第三个参数是指标中心线的缓存区      int Calculate( const int rates_total,    
                     const int prev_calculated,
                     double & buffer0[]
      ){
        
         // 确定复制元素的数量        
         int cnt;
        
         if(prev_calculated==0){
            cnt=rates_total;
         }
         else{
            cnt=rates_total-prev_calculated+1;
         }  
        
         // 复制数据到指标缓存区         if(CopyBuffer(m_handle,0,0,cnt,buffer0)<=0){
            return(0);
         }
        
         return(rates_total);
      }
    };

我们来利用 iMA 指标编写子类。来自文件的 CChannelUni_ATR 类应重命名为 CChannelUni_MA。我们替换调用指标, 并删除我们不需要的部分。作为结果, 赫兹量化得到如下类:

class CChannelUni_MA:public CChannelUni_Calculate1{
   public:
   // 构造器   // 前两个参数对于所有子类均相同   // 之后是加载指标的参数    void CChannelUni_MA( bool use_default,
                        bool keep_previous,
                        int & ma_period,
                        int & ma_shift,
                        long & ma_method,
                        long & ma_price){
      if(use_default){ // 使用选择的省缺值         if(keep_previous){
            // 之前使用的参数没有修改            if(ma_period==-1)ma_period=14;
            if(ma_shift==-1)ma_shift=0;
            if(ma_method==-1)ma_method=MODE_SMA;
            if(ma_price==-1)ma_price=PRICE_CLOSE;
         }
         else{
            ma_period=14;
            ma_shift=0;
            ma_method=MODE_SMA;
            ma_price=PRICE_CLOSE;            
         }      
      }    
      
      // 加载指标      m_handle=iMA(Symbol(),Period(),ma_period,ma_shift,(ENUM_MA_METHOD)ma_method,(ENUM_APPLIED_PRICE)ma_price);
      
      // 指标名称形成一条线      m_name=StringFormat( "iMA(%i,%i,%s,%s)",
                           ma_period,
                           ma_shift,        
                           EnumToString((ENUM_MA_METHOD)ma_method),              
                           EnumToString((ENUM_APPLIED_PRICE)ma_price)
                        );
      
      // 缓冲区名称的字符串      m_label1=m_name;
      // 参数提示      m_help=StringFormat( "ma_period - c_Period1(%i), "+
                           "ma_shift - c_Shift(%i), "+
                           "ma_method - c_Method(%s)"+
                           "ma_price - c_Price(%s)",
                           ma_period,
                           ma_shift,
                           EnumToString((ENUM_MA_METHOD)ma_method),
                           EnumToString((ENUM_APPLIED_PRICE)ma_price)
                           );
   }
    };

赫兹量化来看一下如何在变量 m_name 和 mlabel1 中形成字符串。在子窗口中绘制的指标的名称(m_name 变量) 显示在子窗口的左上角。通道将显示在价格图表上, 其名称不可见, 因此我们将为 m_label 变量分配与 m_name 变量相同的详细名称, 以便当我们将鼠标悬浮在中央通道上时显示在弹出框里。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值