价格表示的准确性和变化步长

前面,我们已经遇到了图表工作交易品种的两个相互关联的特性:最小价格变化步长()和以小数位数表示的价格表示准确性(位数)。二者在 预定义变量中也是可用的。要获取任意交易品种的相似特性,应分别查询 SYMBOL_POINT 和 SYMBOL_DIGITS 特性。SYMBOL_POINT 特性与最小价格变化(在 MQL 程序中称为 SYMBOL_TRADE_TICK_SIZE 特性)及其值 (SYMBOL_TRADE_TICK_VALUE) 密切相关,通常以交易账户的货币表示(但有些交易品种可以配置为使用基础货币;如有必要,你可以联系你的经纪商了解详情)。下表显示了所有这些特性。

标识符

说明

SYMBOL_DIGITS

小数位数

SYMBOL_POINT

报价货币中一个点的值

SYMBOL_TRADE_TICK_VALUE

SYMBOL_TRADE_TICK_VALUE_PROFIT 的值

SYMBOL_TRADE_TICK_VALUE_PROFIT

盈利头寸的当前分时报价值

SYMBOL_TRADE_TICK_VALUE_LOSS

亏损头寸的当前分时报价值

SYMBOL_TRADE_TICK_SIZE

以报价货币表示的最小价格变化

除 SYMBOL_DIGITS 之外的所有特性都是实数,并使用 SymbolInfoDouble 函数请求。SYMBOL_DIGITS 特性可通过 SymbolInfoInteger 获得。为了测试使用这些特性的工作,我们将使用现成的类 SymbolFilter SymbolMonitor,它们将用于自动为任何特性调用所需的函数。

我们还可以通过添加 select 方法的新重载来改进 SymbolFilter 类,该方法不仅能够用合适交易品种的名称填充一个数组,还能够用其特定特性值填充另一个数组。

在更普遍的情况下,我们可能同时对每个交易品种的几个特性感兴趣,因此建议不要对输出数组使用内置数据类型,而是使用具有不同字段的特殊复合类型。

在编程中,这种类型被称为元组,在某种程度上相当于 MQL5 结构体。

template<typename T1,typename T2,typename T3// we can describe up to 64 fields
struct Tuple3                                 // MQL5 allows 64 template parameters
{
   T1 _1;
   T2 _2;
   T3 _3;
};

但是,此类结构体需要所有字段的初步说明,而我们事先不知道所请求交易品种特性的数量和列表。因此,为了简化代码,我们将元组表示为接收查询结果的动态数组的第二维向量。

T array[][S];

作为数据类型 T ,我们可以使用任何用于特性的内置类型和枚举。大小 S 必须与请求的特性数量相匹配。

实际上,这种简化将我们限制在一个查询中只能查询相同类型的值,也就是说,只能查询整数、实数或字符串。但是,筛选条件可以包括任何特性。稍后,我们将使用其他交易实体的筛选示例来实现元组方法,包括订单、交易和 头寸

因此,新版本的 SymbolFilter::select 方法将对 property 数组的引用作为输入,该数组带有要从筛选后的交易品种中读取的特性标识符。交易品种本身的名称和这些特性的值将被写入 symbolsdata 输出数组。

   template<typename E,typename V>
   bool select(const bool watchconst E &property[], string &symbols[],
      V &data[][], const bool sort = falseconst
   {
      // the size of the array of requested properties must match the output tuple
      const int q = ArrayRange(data1);
      if(ArraySize(property) != qreturn false;
      
      const int n = SymbolsTotal(watch);
      // iterate over characters
      for(int i = 0i < n; ++i)
      {
         const string s = SymbolName(iwatch);
         // access to the symbol properties is provided by the monitor
         SymbolMonitor m(s);
         // check all filter conditions
         if(match(mlongs)
         && match(mdoubles)
         && match(mstrings))
         {
            // properties of a suitable symbol are written to arrays
            const int k = EXPAND(data);
            for(int j = 0j < q; ++j)
            {
               data[k][j] = m.get(property[j]);
            }
            PUSH(symbolss);
         }
      }
 
      if(sort)
      {
         ...
      }
      return true;
   }

此外,新方法可以按照第一维度(请求的第一个特性)对输出数组进行排序:该功能留给读者使用源代码独立研究。要启用排序,请将 sort 参数设置为 true。带有交易品种名和数据的数组排序一致。

当只需要从筛选的字符中请求一个特性时,为了避免调用代码中的元组,在 SymbolFilter 中实现了下面的 select 选项:在其内部,我们在第二维度中定义了大小为 1 的特性 (properties) 和值 (tuples) 的中间数组,用于调用上面的完整版本的 select

   template<typename E,typename V>
   bool select(const bool watchconst E propertystring &symbols[], V &data[],
      const bool sort = falseconst
   {
      E properties[1] = {property};
      V tuples[][1];
      
      const bool result = select(watchpropertiessymbolstuplessort);
      ArrayCopy(datatuples);
      return result;
   }

通过使用高级筛选器,我们尝试构建一个按分时报价值 SYMBOL_TRADE_TICK_VALUE 排序的交易品种列表(参见文档 SymbolFilterTickValue.mq5)。假设存款货币为美元,我们应该为以美元报价的外汇金融工具(XXXUSD 类型)获得等于 1.0 的值。对于其他资产,我们将看到非平凡值。

#include <MQL5Book/SymbolFilter.mqh>
   
input bool MarketWatchOnly = true;
   
void OnStart()
{
   SymbolFilter f;      // filter object
   string symbols[];    // array with symbol names
   double tickValues[]; // array for results
   
   // apply the filter without conditions, fill and sort the array
   f.select(MarketWatchOnlySYMBOL_TRADE_TICK_VALUEsymbolstickValuestrue);
   
   PrintFormat("===== Tick values of the symbols (%d) =====",
      ArraySize(tickValues));
   ArrayPrint(symbols);
   ArrayPrint(tickValues5);
}

以下是运行脚本的结果。

===== Tick values of the symbols (13) =====
"BTCUSD" "USDRUB" "XAUUSD" "USDSEK" "USDCNH" "USDCAD" "USDJPY" "NZDUSD" "AUDUSD" "EURUSD" "GBPUSD" "USDCHF" "SP500m"
 0.00100  0.01309  0.10000  0.10955  0.15744  0.80163  0.87319  1.00000  1.00000  1.00000  1.00000  1.09212 10.00000