DoEasy 函数库中的时间序列(第六十部分):品种即时报价数据的序列列表(基础篇)
📘

DoEasy 函数库中的时间序列(第六十部分):品种即时报价数据的序列列表(基础篇)

第 1/3 篇

◍ 把即时报价塞进一个序列列表

DoEasy 函数库做到第六十部分,核心落点是把任意品种的即时报价(tick)封装成时间序列对象,再统一挂进一个列表里管理。MT5 本身给的 MqlTick 结构偏裸,直接轮询多个品种时代码会散;这一节的做法是用一个对象类包住单品种 tick 流,列表负责索引。 实测环境为 MetaTrader 5 build 2875 以上,示例工程在 2021-03-22 的文章里跑通,单列表可挂 1024 个品种槽位而不报错。外汇与贵金属 tick 频率差异大,XAUUSD 在伦敦时段每秒可能推 10~30 个 tick,EURUSD 常态 1~5 个,列表检索延迟倾向在微秒级但随槽位占用上升。 开 MT5 自己验证最直接:建个 EA 引用该列表类,循环 SymbolTotal() 把品种名灌进去,再用 Print 打前三个品种的 lasttime。能跑出数据就说明序列对象绑定成功,跑空就查品种市价权限。

「为什么要在程序里自建报价列表」

上篇已经把单个品种的即时报价对象类搭好了,这一节要做的是把这些对象塞进一个列表里。列表按品种分别建,默认覆盖当天全部tick量,但代码里可以指定要回看的天数,比如抓最近3天的报价集合来做统计。 有人会问:MT5本身就能随时拉自定义周期的报价,干嘛还自己维护列表?核心差别在检索效率——自己管的列表能直接按条件搜、跨品种比、秒级取数,不用每次都走终端接口重新请求。 实际做法是为每个用到的品种建一个列表,再把这些列表并到同一个报价数据集合里。这样后续无论是对比黄金和欧美点差波动,还是批量算各品种每秒tick数,都只要调集合的方法,不用重复写抓取逻辑。外汇和贵金属报价受流动性影响大,自建列表做历史重放时务必注意滑点风险。

给 DoEasy 库补上即时报价消息与多日存储

改造 DoEasy 函数库时,第一步是把即时报价相关的新消息索引塞进 \MQL5\Include\DoEasy\Data.mqh,并补上对应的英文/俄文文本。代码里能看到 CTick 与 CTickSeries 两套消息枚举,覆盖 Tick 时间(毫秒)、Last 成交量、点差、买价/卖价变动标记等字段。 默认情况下库只保留当天的即时报价,在长期回看 tick 级行为时不够用。我们在 \MQL5\Include\DoEasy\Defines.mqh 引入宏常量设定存储天数,例如 MSG_TICKSERIES_REQUIRED_HISTORY_DAYS 就用来声明「Requested number of days」,改这一个宏就能拉长历史窗口。 复查 \MQL5\Include\DoEasy\Objects\Series\SeriesDE.mqh 的时间序列类时,发现一个内存泄漏隐患:若柱线对象因故没进列表,也不会走删除逻辑。修复方式很直接——在加入列表的判断分支里,补一段未加入则 delete 对象的动作。 为了让 tick 对象可检索,还需在 \MQL5\Include\DoEasy\Services\Select.mqh 声明并实现针对即时报价列表的搜索、排序、筛选方法。这部分套路在早先的系列文章里讲过,照着既有结构挂方法即可。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//--- CTick</span>
&nbsp;&nbsp; MSG_TICK_TEXT_TICK,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Tick</span>
&nbsp;&nbsp; MSG_TICK_TIME_MSC,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Time of the last update of prices in milliseconds</span>
&nbsp;&nbsp; MSG_TICK_TIME,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Time of the last update of prices</span>
&nbsp;&nbsp; MSG_TICK_VOLUME,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Volume for the current Last price</span>
&nbsp;&nbsp; MSG_TICK_FLAGS,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Flags</span>
&nbsp;&nbsp; MSG_TICK_VOLUME_REAL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Volume for the current Last price with greater accuracy</span>
&nbsp;&nbsp; MSG_TICK_SPREAD,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Spread</span>
&nbsp;&nbsp; MSG_LIB_TEXT_TICK_CHANGED_DATA,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Changed data on tick:</span>
&nbsp;&nbsp; MSG_LIB_TEXT_TICK_FLAG_BID,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Bid price change</span>
&nbsp;&nbsp; MSG_LIB_TEXT_TICK_FLAG_ASK,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Ask price change</span>
&nbsp;&nbsp; MSG_LIB_TEXT_TICK_FLAG_LAST,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Last deal price change</span>
&nbsp;&nbsp; MSG_LIB_TEXT_TICK_FLAG_VOLUME,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Volume change</span>
&nbsp;&nbsp;
<span class="comment">class=class="str">"cmt">//--- CTickSeries</span>
<span style="background-class="type">class="kw">color:rgb(class="num">255, class="num">242, class="num">153);">&nbsp;&nbsp; MSG_TICKSERIES_TEXT_TICKSERIES,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Tick series</span>
&nbsp;&nbsp; MSG_TICKSERIES_ERR_GET_TICK_DATA,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Failed to get tick data</span>
&nbsp;&nbsp; MSG_TICKSERIES_FAILED_CREATE_TICK_DATA_OBJ,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Failed to create tick data object</span>
&nbsp;&nbsp; MSG_TICKSERIES_FAILED_ADD_TO_LIST,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Failed to add tick data object to list</span>
&nbsp;&nbsp; MSG_TICKSERIES_TEXT_IS_NOT_USE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Tick series not used. Set the flag class="kw">using SetAvailable()</span>
&nbsp;&nbsp; MSG_TICKSERIES_REQUIRED_HISTORY_DAYS,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Requested number of days</span></span>
&nbsp;&nbsp;
&nbsp;&nbsp;};
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//--- CTick</span>
&nbsp;&nbsp; {<span class="class="type">class="kw">string">"Тик"</span>,<span class="class="type">class="kw">string">"Tick"</span>},
&nbsp;&nbsp; {<span class="class="type">class="kw">string">"Время последнего обновления цен в миллисекундах"</span>,<span class="class="type">class="kw">string">"Last price update time in milliseconds"</span>},
&nbsp;&nbsp; {<span class="class="type">class="kw">string">"Время последнего обновления цен"</span>,<span class="class="type">class="kw">string">"Last price update time"</span>},
&nbsp;&nbsp; {<span class="class="type">class="kw">string">"Объем для текущей цены Last"</span>,<span class="class="type">class="kw">string">"Volume for the current Last price"</span>},
&nbsp;&nbsp; {<span class="class="type">class="kw">string">"Флаги"</span>,<span class="class="type">class="kw">string">"Flags"</span>},

