DoEasy 函数库中的价格(第六十三部分):市场深度及其抽象请求类·进阶篇
📊

DoEasy 函数库中的价格(第六十三部分):市场深度及其抽象请求类·进阶篇

(2/3)·从 OnBookEvent 到订单对象类,把四种盘口挂单收敛成供给与需求两条主线

进阶 第 2/3 篇
很多交易者订阅了 DOM 却只盯着买卖一档价差,忽略了 OnBookEvent 每次触发时整张订单簿的拓扑变化。把 MqlBookInfo 的四种类型直接当原始数据用,后续统计供需失衡要写一堆 if-else。先建一层抽象订单对象,后面扩展任何盘口策略都能少改很多代码。

「把 DOM 订单抽象成可排序的对象类」

在 MT5 里做深度盘口(DOM)分析,第一步是把每一笔挂单封装成对象,而不是散着读 MqlBookInfo 结构。先在函数库头文件里补三组枚举:整数型、实数型、字符串型属性,再加一个 ENUM_MBOOK_ORD_STATUS 区分买方挂单与卖方挂单。 按状态归类后,能一键筛出需求侧或供应侧的全部挂单,后续做失衡计算不用每次遍历全簿。整数属性枚举里目前定义了 STATUS、TYPE、VOLUME 三项,MBOOK_ORD_PROP_INTEGER_TOTAL 写死为 3,若你以后加字段记得同步改这个宏,否则排序会漏属性。 CMarketBookOrd 类继承基准对象 CBaseObj,构造函数直接吃 DOM 传来的订单结构,同时由派生类告知这笔单是买还是卖。类内 Compare() 返回 -1 / 0 / +1 三态,用于按指定属性排大小;CompareAll() 则逐属性比对,全相等才返 true,用来判重单。 日志方法分三个循环打印整数、实数、字符串属性说明,调试时开 MT5 专家日志就能看到每笔挂单的对象化结果。下一篇要建四个派生类,在初始化列表里写死各自状态,届时 new 一个对象就能自动归类。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Data for working with DOM                                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| List of possible DOM events                                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#define MBOOK_ORD_EVENTS_NEXT_CODE(SERIES_EVENTS_NEXT_CODE+class="num">1)   class=class="str">"cmt">// The code of the next event after the last DOM event code
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Abstract DOM type(status)                                                       |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_MBOOK_ORD_STATUS
  {
   MBOOK_ORD_STATUS_BUY,                                           class=class="str">"cmt">// Buy side
   MBOOK_ORD_STATUS_SELL,                                          class=class="str">"cmt">// Sell side
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Integer properties of DOM order                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_MBOOK_ORD_PROP_INTEGER
  {
   MBOOK_ORD_PROP_STATUS = class="num">0,                                      class=class="str">"cmt">// Order status
   MBOOK_ORD_PROP_TYPE,                                            class=class="str">"cmt">// Order type
   MBOOK_ORD_PROP_VOLUME,                                          class=class="str">"cmt">// Order volume
  };
class="macro">#define MBOOK_ORD_PROP_INTEGER_TOTAL(class="num">3)                           class=class="str">"cmt">// Total number of integer properties
class="macro">#define MBOOK_ORD_PROP_INTEGER_SKIP(class="num">0)                           class=class="str">"cmt">// Number of integer DOM properties not used in sorting
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Real properties of DOM order                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ DOM 订单属性的枚举与排序基准

在 MT5 的 MarketBook 订单结构里,双精度属性被单独抽成一个枚举:价格(MBOOK_ORD_PROP_PRICE)和扩展精度成交量(MBOOK_ORD_PROP_VOLUME_REAL),宏定义标明这类实数属性共 2 个、不参与排序的有 0 个。 字符串属性目前只有品种名一项(MBOOK_ORD_PROP_SYMBOL),其枚举值要叠加前面整数与双精度属性的总数偏移,实数总数 1 个。 排序枚举 ENUM_SORT_MBOOK_ORD_MODE 把三类属性映射成连续排序键:整数类从 0 起(状态、类型、成交量),双精度类由 FIRST_MB_DBL_PROP 承接,字符串类由 FIRST_MB_STR_PROP 承接。 开 MT5 把这段头文件塞进 Include 目录,直接打印 SORT_BY_MBOOK_ORD_PRICE 的枚举值,能验证它等于整数属性可用数,从而确认深度图订单按价排序的底层偏移。

MQL5 / C++
enum ENUM_MBOOK_ORD_PROP_DOUBLE
  {
   MBOOK_ORD_PROP_PRICE = MBOOK_ORD_PROP_INTEGER_TOTAL, class=class="str">"cmt">// Order price
   MBOOK_ORD_PROP_VOLUME_REAL,                          class=class="str">"cmt">// Extended accuracy order volume
  };
class="macro">#define MBOOK_ORD_PROP_DOUBLE_TOTAL(class="num">2)                 class=class="str">"cmt">// Total number of real properties
class="macro">#define MBOOK_ORD_PROP_DOUBLE_SKIP(class="num">0)                 class=class="str">"cmt">// Number of real properties not used in sorting
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| String properties of DOM order                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_MBOOK_ORD_PROP_STRING
  {
   MBOOK_ORD_PROP_SYMBOL = (MBOOK_ORD_PROP_INTEGER_TOTAL+MBOOK_ORD_PROP_DOUBLE_TOTAL), class=class="str">"cmt">// Order symbol name
  };
class="macro">#define MBOOK_ORD_PROP_STRING_TOTAL(class="num">1)                 class=class="str">"cmt">// Total number of class="type">class="kw">string properties
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Possible sorting criteria of DOM orders                          |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#define FIRST_MB_DBL_PROP(MBOOK_ORD_PROP_INTEGER_TOTAL-MBOOK_ORD_PROP_INTEGER_SKIP)
class="macro">#define FIRST_MB_STR_PROP(MBOOK_ORD_PROP_INTEGER_TOTAL-MBOOK_ORD_PROP_INTEGER_SKIP+MBOOK_ORD_PROP_DOUBLE_TOTAL-MBOOK_ORD_PROP_DOUBLE_SKIP)
enum ENUM_SORT_MBOOK_ORD_MODE
  {
class=class="str">"cmt">//--- Sort by integer properties
   SORT_BY_MBOOK_ORD_STATUS = class="num">0,                         class=class="str">"cmt">// Sort by order status
   SORT_BY_MBOOK_ORD_TYPE,                               class=class="str">"cmt">// Sort by order type
   SORT_BY_MBOOK_ORD_VOLUME,                             class=class="str">"cmt">// Sort by order volume
class=class="str">"cmt">//--- Sort by real properties
   SORT_BY_MBOOK_ORD_PRICE = FIRST_MB_DBL_PROP,          class=class="str">"cmt">// Sort by order price
   SORT_BY_MBOOK_ORD_VOLUME_REAL,                        class=class="str">"cmt">// Sort by extended accuracy order volume
class=class="str">"cmt">//--- Sort by class="type">class="kw">string properties
   SORT_BY_MBOOK_ORD_SYMBOL = FIRST_MB_STR_PROP,         class=class="str">"cmt">// Sort by symbol name
  };

深度簿订单对象的属性存取设计

做 DOM(深度簿)分析时,把每一笔挂单抽象成一个对象比直接裸读 MqlBookInfo 数组更利于扩展。下面这个类从 CBaseObj 继承,把订单的整数、实数、字符串三类属性分别塞进三个定长数组,用枚举偏移直接寻址。 私有成员里 m_long_prop 长度为 MBOOK_ORD_PROP_INTEGER_TOTAL,m_double_prop 和 m_string_prop 则分别对应 DOUBLE 与 STRING 的总枚举数。IndexProp 两个重载就是关键:实数属性在数组里的真实下标 = (int)property - 整数属性总数,字符串再减去实数总数,避免每次都写魔法数字。 对外只暴露 SetProperty / GetProperty 三套重载。写实数属性时先调 IndexProp 算出偏移再落数组,读的时候同理。这样后续要加新字段,只需改枚举和总数常量,类内部不用动逻辑。 外汇与贵金属市场流动性瞬变,深度簿数据仅反映某一毫秒的挂单分布,据此交易仍属高风险,价格可能随时反向扫单。

MQL5 / C++
class="macro">#class="kw">property strict   class=class="str">"cmt">// Necessary for mql4
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Include files                                                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "..\..\Services\DELib.mqh"
class="macro">#include "..\..\Objects\BaseObj.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| DOM abstract order class                                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CMarketBookOrd : class="kw">public CBaseObj
  {
class="kw">private:
   class="type">int               m_digits;                                          class=class="str">"cmt">// Number of decimal places
   class="type">long              m_long_prop[MBOOK_ORD_PROP_INTEGER_TOTAL];         class=class="str">"cmt">// Integer properties
   class="type">class="kw">double            m_double_prop[MBOOK_ORD_PROP_DOUBLE_TOTAL];        class=class="str">"cmt">// Real properties
   class="type">class="kw">string            m_string_prop[MBOOK_ORD_PROP_STRING_TOTAL];        class=class="str">"cmt">// String properties
class=class="str">"cmt">//--- Return the index of the array the(class="num">1) class="type">class="kw">double and(class="num">2) class="type">class="kw">string properties are actually located at
   class="type">int               IndexProp(ENUM_MBOOK_ORD_PROP_DOUBLE class="kw">property)   class="kw">const { class="kw">return(class="type">int)class="kw">property-MBOOK_ORD_PROP_INTEGER_TOTAL;                    }
   class="type">int               IndexProp(ENUM_MBOOK_ORD_PROP_STRING class="kw">property)   class="kw">const { class="kw">return(class="type">int)class="kw">property-MBOOK_ORD_PROP_INTEGER_TOTAL-MBOOK_ORD_PROP_DOUBLE_TOTAL; }
class="kw">public:
class=class="str">"cmt">//--- Set object&class="macro">#x27;s(class="num">1) integer, (class="num">2) real and(class="num">3) class="type">class="kw">string properties
   class="type">void              SetProperty(ENUM_MBOOK_ORD_PROP_INTEGER class="kw">property,class="type">long value)   { this.m_long_prop[class="kw">property]=value;                    }
   class="type">void              SetProperty(ENUM_MBOOK_ORD_PROP_DOUBLE class="kw">property,class="type">class="kw">double value)  { this.m_double_prop[this.IndexProp(class="kw">property)]=value;  }
   class="type">void              SetProperty(ENUM_MBOOK_ORD_PROP_STRING class="kw">property,class="type">class="kw">string value)  { this.m_string_prop[this.IndexProp(class="kw">property)]=value;  }
class=class="str">"cmt">//--- Return object’s(class="num">1) integer, (class="num">2) real and(class="num">3) class="type">class="kw">string class="kw">property from the properties array
   class="type">long              GetProperty(ENUM_MBOOK_ORD_PROP_INTEGER class="kw">property)            class="kw">const { class="kw">return this.m_long_prop[class="kw">property];                  }
   class="type">class="kw">double            GetProperty(ENUM_MBOOK_ORD_PROP_DOUBLE class="kw">property)            class="kw">const { class="kw">return this.m_double_prop[this.IndexProp(class="kw">property)]; }
  };

「深度盘口订单对象的属性读取与比较接口」

在 MT5 的 DOM(深度市场)分析里,CMarketBookOrd 类把每一笔盘口挂单封装成对象,对外暴露了三类属性读取:整型、双精度、字符串。上面这段头文件显示了 GetProperty 的重载实现,字符串属性直接通过 m_string_prop 数组按索引返回,调用方无需关心底层存储。 SupportProperty 的三个虚函数全部返回 true,意味着该订单对象默认宣称支持所有枚举属性;如果你在派生类里只实现部分属性,应当重写对应虚函数返回 false,否则 Print 全量输出时可能打印空值。 对象间排序依赖 Compare 虚函数(mode 参数默认 0,按全部属性比对),而 IsEqual 用于在同质订单中做等值检索。实盘上,黄金 XAUUSD 的盘口在流动性切换时一秒可能刷新十余次,用 IsEqual 快速去重比逐字段手写判断更稳。外汇与贵金属杠杆高、滑点突发,回测 DOM 行为不能替代实盘验证。 构造函数分两层:公开默认构造仅作占位,真正初始化走 protected 参数化构造,传入 ENUM_MBOOK_ORD_STATUS、MqlBookInfo 引用与 symbol 字符串。想自己扩展盘口逻辑,继承后务必调用该 protected 构造,否则 Status() 读出的枚举会是脏值。

MQL5 / C++
class="type">class="kw">string GetProperty(ENUM_MBOOK_ORD_PROP_STRING class="kw">property) class="kw">const { class="kw">return this.m_string_prop[this.IndexProp(class="kw">property)]; }
class=class="str">"cmt">//--- Return itself
CMarketBookOrd *GetObject(class="type">void) { class="kw">return &this;}
class=class="str">"cmt">//--- Return the flag of the object supporting this class="kw">property
class="kw">virtual class="type">bool SupportProperty(ENUM_MBOOK_ORD_PROP_INTEGER class="kw">property) { class="kw">return true; }
class="kw">virtual class="type">bool SupportProperty(ENUM_MBOOK_ORD_PROP_DOUBLE class="kw">property) { class="kw">return true; }
class="kw">virtual class="type">bool SupportProperty(ENUM_MBOOK_ORD_PROP_STRING class="kw">property) { class="kw">return true; }
class=class="str">"cmt">//--- Get description of(class="num">1) integer, (class="num">2) real and(class="num">3) class="type">class="kw">string properties
class="type">class="kw">string GetPropertyDescription(ENUM_MBOOK_ORD_PROP_INTEGER class="kw">property);
class="type">class="kw">string GetPropertyDescription(ENUM_MBOOK_ORD_PROP_DOUBLE class="kw">property);
class="type">class="kw">string GetPropertyDescription(ENUM_MBOOK_ORD_PROP_STRING class="kw">property);
class=class="str">"cmt">//--- Display the description of object properties in the journal(full_prop=true - all properties, false - supported ones only)
class="type">void Print(class="kw">const class="type">bool full_prop=false);
class=class="str">"cmt">//--- Display a class="type">class="kw">short description of the object in the journal
class="kw">virtual class="type">void PrintShort(class="type">void);
class=class="str">"cmt">//--- Return the object class="type">class="kw">short name
class="kw">virtual class="type">class="kw">string Header(class="type">void);

class=class="str">"cmt">//--- Compare CMarketBookOrd objects by all possible properties(to sort the lists by a specified order object class="kw">property)
class="kw">virtual class="type">int Compare(class="kw">const CObject *node,class="kw">const class="type">int mode=class="num">0) class="kw">const;
class=class="str">"cmt">//--- Compare CMarketBookOrd objects by all properties(to search for equal request objects)
class="type">bool IsEqual(CMarketBookOrd* compared_req) class="kw">const;

class=class="str">"cmt">//--- Default constructor
CMarketBookOrd(){;}
class="kw">protected:
class=class="str">"cmt">//--- Protected parametric constructor
CMarketBookOrd(class="kw">const ENUM_MBOOK_ORD_STATUS status,class="kw">const MqlBookInfo &book_info,class="kw">const class="type">class="kw">string symbol);

class="kw">public:
class=class="str">"cmt">//+-------------------------------------------------------------------+
class=class="str">"cmt">//|Methods of a simplified access to the DOM request object properties|
class=class="str">"cmt">//+-------------------------------------------------------------------+
class=class="str">"cmt">//--- Return order(class="num">1) status, (class="num">2) type and(class="num">3) order volume
ENUM_MBOOK_ORD_STATUS Status(class="type">void) class="kw">const { class="kw">return (ENUM_MBOOK_ORD_STATUS)this.GetProperty(MBOOK_ORD_PROP_STATUS); }

◍ 从挂单对象里抠出价格和成交量

做深度盘口分析时,单条挂单的属性必须能随时被 EA 调取。下面这段把 CMarketBookOrd 类里的取值接口直接铺开,每一行都对应一个盘口字段,开 MT5 新建类就能照抄。 TypeOrd() 把内部存储的整型强转回 ENUM_BOOK_TYPE,用来区分买序 / 卖序;Volume() 取整型手数,Price() 与 VolumeReal() 分别返回双精度挂单价与真实小数手数——后者在贵金属 0.01 手以下微单里才有意义。 Symbol() 回传该挂单所属品种,Digits() 不走 GetProperty 而是直接读 m_digits 成员,避免在高频 OnBookEvent 里反复调 SymbolInfoInteger 拖慢回测。 构造器里先存一次 Digits,再把 status、type、volume 三个整型属性写进对象。外汇与贵金属盘口跳动极快,这类封装能降低重复系统调用,但杠杆品种滑点风险高,回测和实盘差异可能很大。

MQL5 / C++
ENUM_BOOK_TYPE    TypeOrd(class="type">void)                class="kw">const { class="kw">return (ENUM_BOOK_TYPE)this.GetProperty(MBOOK_ORD_PROP_TYPE); }
class="type">long              Volume(class="type">void)                class="kw">const { class="kw">return this.GetProperty(MBOOK_ORD_PROP_VOLUME); }
class=class="str">"cmt">//--- Return(class="num">1) the price and(class="num">2) extended accuracy order volume
class="type">class="kw">double            Price(class="type">void)                class="kw">const { class="kw">return this.GetProperty(MBOOK_ORD_PROP_PRICE); }
class="type">class="kw">double            VolumeReal(class="type">void)           class="kw">const { class="kw">return this.GetProperty(MBOOK_ORD_PROP_VOLUME_REAL); }
class=class="str">"cmt">//--- Return(class="num">1) order symbol and(class="num">2) symbol&class="macro">#x27;s Digits
class="type">class="kw">string            Symbol(class="type">void)               class="kw">const { class="kw">return this.GetProperty(MBOOK_ORD_PROP_SYMBOL); }
class="type">int               Digits()                   class="kw">const { class="kw">return this.m_digits; }

class=class="str">"cmt">//--- Return the description of order(class="num">1) type(ENUM_BOOK_TYPE) and(class="num">2) status(ENUM_MBOOK_ORD_STATUS)
class="kw">virtual class="type">class="kw">string    TypeDescription(class="type">void)      class="kw">const { class="kw">return this.StatusDescription(); }
class="type">class="kw">string            StatusDescription(class="type">void)    class="kw">const;
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Parametric constructor                                           |
class=class="str">"cmt">//+------------------------------------------------------------------+
CMarketBookOrd::CMarketBookOrd(class="kw">const ENUM_MBOOK_ORD_STATUS status,class="kw">const MqlBookInfo &book_info,class="kw">const class="type">class="kw">string symbol)
  {
class=class="str">"cmt">//--- Save symbol’s Digits
   this.m_digits=(class="type">int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
class=class="str">"cmt">//--- Save integer object properties
   this.SetProperty(MBOOK_ORD_PROP_STATUS,status);
   this.SetProperty(MBOOK_ORD_PROP_TYPE,book_info.type);
   this.SetProperty(MBOOK_ORD_PROP_VOLUME,book_info.volume);
class=class="str">"cmt">//--- Save real object properties

订单簿对象的比较与全等判定

深度重构订单簿类时,比较逻辑决定了挂单在集合里如何排序。CMarketBookOrd::Compare 按 mode 值分流:小于整数属性总数走整型比较,介于整型与双精度总数之间走浮点比较,再往后走字符串比较,每层都返回 1 / -1 / 0 三态。 IsEqual 则是另一种用法——它不排序,只回答「两条挂单是否完全一致」。函数把整数、双精度、字符串三类属性区间拼成连续循环,任一属性不等立即返回 false,全过才算 true。 实盘里这套机制能直接支撑「同价同量挂单去重」:若某经纪商 XAUUSD 在 2035.20 暴露 3 笔各 0.50 手限价单,IsEqual 可在毫秒级识别出重复快照,避免你在小布盯盘里把同一流动性算成 1.5 手。外汇与贵金属盘口碎片化严重,这类判定失误会放大滑点风险,建议开 MT5 用下面代码自测一遍。

MQL5 / C++
class="type">int CMarketBookOrd::Compare(class="kw">const CObject *node,class="kw">const class="type">int mode=class="num">0) class="kw">const
  {
  class="kw">const CMarketBookOrd *obj_compared=node;
class=class="str">"cmt">//--- compare integer properties of two objects
  if(mode<MBOOK_ORD_PROP_INTEGER_TOTAL)
    {
    class="type">long value_compared=obj_compared.GetProperty((ENUM_MBOOK_ORD_PROP_INTEGER)mode);
    class="type">long value_current=this.GetProperty((ENUM_MBOOK_ORD_PROP_INTEGER)mode);
    class="kw">return(value_current>value_compared ? class="num">1 : value_current<value_compared ? -class="num">1 : class="num">0);
    }
class=class="str">"cmt">//--- compare real properties of two objects
  else if(mode<MBOOK_ORD_PROP_DOUBLE_TOTAL+MBOOK_ORD_PROP_INTEGER_TOTAL)
    {
    class="type">class="kw">double value_compared=obj_compared.GetProperty((ENUM_MBOOK_ORD_PROP_DOUBLE)mode);
    class="type">class="kw">double value_current=this.GetProperty((ENUM_MBOOK_ORD_PROP_DOUBLE)mode);
    class="kw">return(value_current>value_compared ? class="num">1 : value_current<value_compared ? -class="num">1 : class="num">0);
    }
class=class="str">"cmt">//--- compare class="type">class="kw">string properties of two objects
  else if(mode<MBOOK_ORD_PROP_DOUBLE_TOTAL+MBOOK_ORD_PROP_INTEGER_TOTAL+MBOOK_ORD_PROP_STRING_TOTAL)
    {
    class="type">class="kw">string value_compared=obj_compared.GetProperty((ENUM_MBOOK_ORD_PROP_STRING)mode);
    class="type">class="kw">string value_current=this.GetProperty((ENUM_MBOOK_ORD_PROP_STRING)mode);
    class="kw">return(value_current>value_compared ? class="num">1 : value_current<value_compared ? -class="num">1 : class="num">0);
    }
  class="kw">return class="num">0;
  }

class="type">bool CMarketBookOrd::IsEqual(CMarketBookOrd *compared_obj) class="kw">const
  {
  class="type">int beg=class="num">0, end=MBOOK_ORD_PROP_INTEGER_TOTAL;
  for(class="type">int i=beg; i<end; i++)
    {
    ENUM_MBOOK_ORD_PROP_INTEGER prop=(ENUM_MBOOK_ORD_PROP_INTEGER)i;
    if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) class="kw">return false;
    }
  beg=end; end+=MBOOK_ORD_PROP_DOUBLE_TOTAL;
  for(class="type">int i=beg; i<end; i++)
    {
    ENUM_MBOOK_ORD_PROP_DOUBLE prop=(ENUM_MBOOK_ORD_PROP_DOUBLE)i;
    if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) class="kw">return false;
    }
  beg=end; end+=MBOOK_ORD_PROP_STRING_TOTAL;
  for(class="type">int i=beg; i<end; i++)
    {
把盘口快照交给小布盯盘
这些 DOM 订单对象的抽象与分类逻辑,小布盯盘的 AIGC 已内置,打开对应品种页即可看到实时供需划分,你只需判断失衡方向。

常见问题

volume 是整型交易量,volume_real 是双精度真实交易量;高频 DOM 里大单拆细时 real 能保留更多小数精度,做微结构统计建议用 real。
抽象基类把类型规则下沉到衍生类,主流程只调用统一接口;后续加冰山单或隐藏单衍生类时,既有调用代码不用动。
品种未订阅 BookEvent、账户没有该品种交易权限、或经纪商不提供 DOM 数据时,处理程序不会激活,需要先用 MarketBookAdd 确认订阅。
可以,小布盯盘对活跃品种内置了盘口订单流聚合,按买单卖单方向归并展示,省去自己写 CBaseObject 继承链。
市价单代表已准备成交的流动性,限价单是挂出的等待单;抽象类里加方向状态后,能快速分离等待流动性与即时流动性做失衡分析。