MetaTrader 5 中的出价/要价(Bid/Ask)点差分析(基础篇)
「MT5 里点差到底怎么读」
在 MT5 里,Bid 是做市商愿意买入的价格,Ask 是愿意卖出的价格,两者之差就是点差。对外汇和贵金属来说,点差直接吃掉短线盈利,属于高频交易必须盯死的成本项,这类品种杠杆高、波动剧烈,风险显著。
用 SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) 能直接拿到当前点差,单位是点数(point)。实测 EURUSD 在伦敦盘活跃时段点差常落在 0~5 点,而在周日开盘或重大数据前可能拉伸到 20 点以上,这种跳动会在毫秒级影响你的止损距离。
别把点差当常数。它随流动性、会话切换和平台规则变化,写 EA 时若硬编码 spread<=2 过滤条件,遇到的新闻行情可能直接把你挡在门外,也可能让你在异常点差下疯狂成交。
市价单成交价藏在买卖点差里
只要你的开仓或平仓没挂限价、也没设止损单,走的都是市价单,最终成交价直接被买卖点差吃掉一块。点差不是装饰,它是你每笔市价操作的实际摩擦成本。 点买入按钮时,你按卖方的要价(Ask)接货,这比你看盘时盯着的买方出价(Bid)高一截;点卖出按钮时,你按买方出价(Bid)甩货,比要价低一截。平多仓同理——按当前 Bid 卖;平空仓则按当前 Ask 回补。 MT5 的即时报价流能拉出近期真实平均点差,不用只盯当下那一个跳动值。把 Bid 线和 Ask 线都显示在图表上,点差已经肉眼可见,但要做统计得用代码抓历史 tick。外汇与贵金属杠杆高,点差扩大时市价单滑点可能显著吞噬盈利,验证前先认清风险。
◍ 点差成本如何啃掉你的止损空间
把经纪商平台标称点差拉出来看,大部分时间在 5 个点。往返一开一平就是 1 个点成本,对 10 点止损、10 点止盈、1:1 盈亏比的单子来说,这占掉风险的 10%。横向比一下,博彩公司过盈率通常 15%,赌场毛利约 4%,5 点差算相对公道。 但数据窗口里实际平均点差(红线)几乎是黑色虚线标称值的两倍。同样 10/10 的 setup,成本通常至少 2 个点,也就是风险的 20%。做 5 点止损 5 点止盈的剥头皮,或者触发 10 点离场却只亏 5 点,成本还是 2 点,但因基数变小,占比直接飙到 40%。 我早年用 5 点损、10 点盈凑 2:1,结果不灵。后来在 EURUSD M1 上用腿长≥5 点的之字指标回测,发现大多数小幅波动约 7 点,10 点腿长反而偏短。于是改 10 点损、止盈不挂,盯盘到 7 点浮盈就手动撤,小有改善,但直到发现该经纪商对赌时点差异常高才换平台。 新闻或波动期实际均差能到 15 点,是标准 5 点的 3 倍,单笔成本 3 点即 60% 风险。英时间 20:30(服务器 21:30)后常是 4~6 倍,持仓过周末甚至接近 10 倍,除非止损止盈留极宽空间,否则外汇/贵金属这种高杠杆品种会被点差直接洗掉。
「初始化里先把点差基准算清楚」
这个双线绘图指标只暴露两个输入:numRecentBarsBack 控制回看柱数,doPrint 决定是否往日志吐逐根统计。OnInit() 第一件事不是画图,而是用 iBars(_Symbol,PERIOD_CURRENT)-2 拿到可用柱数,若请求值大于实际可用数就弹 Alert 并回 INIT_PARAMETERS_INCORRECT,避免后面空跑。 点差基准的算法有点绕:先取 EURUSD 现价(取不到就填 1.2),用 5 个 EURUSD 点除以该价得到“标准点差”比例;再遍历当前品种最近 numRecentBarsBack 根外汇价求平均价,乘回标准比例除以 5,四舍五入出该品种的换算点差。USDMXN 日图宣称点差约 0.0025,比零高 3 个水平,折 EURUSD 约 15 点,且实盘均值比经纪商高位还大;GBPJPY 日图宣称约 0.020,同样折 15 点,实均值贴近宣称值。 换算后的点差会写进指标短名,也作为水平线塞进子窗口。doPrint 若为真,会在 Experts 日志打印每根柱的实差点差与宣称点差,numRecentBarsBack 设太大就拖慢刷新,所以默认压在 100。 把 doPrint 开 true、numRecentBarsBack 设成 30 分钟图 100 或 1 分钟图 300,跑完复制日志,就是找经纪商对峙真实买卖点差的一手材料。外汇与贵金属杠杆高,点差漂移会直接吃掉短线盈亏,样本只覆盖外汇对,非外汇品种未测。
class="macro">#class="kw">property indicator_separate_window class="macro">#class="kw">property indicator_buffers class="num">2 class="macro">#class="kw">property indicator_plots class="num">2 class=class="str">"cmt">//--- plots class="macro">#class="kw">property indicator_label1 "ActSpread" class="macro">#class="kw">property indicator_type1 DRAW_LINE class="macro">#class="kw">property indicator_color1 clrRed class="macro">#class="kw">property indicator_style1 STYLE_SOLID class="macro">#class="kw">property indicator_width1 class="num">2 class="macro">#class="kw">property indicator_label2 "DeclaredSpread" class="macro">#class="kw">property indicator_type2 DRAW_LINE class="macro">#class="kw">property indicator_color2 clrBlack class="macro">#class="kw">property indicator_style2 STYLE_DASH class="macro">#class="kw">property indicator_width2 class="num">2 class=class="str">"cmt">//--- indicator parameters class="kw">input class="type">int numRecentBarsBack=class="num">100; class=class="str">"cmt">//class="macro">#RecentBarsBack M30+~class="num">100, M5~class="num">200, M1~class="num">500 class="kw">input class="type">bool doPrint=true; class=class="str">"cmt">//true=prints to the toolbox\experts log class=class="str">"cmt">//--- indicator buffers class="type">class="kw">double ActSpreadBuf[], DeclaredSpreadBuf[]; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Custom indicator initialization function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class="type">int numBars=iBars(_Symbol,PERIOD_CURRENT)-class="num">2; class=class="str">"cmt">// Check we have enough data for the request before we begin if(numRecentBarsBack>numBars) { Alert("Can&class="macro">#x27;t Do ", numRecentBarsBack, "! Only ", numBars, " Bars are Available", " try class="num">100 or so for class="num">30+ minute charts,", " class="num">200 for class="num">5 minute, or class="num">500 for class="num">1 minute charts.", " Otherwise the indicator may be too slow" ); class="kw">return(INIT_PARAMETERS_INCORRECT); } class="type">class="kw">double sumPrice=class="num">0; class="type">class="kw">double avgPrice=class="num">0;