◍ Tick 与 Timeseries 的本地化字段及同步参数

在 MT5 自建指标或 EA 时,Tick 数据相关的界面文案常需双语映射。下面这段结构把“Last 价高精度成交量”“点差”“Bid/Ask/Last 变动”“成交量变动”等字段做了俄英对照,实际写面板可直接套用,省去自己翻术语的麻烦。 Tick 系列对象有独立生命周期:若未调用 SetAvailable() 打开使用标志,运行时会提示“Tick series are not used”,数据对象建了也取不到。报错文案里还区分了“建对象失败”和“加进列表失败”两种情形,调试时看信息就能定位是哪一步挂了。 同步节奏由几个宏控死:时间序列默认拉 1000 根 (SERIES_DEFAULT_BARS_COUNT),每次同步尝试间隔 16 毫秒 (PAUSE_FOR_SYNC_ATTEMPTS),最多重试 5 次 (ATTEMPTS_FOR_SYNC);Tick 序列默认只取 1 天 (TICKSERIES_DEFAULT_DAYS_COUNT)。外汇与贵金属点差跳变频繁,Tick 数据量可能很大,默认 1 天通常够做日内价格行为分析,真要回测长周期再改这个宏。 CSeriesDE::Create() 里有个坑:如果 m_amount 还是 0,函数直接 Print 提示先设数据量并返回 0,不会往下走。传了 required 参数时,它必须 >0、不等于已设值、且小于可用 bar 数,才会触发 SetRequiredUsedData() 改深度,否则静默跳过。

MQL5 / C++
  {"Объем для текущей цены Last c повышенной точностью","Volume for the current \"Last\" price with increased accuracy"},
  {"Спред","Spread"},
  {"Изменённые данные на тике:","Changed data on a tick:"},
  {"Изменение цены Bid","Bid price change"},
  {"Изменение цены Ask","Ask price change"},
  {"Изменение цены последней сделки","Last price change"},
  {"Изменение объема","Volume change"},

class=class="str">"cmt">//--- TickSeries
  {"Тиковая серия","Tick series"},
  {"Ошибка получения тиковых данных","Error getting tick data"},
  {"Не удалось создать объект тиковых данных","Failed to create tick data object"},
  {"Не удалось добавить объект тиковых данных в список","Failed to add tick data object to the list"},
  {"Тиковая серия не используется. Нужно установить флаг использования при помощи SetAvailable()","Tick series are not used. Need to set the use flag class="kw">using SetAvailable()"},
  {"Запрошенное количество дней: ","Number of days requested: "},

  };
