用于构建交易品种图表的价格类型
MetaTrader 5 价格图表上的柱线可以根据 Bid 或 Last 价格绘制,绘制类型在每个金融工具的规范中指明。MQL 程序可以通过对 SYMBOL_CHART_MODE 特性调用 SymbolInfoInteger 函数来找到这一特征。返回值为 ENUM_SYMBOL_CHART_MODE 枚举之一。
标识符
|
说明
|
SYMBOL_CHART_MODE_BID
|
柱线按买入价格构建
|
SYMBOL_CHART_MODE_LAST
|
柱线按最新价格构建
|
具有 Last 价格的模式用作在交易所交易的交易品种(与分散的外汇市场相反),而 市场深度 可用于这种交易品种。可依据 SYMBOL_TICKS_BOOKDEPTH 特性可以找到市场深度。
SYMBOL_CHART_MODE 的特性对于调整所构建的指标或策略的信号很有用,例如,在图表的 Last 价格;而订单将“以市价”执行,即,根据方向以 Ask 或 Bid 价格执行。
此外,在计算 自定义金融工具的柱线时,价格类型也是必需的:如果价格类型取决于标准交易品种,则按价格类型考虑其设置是有意义的。若用户将 合成金融工具 的公式输入 Custom Symbol 窗口(通过选择 Symbols 对话框中的 Create Symbol 打开),可以根据所使用的各个标准交易品种的规范来选择价格类型。但是,当计算算法在 MQL 程序中形成时,精确地说,其负责正确选择价格类型。
首先,让我们收集使用 Bid 和 Last 价格的统计数据,以构建特定账户的图表。这就是脚本 SymbolStatsByPriceType.mq5 的功能。
const bool MarketWatchOnly = false;
void OnStart()
{
const int n = SymbolsTotal(MarketWatchOnly);
int k = 0;
// loop through all available characters
for(int i = 0; i < n; ++i)
{
if(SymbolInfoInteger(SymbolName(i, MarketWatchOnly), SYMBOL_CHART_MODE)
== SYMBOL_CHART_MODE_LAST)
{
k++;
}
}
PrintFormat("Symbols in total: %d", n);
PrintFormat("Symbols using price types: Bid=%d, Last=%d", n - k, k);
}
|
用不同账户上尝试运行该脚本(有些账户可能没有股票交易品种)。结果如下所示:
Symbols in total: 52304
Symbols using price types: Bid=229, Last=52075
|
一个更实际的示例是指标 SymbolBidAskChart.mq5,其设计用于根据指定类型的价格绘制柱线形式。这将允许你将使用 SYMBOL_CHART_MODE 特性中价格构建的蜡烛图与其他价格类型的柱线进行比较。例如,你可以在金融工具图表的 Last 价格处看到 Bid 价格的柱线或者得到 Ask 价格的柱线,而标准终端图表不支持这些功能。
作为新指标的依据,我们将采用一个现成指标 IndDeltaVolume.mq5,如 等待数据和管理可见性一节所述。在这个指标中,我们下载了一定数量柱线 BarCount 的分时报价历史,并计算了交易量的增量,即分别买入和卖出的交易量。在新指标中,我们只需要将计算算法替换为基于每根柱线内分时报价搜索 Open、High、Low 和 Close 价格。
指标设置包括显示在主窗口中的四个缓冲区和一根柱线图 (DRAW_BARS)。
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 1
#property indicator_type1 DRAW_BARS
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
#property indicator_label1 "Open;High;Low;Close;"
|
选择显示为柱线是为了在主蜡烛图上运行时更容易阅读,同时显示每根柱线的两个版本。
新增的 ChartMode 输入参数允许用户从三种价格类型中选择一种(注意,与 ENUM_SYMBOL_CHART_MODE 中的标准元素集相比,Ask 是我们添加的元素)。
enum ENUM_SYMBOL_CHART_MODE_EXTENDED
{
_SYMBOL_CHART_MODE_BID, // SYMBOL_CHART_MODE_BID
_SYMBOL_CHART_MODE_LAST, // SYMBOL_CHART_MODE_LAST
_SYMBOL_CHART_MODE_ASK, // SYMBOL_CHART_MODE_ASK*
};
input int BarCount = 100;
input COPY_TICKS TickType = INFO_TICKS;
input ENUM_SYMBOL_CHART_MODE_EXTENDED ChartMode = _SYMBOL_CHART_MODE_BID;
|
以前的 CalcDeltaVolume 类将其名称改为 CalcCustomBars,但几乎保持不变。不同之处包括一组新的四个缓冲区和 chartMode 字段,该字段在构造函数中由输入变量 ChartMode 初始化。
class CalcCustomBars
{
const int limit;
const COPY_TICKS tickType;
const ENUM_SYMBOL_CHART_MODE_EXTENDED chartMode;
double open[];
double high[];
double low[];
double close[];
...
public:
CalcCustomBars(
const int bars,
const COPY_TICKS type,
const ENUM_SYMBOL_CHART_MODE_EXTENDED mode)
: limit(bars), tickType(type), chartMode(mode) ...
{
// register arrays as indicator buffers
SetIndexBuffer(0, open);
SetIndexBuffer(1, high);
SetIndexBuffer(2, low);
SetIndexBuffer(3, close);
const static string defTitle[] = {"Open;High;Low;Close;"};
const static string types[] = {"Bid", "Last", "Ask"};
string name = defTitle[0];
StringReplace(name, ";", types[chartMode] + ";");
PlotIndexSetString(0, PLOT_LABEL, name);
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
}
...
|
根据 chartMode 的模式,辅助方法 price 可从每条分时报价返回特定的价格类型。
protected:
double price(const MqlTick &t) const
{
switch(chartMode)
{
case _SYMBOL_CHART_MODE_BID:
return t.bid;
case _SYMBOL_CHART_MODE_LAST:
return t.last;
case _SYMBOL_CHART_MODE_ASK:
return t.ask;
}
return 0; // error
}
...
|
使用 price 方法,我们可以很容易地实现对主计算方法calc 的修改,该方法用于根据该柱线的 ticks 数组来填充第 i 根柱线的缓冲区。
void calc(const int i, const MqlTick &ticks[], const int skip = 0)
{
const int n = ArraySize(ticks);
for(int j = skip; j < n; ++j)
{
const double p = price(ticks[j]);
if(open[i] == EMPTY_VALUE)
{
open[i] = p;
}
if(p > high[i] || high[i] == EMPTY_VALUE)
{
high[i] = p;
}
if(p < low[i])
{
low[i] = p;
}
close[i] = p;
}
}
|
其余的源代码片段及其工作原理对应于 IndDeltaVolume.mq5 的说明。
在 OnInit 处理程序中,我们还显示了图表的当前价格类型,如果用户决定在缺少 Last的情况下基于该金融工具的 Last 价格类型构建一个指标,系统将会返回警告。
int OnInit()
{
...
ENUM_SYMBOL_CHART_MODE mode =
(ENUM_SYMBOL_CHART_MODE)SymbolInfoInteger(_Symbol, SYMBOL_CHART_MODE);
Print("Chart mode: ", EnumToString(mode));
if(mode == SYMBOL_CHART_MODE_BID
&& ChartMode == _SYMBOL_CHART_MODE_LAST)
{
Alert("Last price is not available for ", _Symbol);
}
return INIT_SUCCEEDED;
}
|
下面是基于 Last 价格图表绘图模式的工具屏幕截图;价格类型 Bid 的指标位于图表上方。

最新价格图表上带有买入价柱线的指标
观察普通 Bid 价格图表上叠加的 Ask 价格柱线也很有趣。

在买入价格图表上叠加卖出价格柱线的指标
在低流动性时段,当点差扩大时,你可以看到 Bid 和 Ask 价格图表之间的巨大差异。