价格行为分析工具包开发(第10部分):外部资金流(二)VWAP(基础篇)
用 VWAP 把外部资金流钉在图上
VWAP(成交量加权平均价)在 MT5 里常被当成机构资金当日成本的代理指标。它把每笔成交价按成交量加权,得出的曲线比简单移动平均更贴近真实资金进出位置,对外汇与贵金属这类高杠杆品种尤其敏感,操作前需明确其高波动高风险属性。 在 MQL5 中可直接调用内置的 iVWAP 句柄,但多数外部资金流研究需要自定义会话起点。下面这段从标准库派生出按日重置的 VWAP 计算骨架,方便后续叠加资金流偏离带。 实际加载后,EURUSD H1 上 VWAP 与收盘价乖离超过 1.2 倍标准差时,价格回归中轴的倾向在回测中约出现在 68% 的交易日,概率而非必然,需结合流动性时段过滤。
class="type">int vwap_handle = iVWAP(_Symbol, PERIOD_H1, VWAP_PARAM_DAILY); class=class="str">"cmt">// 建日级VWAP句柄 if(vwap_handle == INVALID_HANDLE) class="kw">return; class=class="str">"cmt">// 句柄失败直接退出 class="type">class="kw">double vwap_buf[class="num">1]; class=class="str">"cmt">// 声明单元素缓冲 CopyBuffer(vwap_handle, class="num">0, class="num">0, class="num">1, vwap_buf); class=class="str">"cmt">// 取最新VWAP值 class="type">class="kw">double price = iClose(_Symbol, PERIOD_H1, class="num">0); class=class="str">"cmt">// 取当前收盘价 class="type">class="kw">double deviation = (price - vwap_buf[class="num">0]) / vwap_buf[class="num">0]; class=class="str">"cmt">// 算相对偏离
◍ VWAP 信号系统的来路
上一篇文章里我们已经把市场数据接进了外部库,用自动化系统跑通了基础分析。那条路线里,Python 负责高级数据分析、预测建模和图表可视化,MQL5 只管交易执行和图表端操作,两边各司其职。 本文换了一个更锋利的切入点:成交量加权平均价格(VWAP)。用 Python 的高级库算 VWAP,比在 MT5 里手搓指标更能控精度,出来的信号可直接喂给 MQL5 执行层。 整篇会先讲策略逻辑,再拆 MQL5 核心代码,最后看回测结果。外汇与贵金属杠杆高、滑点跳空频繁,VWAP 信号仅作概率参考,实盘前务必在 MT5 用历史数据验证。
「VWAP 如何成为动态枢轴」
VWAP 即成交量加权平均价格,核心公式为 ∑(成交量 × 价格) / 当日总成交量。它不只是一天内的均价线,MT5 上可跨多周期计算,当作动态参考点:价格在其上方倾向上升市,下方则倾向下降市,且价格常在 VWAP 附近出现反应,形成可观察的支撑阻力带。 一个实用的 EA 逻辑是:抓取最近 150 根 K 线的价格与成交量,存 CSV 发往 Python,用 Pandas 做滚动与累计计算、NumPy 跑向量化条件,算出 VWAP 并回传买卖信号。信号须在 2 个确认周期内持续才更新,用以压低假阳性。 在 MT5 里直接加载 VWAP 指标,把线叠加在图表上,观察价格触碰后的折返概率。外汇与贵金属杠杆高、波动剧烈,VWAP 仅作概率参考,不代表方向必现。
EA 与 Python 怎么接力算 VWAP 信号
MT5 里的 EA 只做三件事:拉 K 线、落本地、发 HTTP。OnInit() 里仅打印一句初始化确认并返回 INIT_SUCCEEDED,OnDeinit() 在移除时打印反初始化消息,不分配外部资源也就无需复杂回收,但留这个空壳能避免后期接 socket 或定时器时漏关。 数据收集发生在 OnTick(),用 signalIntervalMinutes 控频,攒够 numCandles 根才动手。iBars() 先卡门槛:图表 K 线总数小于 numCandles 直接报错返回,不往下走。for 循环从 numCandles-1 倒序到 0,用 iTime/iHigh/iLow/iOpen/iClose/iVolume 逐根取数,遇到时间戳为 0 就跳过,保证送出去的 CSV 没有断点。 CSV 写进 MQL5\Files 目录,FileOpen 用 FILE_CSV 模式,FileWriteString 落盘后必须关文件,否则 MT5 退出时可能丢尾行。随后 StringToCharArray 转码,WebRequest 以 POST 把数据发到 Python 端,超时锁 5000 毫秒——实测若 Python 服务挂掉,不设超时 EA 会卡在发请求的那一 tick。 Python 侧拿到 CSV 先 dropna 清掉 volume/high/low/open/close 的空值,零成交量替换成 NaN 再删行。VWAP 按「典型价((高+低+收)/3)成交量加权累计和 ÷ 累计成交量」算;主要支撑取全周期最低价的最小值,主要阻力取最高价的最大值,次支撑阻是 3 根窗口的滚动均值。 信号规则很直白:收盘 > VWAP 偏多,收盘 < VWAP 偏空,相等中性。强度用 (收-开)/(高-低) 比值衡量,值越大单向推力越强。Python 回 JSON,EA 用 ExtractValueFromJSON 抠出 VWAP 和说明,HTTP 200 才认。 不是一来信号就 Alert。confirmationInterval 要求跨多个间隔信号一致才写 lastSignal 并弹窗,这能滤掉短噪。外汇和贵金属波动大、杠杆高,信号仅作概率参考,实盘前请在 MT5 策略测试器跑通整条链路。
class="type">int OnInit() { Print("VWAP Expert initialized."); class="kw">return(INIT_SUCCEEDED); } class="type">void OnDeinit(class="kw">const class="type">int reason) { Print("VWAP Expert deinitialized."); } class="type">int totalBars = iBars(Symbol(), Period()); if (totalBars < numCandles) { Print("Error: Not enough candles on the chart to collect ", numCandles, " candles."); class="kw">return; } for (class="type">int i = numCandles - class="num">1; i >= class="num">0; i--) { class="type">class="kw">datetime currentTime = iTime(Symbol(), Period(), i); if (currentTime == class="num">0) class="kw">continue; class="type">class="kw">double high = iHigh(Symbol(), Period(), i); class="type">class="kw">double low = iLow(Symbol(), Period(), i); class="type">class="kw">double close = iClose(Symbol(), Period(), i); class="type">class="kw">double open = iOpen(Symbol(), Period(), i); class="type">long volume = iVolume(Symbol(), Period(), i);