我看不出为什么需要自定义符号。在标准符号本身上保存和重放书籍事件是完全可行的--无论是在常规图表的历史记录上(用于显示指标)还是在测试器中(用于 EA 测试)。
这篇文章很短,代码很少。让我们在下一部分中看看是否有必要增加第 1 部分、第 2 部分等。
SYMBOL_TICKS_BOOKDEPTH 给出了市场深度中显示的最大请求数。该属性给出的结果与计算 DOM 中的层数相同,这是不正确的。它给出的是最大数量,而不是精确数量。
您可以使用此脚本来计算:
//+------------------------------------------------------------------+ //|TestOnderBook.mq5 //|版权所有 2025 年,塞缪尔-马诺埃尔-德索萨 | | //|https://www.mql5.com/zh/users/samuelmnl| |. //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Samuel Manoel De Souza" #property link "https://www.mql5.com/zh/users/samuelmnl" #property version "1.00" //+------------------------------------------------------------------+ //| 脚本程序启动功能| //+------------------------------------------------------------------+ int OnInit(void) { MarketBookAdd(_Symbol); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ void OnDeinit(const int reason) { MarketBookRelease(_Symbol); } //+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ void OnTick(void) { } //+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ void OnBookEvent(const string& symbol) { double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); MqlBookInfo book[]; MarketBookGet(_Symbol, book); int total = ArraySize(book); if(total == 0) { Print("there is no order available on the book"); ExpertRemove(); return; } int buy_levels = 0, sell_levels = 0; int buy_gaps = 0, sell_gaps = 0, gaps = 0; for(int i = 0; i < total; i++) { Print("price: ", book[i].price, ", volume: ", book[i].volume, ", type: ", EnumToString(book[i].type)); buy_levels += book[i].type == BOOK_TYPE_BUY ? 1 : 0; sell_levels += book[i].type == BOOK_TYPE_SELL ? 1 : 0; if(i > 0) { bool is_gap = fabs(book[i].price - book[i - 1].price) >= 2 * tick_size; gaps += is_gap ? 1 : 0; buy_gaps += is_gap && book[i].type == book[i - 1].type && book[i].type == BOOK_TYPE_BUY ? 1 : 0; sell_gaps += is_gap && book[i].type == book[i - 1].type && book[i].type == BOOK_TYPE_SELL ? 1 : 0; } } Print("max levels: ", SymbolInfoInteger(_Symbol, SYMBOL_TICKS_BOOKDEPTH)); Print("levels: ", total); Print("buy levels: ", buy_levels); Print("sell levels: ", sell_levels); Print("gaps: ", gaps); Print("buy gaps: ", buy_gaps); Print("sell gap: ", sell_gaps); ExpertRemove(); } //+------------------------------------------------------------------+
本打算用该指标开发的交易系统怎么了?
新文章 开发基于订单簿的交易系统(第一部分):指标已发布:
让我们回顾一下市场深度是什么。这是一系列待执行的限价订单。这些订单代表了市场参与者的交易意图,通常不会导致实际交易。这是因为交易者有能力因各种原因取消之前下达的订单。这些原因可能包括市场状况的变化以及由此导致的失去以先前指定的价格和数量执行订单的兴趣。
函数 SymbolInfoInteger(_Symbol, SYMBOL_TICKS_BOOKDEPTH) 返回的值与订单簿的深度精确对应,并代表将填充要分析的价格水平的数组部分的一半。该数组的一半用于限价卖出订单的数量,另一半用于已下达的限价买入订单。根据文档,对于没有订单队列的资产,此属性的值为零。下图中可以看到一个示例,其中显示了深度为 10 的订单簿,其中显示了所有可用的价格水平。
需要注意的是,深度可以从交易品种获得,而不一定从市场深度获得。使用 SymbolInfoInteger 函数足以获取属性值,而无需借助 OnBookEvent 处理程序或相关函数(如 MarketBookAdd )。当然,我们可以通过计算 OnBookEvent 处理函数填充的 MqlBookInfo 数组中的元素数量来得出相同的结果,我们稍后将详细探讨。
作者:Daniel Santos