Erik Nayman 绳索指标:从多空力度拉锯读懂趋势基础(基础篇)
(1/3)·多数交易者盯着均线金叉却说不清谁在控盘,绳索指标用力度差把多空拉锯摊开在图上
不少人把指标当黑盒,加载完只看颜色红绿就下单,却不知道背后算的是相邻周期的多空力度差。绳索指标的价值不在信号线本身,而在它把买卖双方的拉锯量化成了可比较的数值。这篇先铺开原理和例程,后续才谈策略和实盘。
绳索指标的来路与出处
绳索指标(Rope)由 Erik Nayman 提出,思路是用多条不同周期的移动平均线拧成一股,观察价格与这股‘绳’的缠绕关系来判断趋势强弱。该实现版本面向 MetaTrader 5 平台,属于第三方开源指标的移植思路。 公开示例帖记录于 2016 年 9 月 29 日 10:34 发布,累计查看 4029 次、评论 2 条,作者署名 Alexander Puzikov。这个冷门但被反复引用的数据点说明:即便小众指标,在 MT5 社区也有稳定检索量,值得手动验证一遍。 外汇与贵金属品种波动受杠杆与隔夜风险影响,绳索信号仅作概率参考,实盘前请在 MT5 策略测试器用历史数据跑一遍再决定参数。
「绳索指标的三段式技术路径」
原文把「绳索」指标的开发到实盘落地拆成三块:先讲指标创建与计算的原理并给例程代码,再讲实盘怎么用这个指标搭 EA,最后专门做输入参数优化。这条路径对 MT5 用户很直接——你想验证一个自定义指标靠不靠谱,照这个顺序走一遍就能排除大部分纸上谈兵。 第一章聚焦原理和代码,意味着你不是黑盒调用,而是能看清每条线是怎么算出来的;第二章把指标接进 EA,是把信号变成可执行订单的关键一步;第三章的优化则决定这套逻辑在 EURUSD 或 XAUUSD 上是不是只是拟合了历史。外汇与贵金属波动带杠杆,回测漂亮不等于实盘概率占优,参数过拟合风险始终在。
◍ 绳索指标的多空力度拆解
Erik L. Nayman 在 1999 年出版的交易员小百科里提出用「绳索」衡量多空拉锯:核心是把覆盖周期内的价格变化速度、买卖数量、变化规模分开算,再比谁占上风。指标底层只认最后已知价当报价,规模就是相邻两笔报价(当前减之前)的差值,速度由多笔成交流水测定。 静态层面先算力度:多头力度 BuF 是周期内所有正变化的加总(SPCi),空头力度 BeF 是负变化加总(SNCi)。谁数值高,那段周期内哪边主导,外汇和贵金属这种高杠杆品种里方向误判的回撤风险会被放大。 光看静态不够,动态看相邻柱线差值才敏感。比如 BuF>BeF 且 (BuF1-BuF0)>(BeF1-BeF0),说明整体多头力度还在增长;反过来差值缩小就是多头力度下降。把「前一根索引0、当前索引1」这套比较套到活力(变化笔数 NPCi/NNCi)和技巧(力度÷活力)上,得到三维度的动态评价。 作者最终用三个参数同步过关才定性趋势:BuF>BeF、BuV>BeV、BuS>BeS 且动态同向,才倾向只做多单。本文实现的指标只取了静态算法,但你在 MT5 里把动态比较补进源码,能明显提前半根到一根柱捕捉转向。
绳索指标的构造逻辑与双模显示
绳索指标采用线性与直方图两套呈现方式:线性法把多空计算值合并成一条主线,直方图则把多头、空头力度分开画,便于直接对比谁占上风。代码里用 #property 定义了 12 个缓存区、5 个绘图区,其中多头直方图配了 4 级绿色——clrDarkGreen 代表仅买入高确认,clrGray 代表买单禁止,颜色本身就是趋势强度的速读表。 原文给出的判定很直白:当 BuF>BeF、BuV>BeV、BuS>BeS 三个条件同时成立,多头全面占优,只考虑买单;反过来三者皆反,则空头首选。匹配的维度越多,趋势倾向越强,这是用概率而非绝对信号来看市。 OnInit 里有个容易踩坑的点:图表周期切换或指标重置时,必须把 prev_rates_total 和 _tm_prev 清零。前者保留上一次 rates_total,和当前柱数比对能识别是否重算;后者记录上次计算到的柱线时间。不清零的话,加载历史数据出现缺口时,图显示可能错乱。 OnCalculate 中按书里第 147 页的逻辑,用收盘价(price=PRICE_CLOSE)算相邻价差,正差看涨、负差看空;开盘价取前一根已算柱的收盘。以 _period=5 为例,多头均值写法是 if(total_bull>0) Buffer_calc_bull[i]=sum_bull/total_bull;,空头对称处理,再汇成每根柱上的“绳索”值送进颜色缓存区 Buffer_mainline_color[]。 外汇与贵金属波动剧烈、杠杆风险高,这套颜色确认仅作多空倾向参考,实盘前请在 MT5 用 M1 小周期跑一下,max_bars 限制能明显提速,别直接拿来当入场指令。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| RopebyEricNaiman.mq5 | class=class="str">"cmt">//| 版权 class="num">2015, MetaQuotes 软件公司| class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "版权 class="num">2015, MetaQuotes 软件公司" class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property description "RopebyEricNaiman by Im_hungry([MQL5官方文档] class="macro">#class="kw">property description "RopebyEricNaiman - 显示市场动作的期望方向和期望力量。" class="macro">#class="kw">property version "class="num">1.00" class="macro">#class="kw">property strict class=class="str">"cmt">//--- 包含来自 MovingAverages.mqh 文件的均值计算函数 class="macro">#include <MovingAverages.mqh> class=class="str">"cmt">//--- class="macro">#class="kw">property indicator_separate_window class=class="str">"cmt">// 设置在单独窗口绘制 class="macro">#class="kw">property indicator_buffers class="num">12 class=class="str">"cmt">// 设置 class="num">12 个指标缓存区 class="macro">#class="kw">property indicator_plots class="num">5 class=class="str">"cmt">// 设置 class="num">5 个指标绘图区 class=class="str">"cmt">//--- 多头直方图 class="macro">#class="kw">property indicator_label1 "BULL" class="macro">#class="kw">property indicator_type1 DRAW_COLOR_HISTOGRAM class=class="str">"cmt">// class="num">0 - clrDarkGreen - 颜色索引 "仅买入", 买单具有高级别确认 class=class="str">"cmt">// class="num">1 - clrMediumSeaGreen - 颜色索引 "买单允许", 买单具有平均级别确认 class=class="str">"cmt">// class="num">2 - clrLightGreen - 颜色索引 "买单允许", 买单具有低级别确认 class=class="str">"cmt">// class="num">3 - clrGray - 颜色索引 "买单禁止" class="macro">#class="kw">property indicator_color1 clrDarkGreen,clrMediumSeaGreen,clrLightGreen,clrGray class="macro">#class="kw">property indicator_style1 STYLE_SOLID class="macro">#class="kw">property indicator_width1 class="num">2 class=class="str">"cmt">//--- 空头直方图 class="macro">#class="kw">property indicator_label2 "BEAR" class="macro">#class="kw">property indicator_type2 DRAW_COLOR_HISTOGRAM class=class="str">"cmt">// class="num">0 - clrDarkRed - 颜色索引 "仅卖出", 卖单具有高级别确认 class=class="str">"cmt">// class="num">1 - clrIndianRed - 颜色索引 "卖出允许", 卖单具有平均级别确认
「多空颜色映射与输入参数拆解」
这段指标声明把第 2 条绘图线做成四色直方图:clrDarkRed 代表高级别卖确认,clrIndianRed 是低级别卖确认,clrLightPink 对应「卖出允许」的低级确认,clrGray 则是卖出禁止。你在 MT5 里加载后,直接从颜色就能读出当前柱线的空方权限等级,不用去翻缓冲区数值。 第 3 条线是指标主线,用 DRAW_COLOR_LINE 画成三色:clrDarkGreen=仅买入(高级确认)、clrDarkRed=仅卖出(高级确认)、clrGray=无限制确认,线宽统一设 2。这条线才是后面快慢均线叠加的基准。 输入参数里几个值值得直接抄去试:_period=76、_price=PRICE_CLOSE、line_deviation=3.0(所有主线和均线数值会乘这个偏移量,让图更清爽)。max_bars=0 表示不限制历史计算深度,老机器上跑 EURUSD 可能卡,可改成 500 限速。 快慢均线默认都不画(draw_MA_fast=false、draw_MA_slow=false)。要开就改 true:快线 period_MA_fast=25、慢线 period_MA_slow=143,都是 MODE_SMA 算在指标值上而非价格上。143 周期慢线在 XAUUSD 的 H1 上约覆盖 6 天,交叉信号偏少但假突破概率可能更低。外汇和贵金属杠杆高,参数验证请用模拟盘。
class="macro">#class="kw">property indicator_color2 clrDarkRed,clrIndianRed,clrLightPink,clrGray class="macro">#class="kw">property indicator_style2 STYLE_SOLID class="macro">#class="kw">property indicator_width2 class="num">2 class="macro">#class="kw">property indicator_label3 "主线" class="macro">#class="kw">property indicator_type3 DRAW_COLOR_LINE class="macro">#class="kw">property indicator_color3 clrDarkGreen,clrDarkRed,clrGray class="macro">#class="kw">property indicator_style3 STYLE_SOLID class="macro">#class="kw">property indicator_width3 class="num">2 class="macro">#class="kw">property indicator_label4 "快速均线" class="macro">#class="kw">property indicator_type4 DRAW_LINE class="macro">#class="kw">property indicator_color4 clrAqua class="macro">#class="kw">property indicator_style4 STYLE_SOLID class="macro">#class="kw">property indicator_width4 class="num">1 class="macro">#class="kw">property indicator_label5 "慢速均线" class="macro">#class="kw">property indicator_type5 DRAW_LINE class="macro">#class="kw">property indicator_color5 clrYellow class="macro">#class="kw">property indicator_style5 STYLE_SOLID class="macro">#class="kw">property indicator_width5 class="num">1 class="kw">input class="type">class="kw">string section_1="___ 主要设置"; class="kw">input class="type">bool draw_histogram=true; class="kw">input class="type">bool draw_line=true; class="kw">input class="type">int _period=class="num">76; class="kw">input ENUM_APPLIED_PRICE _price=PRICE_CLOSE; class="kw">input class="type">int max_bars=class="num">0; class="kw">input class="type">class="kw">double line_deviation=class="num">3.0; class="kw">input class="type">class="kw">string section_2="___ 快速均线"; class="kw">input class="type">bool draw_MA_fast=class="kw">false; class="kw">input class="type">int period_MA_fast=class="num">25; class="kw">input ENUM_MA_METHOD method_MA_fast=MODE_SMA; class="kw">input class="type">class="kw">string section_3="___ 慢速均线"; class="kw">input class="type">bool draw_MA_slow=class="kw">false; class="kw">input class="type">int period_MA_slow=class="num">143; class="kw">input ENUM_MA_METHOD method_MA_slow=MODE_SMA;
◍ 缓存区与初始化收尾怎么挂
在 MT5 自定义指标里,把显示精度和短名先钉死,能省掉运行时很多奇怪的四舍五入错位。下面这段取当前品种小数位并设给指标,再把窗口名写成 RopebyEricNaiman,属于标准 OnInit 收口动作。 _digit=(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS); 拿品种小数位;IndicatorSetInteger(INDICATOR_DIGITS,_digits) 让指标按同精度画;IndicatorSetString(INDICATOR_SHORTNAME,"RopebyEricNaiman") 决定子窗口标题。 SetIndexBuffer 一共挂了 12 个缓冲区:0~5 是绘图与颜色(多头/空头直方图各占数据+颜色两组,主线同理),6~7 是快慢均线数据,8~11 标了 INDICATOR_CALCULATIONS 只参与计算不画线。区分 COLOR_INDEX 与 CALCULATIONS 很关键,前者控色后者纯中间量,混用会导致重绘异常。 _tm_prev 和 prev_rates_total 清零放在返回 INIT_SUCCEEDED 前,保证首根 K 线从头算。OnCalculate 的参数表里 prev_calculated 就是上轮已处理柱数,配合 rates_total 可做增量计算,外汇与贵金属波动大,增量写错容易在跳空时吐脏数据,实盘前建议在 MT5 策略测试器用 EURUSD 1 分钟跑一遍看缓冲是否越界。
_digits=(class="type">int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS); class=class="str">"cmt">//---指标显示精度 IndicatorSetInteger(INDICATOR_DIGITS,_digits); class=class="str">"cmt">//--- 设置指标名称, 显示在指标窗口 IndicatorSetString(INDICATOR_SHORTNAME,"RopebyEricNaiman"); class=class="str">"cmt">//--- INDICATOR_DATA - 保存绘图数据 class=class="str">"cmt">//--- INDICATOR_COLOR_INDEX - 保存颜色索引 class=class="str">"cmt">//--- INDICATOR_CALCULATIONS - 保存不参与绘图的中间计算数据 SetIndexBuffer(class="num">0,Buffer_main_bull,INDICATOR_DATA); class=class="str">"cmt">// 多头直方图的数据缓存区 SetIndexBuffer(class="num">1,Buffer_color_bull,INDICATOR_COLOR_INDEX); class=class="str">"cmt">// 多头颜色数据缓存区 SetIndexBuffer(class="num">2,Buffer_main_bear,INDICATOR_DATA); class=class="str">"cmt">// 空头直方图的数据缓存区 SetIndexBuffer(class="num">3,Buffer_color_bear,INDICATOR_COLOR_INDEX); class=class="str">"cmt">// 空头颜色数据缓存区 SetIndexBuffer(class="num">4,Buffer_mainline,INDICATOR_DATA); class=class="str">"cmt">// 指标主线数据缓存区 SetIndexBuffer(class="num">5,Buffer_mainline_color,INDICATOR_COLOR_INDEX); class=class="str">"cmt">// 指标主线颜色数据缓存区 SetIndexBuffer(class="num">6,Buffer_MAfast,INDICATOR_DATA); class=class="str">"cmt">// 快速均线数据缓存区 SetIndexBuffer(class="num">7,Buffer_MAslow,INDICATOR_DATA); class=class="str">"cmt">// 慢速均线数据缓存区 SetIndexBuffer(class="num">8,Buffer_calc,INDICATOR_CALCULATIONS); class=class="str">"cmt">// 价格计算数据缓存区 SetIndexBuffer(class="num">9,Buffer_calc_bull,INDICATOR_CALCULATIONS); class=class="str">"cmt">// 多头计算数据缓存区 SetIndexBuffer(class="num">10,Buffer_calc_bear,INDICATOR_CALCULATIONS); class=class="str">"cmt">// 空头计算数据缓存区 SetIndexBuffer(class="num">11,Buffer_calcLINE,INDICATOR_CALCULATIONS); class=class="str">"cmt">// 均线计算数据缓存区 class=class="str">"cmt">//--- 最后计算过的柱线时间和 prev_rates_total(rates_total 前一调用 // rates_total = 数组大小 price[]) 清零 _tm_prev=class="num">0; prev_rates_total=class="num">0; class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); } for(class="type">int i=class="num">1; i<bars_calc && !IsStopped(); i++) { ... class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 自定义指标迭代函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnCalculate(class="kw">const class="type">int rates_total, class=class="str">"cmt">// price[] 数组大小 class="kw">const class="type">int prev_calculated,class=class="str">"cmt">// 前一次调用处理过的柱线 class="kw">const class="type">class="kw">datetime &time[], class="kw">const class="type">class="kw">double &open[], class="kw">const class="type">class="kw">double &high[], class="kw">const class="type">class="kw">double &low[], class="kw">const class="type">class="kw">double &close[], class="kw">const class="type">long &tick_volume[], class="kw">const class="type">long &volume[],