纺锤形图表指标(基础篇)
纺锤形图表指标在 MT5 里的定位
纺锤形图表指标(Spindle Chart Indicator)是 MetaTrader 5 平台上的一类可视化辅助工具,把传统 K 线的开盘、收盘、最高、最低压缩成纺锤状形态,便于快速识别实体与影线比例关系。 该指标在 2016 年 2 月 11 日由 Dmitriy Zabudskiy 发布于社区,截至统计时点获得 6,918 次查看与 13 条讨论,说明其在价格行为交易者中有稳定关注度。 在 MT5 中加载后,纺锤宽度通常跟随成交量或 ATR 动态缩放;实体偏窄而影线拉长时,往往对应一段方向犹豫区,外汇与贵金属品种因杠杆高、波动突发行情多,这类形态失效概率也更高,仅可作为辅助而非入场依据。
◍ 纺锤图到底是什么:VWMA 与 VR 的叠加
纺锤图本质上是一种量-价图表,在 MT5 里实时拉取某一货币对的成交量和价格数据绘制,外形接近日本蜡烛图,但多了两个派生量:成交量加权移动平均(VWMA)和成交量比率(VR),整体轮廓像小时候玩的陀螺,所以叫纺锤。 从公开资料看,这类图表相对较新,网上能查到的多半只讲构图,少有实现细节;作者也是收到读者定制需求后才动手,因复杂度高一度搁置。图 1 里蜡烛和纺锤并列,能直观看出 VWMA、VR 只是作为补充维度叠上去,不改变开高低收的呈现。 VWMA 按公式(1)算:周期内「价格×成交量」求和,再除以周期总成交量,相当于给普通 MA 按成交量加了权。VR 按公式(2)算:当前成交量除以选定周期的成交量算术平均值,它没有价格量纲,更适合画成每根纺锤的宽度或独立 tick 量副图。 两个量算完,图就成纺锤形(图 2)。有人会问图 2 的纺锤为何没像图 1 那样填实——这点留到下一节讲绘图原理时拆。外汇与贵金属市场波动剧烈、杠杆高风险大,任何图表形态都只是概率参考,不能直接当成方向信号。
「用位图对象拼出纺锤图」
MQL5 自带的七种绘制类型(线、线段、柱状图、箭头、填充区域、柱形、蜡烛图)都画不出纺锤图,只能自己造绘制风格。没有内置风格设计器,但可以用通用图形函数绕过限制,代价是速度和稳定性要重新权衡。 我们选了 Bitmap 对象来组织自定义风格。缺点很明显:内存占用高、绘制逻辑复杂,容易拖慢刷新;优点也同样关键——能把绘制锁死在特定区域,支持透明通道,还能只取对象的一部分来用,这几点正是纺锤图需要的。 “纺锤”主体是实心填充,绘制复杂度高。以图3的胖菱形为例,画一个就要 4 个 Bitmap 对象(I–IV 块),每种宽度高度组合(Open/Close/VWMA/VR)对应不同角度图片(x1–x4)。单色模型需 360 个位图,双色直接翻倍到 720 副。 若连图表背景一起算,一个纺锤形完整实现要吃 900 个位图;而图2那种非填充快速版,不考虑背景只需 360 个(两色各 180)。非填充版靠两个坐标点(p1、p2)各挂两个对象,利用对称把 IV 替成 I、改左上角坐标,位图量压到 180 同色。 几何上,已知 a=Close-VWMA、b=VWMA-Open、c=Close-Open、d=VR/2,用直角三角形正弦比(公式3.1–3.4)算斜边 e、f 和角 x1、x2,再推 x3 选图。箭头形状同理。开盘价、收盘价、VWMA、VR 这四个值直接决定所有标记距离,MT5 里调出这几根线就能复算角度。
纺锤指标的资源与代码骨架
做这个独立窗口指标前,先备好图形资源:透明背景的 BMP 位图,尺寸 540x540 像素,射线从一个角伸出。前 89 张从左上角出射,角度 1~89 度;后 89 张从左下角出射,角度 91~179 度;1、90、180 度三张分别为 1x540 或 540x1 像素且无需透明。总共 362 张位图,红蓝两色各 181 张(首字母 r/b 区分),其中 1 和 181 号相同。 代码第一部分截止到 OnInit。先用 #property 声明 11 个缓存、4 类绘图形状(1 个柱状+3 条线);再用 #resource 把 362 个位图逐个单独引入——必须一行一个文件,否则加载会失败。输入参数只暴露几个:Magic 数字、绘制类型(纺锤或线)、VR 周期、VR 修正数、VWMA 周期、纺锤数量、VWMA 价格类型。 OnInit 里先校验参数并用输出变量修正,再找最长周期、初始化缓存、按纺锤数量建短数组装图形对象。OnChartEvent 绑定按键 R(ASCII 82)触发重绘,专门应对窗口缩放拉伸。指标窗口检查函数拿 ChartGetInteger / ChartGetDouble 取当前高宽像素与全局变量比对;绘制控制函数算最大 VR 并调 func_picture 创建对象、func_obj_mod 换位图。 OnCalculate 先验 VR/VWMA 周期,填最高最低价缓存后按前文公式算 VR 与 VWMA。func_new_bar 配合窗口检查用,OnDeinit 删对象。外汇与贵金属波动剧烈,这类自绘指标仅辅助判读,实盘前请在 MT5 策略测试器跑历史数据验证开销。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| SPC.mq5 | class=class="str">"cmt">//| Azotskiy Aktiniy ICQ:class="num">695710750 | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Azotskiy Aktiniy ICQ:class="num">695710750" class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property version "class="num">1.00" class="macro">#class="kw">property indicator_separate_window class="macro">#class="kw">property indicator_buffers class="num">11 class="macro">#class="kw">property indicator_plots class="num">4 class=class="str">"cmt">//--- class="macro">#class="kw">property indicator_label1 "Shadow" class="macro">#class="kw">property indicator_type1 DRAW_COLOR_HISTOGRAM2 class="macro">#class="kw">property indicator_color1 clrRed,clrBlue,clrGray class="macro">#class="kw">property indicator_style1 STYLE_SOLID class="macro">#class="kw">property indicator_width1 class="num">1 class=class="str">"cmt">//--- class="macro">#class="kw">property indicator_label2 "Open" class="macro">#class="kw">property indicator_type2 DRAW_LINE class="macro">#class="kw">property indicator_color2 clrRed class="macro">#class="kw">property indicator_style2 STYLE_SOLID class="macro">#class="kw">property indicator_width2 class="num">1 class=class="str">"cmt">//--- class="macro">#class="kw">property indicator_label3 "Close" class="macro">#class="kw">property indicator_type3 DRAW_LINE class="macro">#class="kw">property indicator_color3 clrBlue class="macro">#class="kw">property indicator_style3 STYLE_SOLID class="macro">#class="kw">property indicator_width3 class="num">1 class=class="str">"cmt">//---
◍ 指标第四缓冲线与资源图的声明方式
在 MT5 自定义指标里,第四号绘图缓冲常被用来挂一条辅助线。下面这段声明把该线命名为 VWMA,画成实线、品红色、宽度 1,对应成交量加权移动平均的可视化层。 #property indicator_label4 "VWMA" #property indicator_type4 DRAW_LINE #property indicator_color4 clrMagenta #property indicator_style4 STYLE_SOLID #property indicator_width4 1 资源文件部分用 #resource 把 181 张 b 系列和 181 张 r 系列 BMP 位图编译进 EX5,路径为 \Images\for_SPC\。这种预载方式能让 OnDraw 直接按索引调用图标,避免运行时读盘卡顿;若你只做线型指标,可删掉这 362 行以缩小文件体积。 枚举 type_drawing 给出两种绘制模式:0=纺锤形(spindles)、1=线和柱状图(line_histogram),由 input 的 type_draw 切换。枚举 type_price 则列出 open/high/low/close/middle 五种取价方式,供后续计算引用。 输入参数里 magic_numb 默认 65758473787389,仅作标识用;period_VR=10 为成交量比例周期,correct_VR=4 为修正数,period_VWMA=10 为 VWMA 周期。外汇与贵金属杠杆高、滑点大,改这些数前先在策略测试器用 2020—2023 年日线回测,观察品种在不同波动下的信号密度变化。
class="macro">#class="kw">property indicator_label4 "VWMA" class="macro">#class="kw">property indicator_type4 DRAW_LINE class="macro">#class="kw">property indicator_color4 clrMagenta class="macro">#class="kw">property indicator_style4 STYLE_SOLID class="macro">#class="kw">property indicator_width4 class="num">1 class=class="str">"cmt">//--- 加载资源文件 class="macro">#resource "\\Images\\for_SPC\\b0.bmp"; class="macro">#resource "\\Images\\for_SPC\\b1.bmp"; class="macro">#resource "\\Images\\for_SPC\\b2.bmp"; class="macro">#resource "\\Images\\for_SPC\\b3.bmp"; class=class="str">"cmt">//... class=class="str">"cmt">//... class=class="str">"cmt">//... class="macro">#resource "\\Images\\for_SPC\\b176.bmp"; class="macro">#resource "\\Images\\for_SPC\\b177.bmp"; class="macro">#resource "\\Images\\for_SPC\\b178.bmp"; class="macro">#resource "\\Images\\for_SPC\\b179.bmp"; class="macro">#resource "\\Images\\for_SPC\\b180.bmp"; class="macro">#resource "\\Images\\for_SPC\\r0.bmp"; class="macro">#resource "\\Images\\for_SPC\\r1.bmp"; class="macro">#resource "\\Images\\for_SPC\\r2.bmp"; class="macro">#resource "\\Images\\for_SPC\\r3.bmp"; class=class="str">"cmt">//... class=class="str">"cmt">//... class=class="str">"cmt">//... class="macro">#resource "\\Images\\for_SPC\\r176.bmp"; class="macro">#resource "\\Images\\for_SPC\\r177.bmp"; class="macro">#resource "\\Images\\for_SPC\\r178.bmp"; class="macro">#resource "\\Images\\for_SPC\\r179.bmp"; class="macro">#resource "\\Images\\for_SPC\\r180.bmp"; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 绘图类型 | class=class="str">"cmt">//+------------------------------------------------------------------+ enum type_drawing { spindles=class="num">0, class=class="str">"cmt">// 纺锤形 line_histogram=class="num">1, class=class="str">"cmt">// 线和柱状图 }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 价格类型 | class=class="str">"cmt">//+------------------------------------------------------------------+ enum type_price { open=class="num">0, class=class="str">"cmt">// Open high=class="num">1, class=class="str">"cmt">// High low=class="num">2, class=class="str">"cmt">// Low close=class="num">3, class=class="str">"cmt">// Close middle=class="num">4, class=class="str">"cmt">// Middle }; class=class="str">"cmt">//--- 输入参数 class="kw">input class="type">long magic_numb=class="num">65758473787389; class=class="str">"cmt">// Magic 数字 class="kw">input type_drawing type_draw=class="num">0; class=class="str">"cmt">// 指标绘制类型 class="kw">input class="type">int period_VR=class="num">10; class=class="str">"cmt">// 成交量比例周期 class="kw">input class="type">int correct_VR=class="num">4; class=class="str">"cmt">// 成交量比例修正数 class="kw">input class="type">int period_VWMA=class="num">10; class=class="str">"cmt">// 成交量加权移动平均周期
「指标变量声明与初始化兜底」
把成交量比例(VR)和成交量加权移动平均(VWMA)做成 MT5 自定义指标时,先要在全局区把输入参数和输出缓存都摊开。下面这段代码里,spindles_num 默认 1000 控制纺锤形数量,type_price_VWMA 默认 0 表示用开盘价算 VWMA,注释里列了 open=0 到 middle=4 的映射,改这个数就能换计算基准。 初始化函数 OnInit 里没有信任用户输入:period_VR、correct_VR、period_VWMA、spindles_num 任意一个 ≤0,都会把内部变量强制改成 10 并弹 Alert 提示。也就是说你手滑填了 0 或负数,指标不会崩,只是默默用 10 周期跑,回测时若发现 VR 周期不对劲,先查是不是被这段兜底逻辑改过。 图表参数那组变量(win_price_max_ext、win_height_pixels_ext 等)留着给后续绘图算坐标用,Buff_up / Buff_down / Buff_color_up_down 则是直方图上下沿和颜色的独立缓存。外汇和贵金属波动大、杠杆高,这类指标仅作量价参考,实盘信号失效概率不低,上手前务必在策略测试器里用历史数据验一遍。
class="kw">input class="type">int spindles_num=class="num">1000; class=class="str">"cmt">// 纺锤形数量 class="kw">input type_price type_price_VWMA=class="num">0; class=class="str">"cmt">// 用于绘制成交量加权移动平均的价格类型 class=class="str">"cmt">// open=class="num">0; high=class="num">1; low=class="num">2; close=class="num">3; middle=class="num">4 class=class="str">"cmt">//--- 输出参数 class="type">int ext_period_VR=class="num">0; class="type">int ext_correct_VR; class="type">int ext_period_VWMA=class="num">0; class="type">int ext_spin_num=class="num">0; class="type">int long_period=class="num">0; class=class="str">"cmt">//--- 图表参数变量 class="type">class="kw">double win_price_max_ext=class="num">0; class=class="str">"cmt">// 图表最大值 class="type">class="kw">double win_price_min_ext=class="num">0; class=class="str">"cmt">// 图表最小值 class="type">class="kw">double win_height_pixels_ext=class="num">0; class=class="str">"cmt">// 高度(像素) class="type">class="kw">double win_width_pixels_ext=class="num">0; class=class="str">"cmt">// 宽度(像素) class="type">class="kw">double win_bars_ext=class="num">0; class=class="str">"cmt">// 宽度(以柱形数计) class=class="str">"cmt">//--- 辅助变量 class="type">int end_bar; class=class="str">"cmt">//--- 指标缓存 class="type">class="kw">double Buff_up[]; class=class="str">"cmt">// 直方图上方坐标点缓存 class="type">class="kw">double Buff_down[]; class=class="str">"cmt">// 直方图下方坐标点缓存 class="type">class="kw">double Buff_color_up_down[]; class=class="str">"cmt">// 直方图颜色缓存 class="type">class="kw">double Buff_open_ext[]; class=class="str">"cmt">// 开盘价输出缓存 class="type">class="kw">double Buff_close_ext[]; class=class="str">"cmt">// 收盘价输出缓存 class="type">class="kw">double Buff_VWMA_ext[]; class=class="str">"cmt">// 成交量加权移动平均输出缓存 class="type">class="kw">double Buff_open[]; class=class="str">"cmt">// 开盘价缓存 class="type">class="kw">double Buff_close[]; class=class="str">"cmt">// 收盘价缓存 class="type">class="kw">double Buff_VWMA[]; class=class="str">"cmt">// 成交量加权移动平均缓存 class="type">class="kw">double Buff_VR[]; class=class="str">"cmt">// 成交量比例缓存 class="type">class="kw">double Buff_time[]; class=class="str">"cmt">// 柱形开始时间缓存 class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 自定义指标初始化函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- 检查输入变量 if(period_VR<=class="num">0) { ext_period_VR=class="num">10; class=class="str">"cmt">// 改变变量值 Alert("Volume Ratio formation period was class="kw">input incorrectly and has been changed."); } else ext_period_VR=period_VR; if(correct_VR<=class="num">0) { ext_correct_VR=class="num">10; class=class="str">"cmt">// 改变变量值 Alert("Volume Ratio correction number was class="kw">input incorrectly and has been changed."); } else ext_correct_VR=correct_VR; if(period_VWMA<=class="num">0) { ext_period_VWMA=class="num">10; class=class="str">"cmt">// 改变变量值 Alert("Volume Weighted Moving Average formation period was class="kw">input incorrectly and has been changed."); } else ext_period_VWMA=period_VWMA; if(spindles_num<=class="num">0) {