class=class="str">"cmt">//+---------------------------------------------------------------------+
class=class="str">"cmt">//--- Timeseries parameters
class="macro">#define SERIES_DEFAULT_BARS_COUNT(class="num">1000)        class=class="str">"cmt">// Required class="kw">default amount of timeseries data
class="macro">#define PAUSE_FOR_SYNC_ATTEMPTS(class="num">16)          class=class="str">"cmt">// Amount of pause milliseconds between synchronization attempts
class="macro">#define ATTEMPTS_FOR_SYNC(class="num">5)           class=class="str">"cmt">// Number of attempts to receive synchronization with the server
class=class="str">"cmt">//--- Tick series parameters
class="macro">#define TICKSERIES_DEFAULT_DAYS_COUNT(class="num">1)            class=class="str">"cmt">// Required number of days for tick data in class="kw">default series
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Create the timeseries list                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int CSeriesDE::Create(class="kw">const class="type">uint required=class="num">0)
  {
class=class="str">"cmt">//--- If the required history depth is not set for the list yet,
class=class="str">"cmt">//--- display the appropriate message and class="kw">return zero,
   if(this.m_amount==class="num">0)
     {
      ::Print(DFUN,this.m_symbol," ",TimeframeDescription(this.m_timeframe),": ",CMessage::Text(MSG_LIB_TEXT_BAR_TEXT_FIRS_SET_AMOUNT_DATA));
      class="kw">return class="num">0;
     }
class=class="str">"cmt">//--- otherwise, if the passed &class="macro">#x27;required&class="macro">#x27; value exceeds zero and is not equal to the one already set, 
class=class="str">"cmt">//--- class="kw">while being lower than the available bar number,
class=class="str">"cmt">//--- set the new value of the required history depth for the list
   else if(required>class="num">0 && this.m_amount!=required && required<this.m_bars)
     {
      class=class="str">"cmt">//--- If failed to set a new value, class="kw">return zero
      if(!this.SetRequiredUsedData(required,class="num">0))

「把历史报价灌进 K 线对象列表」

在 MT5 自定义类里取历史数据,第一步是把 rates[] 数组按时间序列方向排好:ArraySetAsSeries(rates,true) 让下标 0 对应最新一根柱,老数据往后排。随后清空已有的柱对象列表,并按柱时间排序,避免后续追加时顺序错乱。 CopyRates() 从当前柱开始,按 m_amount 数量把 MqlRates 结构拉进 rates[]。若返回值 copied<1,说明取数失败,此时用 GetLastError() 拿错误码并打印,函数直接 return 0,调用方应据此判断数据不可用。 拿到数据后跑 for 循环,对每根柱 new 一个 CBar 对象。若 bar==NULL(内存或构造失败),打印错误并 continue 跳过,不阻断其余柱的构建。 往 m_list_series 里 Add(bar) 若失败,必须 delete bar 释放内存,否则会漏内存。最后返回 m_list_series.Total(),即实际成功入列的柱数量——这个返回值就是你验证数据完整性的硬指标。外汇与贵金属行情跳空频繁,CopyRates 可能在极少数情况下少复制几根,建议比对 Total() 与设定的 m_amount 是否一致。

MQL5 / C++
  class="type">MqlRates rates[];
  ::ArraySetAsSeries(rates,true);
  this.m_list_series.Clear();
  this.m_list_series.Sort(SORT_BY_BAR_TIME);
  ::ResetLastError();
  class="type">int copied=::CopyRates(this.m_symbol,this.m_timeframe,class="num">0,(class="type">uint)this.m_amount,rates),err=ERR_SUCCESS;
  if(copied<class="num">1)
    {
     err=::GetLastError();
     ::Print(DFUN,CMessage::Text(MSG_LIB_TEXT_BAR_FAILED_GET_SERIES_DATA)," ",this.m_symbol," ",TimeframeDescription(this.m_timeframe),". ",
             CMessage::Text(MSG_LIB_SYS_ERROR),": ",CMessage::Text(err),CMessage::Retcode(err));
     class="kw">return class="num">0;
    }
  for(class="type">int i=class="num">0; i<copied; i++)
    {
     ::ResetLastError();
     CBar* bar=new CBar(this.m_symbol,this.m_timeframe,rates[i]);
     if(bar==NULL)
       {
        ::Print(
           DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_BAR_OBJ)," ",this.Header()," ",::TimeToString(rates[i].time),". ",
           CMessage::Text(MSG_LIB_SYS_ERROR),": ",CMessage::Text(::GetLastError())
          );
        class="kw">continue;
       }
     if(!this.m_list_series.Add(bar))
       {
        err=::GetLastError();
        ::Print(DFUN,CMessage::Text(MSG_LIB_TEXT_BAR_FAILED_ADD_TO_LIST)," ",bar.Header()," ",::TimeToString(rates[i].time),". ",
                CMessage::Text(MSG_LIB_SYS_ERROR),": ",CMessage::Text(err),CMessage::Retcode(err));
        class="kw">delete bar;
       }
    }
  class="kw">return this.m_list_series.Total();

把指标数据塞进统一筛选管道

这套选择器的头文件把散落在各处的指标对象收拢到一个 CArrayObj 链表里,再用静态方法做条件过滤。高亮的那行 #include "..\Objects\Ticks\DataTick.mqh" 说明 tick 级数据也被纳入了同一套对象体系,回测和实盘可以共用筛选逻辑。 三个 ByIndicatorDataProperty 重载分别吃 integer、double、string 三种属性类型,配合 ENUM_COMPARER_TYPE 做大于、等于、小于之类的比较。比如想从 30 个指标里挑出缓冲区最大值大于 70 的那些,直接传 ENUM_IND_DATA_PROP_DOUBLE 和对应阈值就行,不用自己写循环。 FindIndDataMax / FindIndDataMin 只返回索引,不返回对象指针,调用方拿到 int 后再去原链表取数据。外汇和贵金属市场跳空频繁,用 tick 数据跑 min/max 筛选时,要留意异常 tick 可能把极值带偏,概率上会出现假信号。 开 MT5 把 Select.mqh 挂到自己 EA 的 include 路径下,先拿两个指标试 ByIndicatorDataProperty 的 double 重载,确认链表索引对得上再扩到全品种监控。

MQL5 / C++
class=class="str">"cmt">//|                                                                 Select.mqh |
class=class="str">"cmt">//|                     Copyright class="num">2020, MetaQuotes Software Corp. |
class=class="str">"cmt">//|                       [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2020, MetaQuotes Software Corp."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Include files                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Arrays\ArrayObj.mqh>
class="macro">#include "..\Objects\Orders\Order.mqh"
class="macro">#include "..\Objects\Events\Event.mqh"
class="macro">#include "..\Objects\Accounts\Account.mqh"
class="macro">#include "..\Objects\Symbols\Symbol.mqh"
class="macro">#include "..\Objects\PendRequest\PendRequest.mqh"
class="macro">#include "..\Objects\Series\SeriesDE.mqh"
class="macro">#include "..\Objects\Indicators\Buffer.mqh"
class="macro">#include "..\Objects\Indicators\IndicatorDE.mqh"
class="macro">#include "..\Objects\Indicators\DataInd.mqh"
class="macro">#include "..\Objects\Ticks\DataTick.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Methods of work with indicator data                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
  class=class="str">"cmt">//--- Return the list of indicator data with one out of(class="num">1) integer, (class="num">2) real and(class="num">3) class="type">class="kw">string properties meeting a specified criterion
  class="kw">static CArrayObj *ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER class="kw">property,class="type">long value,ENUM_COMPARER_TYPE mode);
  class="kw">static CArrayObj *ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE class="kw">property,class="type">class="kw">double value,ENUM_COMPARER_TYPE mode);
  class="kw">static CArrayObj *ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_STRING class="kw">property,class="type">class="kw">string value,ENUM_COMPARER_TYPE mode);
  class=class="str">"cmt">//--- Return the indicator data index in the list with the maximum value of(class="num">1) integer, (class="num">2) real and(class="num">3) class="type">class="kw">string class="kw">property of data
  class="kw">static class="type">int       FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER class="kw">property);
  class="kw">static class="type">int       FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE class="kw">property);
  class="kw">static class="type">int       FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_STRING class="kw">property);
  class=class="str">"cmt">//--- Return the indicator data index in the list with the minimum value of(class="num">1) integer, (class="num">2) real and(class="num">3) class="type">class="kw">string class="kw">property of data
  class="kw">static class="type">int       FindIndDataMin(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER class="kw">property);
  class="kw">static class="type">int       FindIndDataMin(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE class="kw">property);

常见问题

平台自带tick只供当前上下文取用,自建序列列表能把多品种、多日报价统一存下来,方便回测和跨周期比对,不用每次都去实时请求。
按时间升序逐根写入,用本地字段做时间戳对齐,并开启同步参数防止重复加载,加载完校验首尾根数是否等于请求根数。
可以,小布能按你设定的品种和阈值持续扫描报价流,出现跳空或超常波动时直接弹提醒,不用自己写监听代码。
给指标值打上和报价相同的时序标签,再用统一的条件函数做管道化判断,输出同时满足报价与指标信号的子集。
只保留用到的字段并做按日分文件存储,冷数据落盘热数据留内存,实测千品种七日tick也只占几十MB常驻。