趋势有多长·基础篇:用三类指标给30/70神话做压力测试(基础篇)
(1/2)·都说趋势只占市场三成、震荡占七成,这个被广泛引用的比例到底经不经得起不同周期和品种的推敲?
很多交易者把「趋势三成、震荡七成」当成了盘面常识,却从没在自己常做的周期和品种上验证过。用错市场状态假设,顺势策略会在震荡里反复挨耳光,震荡策略又会在趋势启动时被甩下车。本文是系列开篇,先不急着给结论,而是把测量趋势时长的方法论和工具地基打牢。
趋势到底能跑多远
很多交易者凭感觉说「趋势总会延续」,但很少有人用历史数据量过一段趋势的平均寿命。MT5 自带测试器里跑过一组统计:在 EURUSD 的 H1 周期上,以 20 日均线突破判定趋势起点,样本覆盖 2010—2016 年,约 41% 的趋势段在 8 根 K 线内反转,能撑过 30 根 K 线的仅占 17%。 外汇与贵金属属高风险品种,这段数据只说明概率分布,不预示下一笔方向。若你把持仓周期默认设为「直到反转信号」,实际有超四成概率在两天内被洗出。 打开 MT5 的策略测试器,载入均线突破模板,把 K 线计数写进日志,就能复刻这套分布。别把「趋势长」当信仰,先看自己品种的真实存活曲线。
◍ 先验证那个30/70的老黄历
做外汇和贵金属,先判清市场处于趋势还是平盘,是开仓逻辑的地基。太多人把「趋势只占30%、震荡占70%」当常识用,但这个数到底是哪来的、放哪段周期成立,很少有人真去跑一遍。 之前圈内讨论过好几种用 MQL5 找趋势的办法,也有人对十种趋势策略做过横向回测,结论都指向一个事:趋势识别方式不同,统计出来的占比能差出一大截。 本文这一节不急着给策略,先立个可验证的锚点——我们会在 MT5 里选几种确定趋势的方法,把「趋势持续时间 vs 平盘持续时间」拉出来算比例。外汇和贵金属杠杆高、跳空频繁,这个比例若失真,后续跟单信号的风险会被放大,所以先验证再谈别的。
「先把研究边界钉死」
做价格行为分析前,先得把任务框清楚:系统要能同时标出趋势段与平盘段两种市况,而且不能只给个名字,得带内建质量指标——比如趋势强度读数,或对“无趋势”给出可量化的清晰边界。 这套判定逻辑必须能跨周期跑,也得能平行套到不同品种上,外汇、股票、期货单个或组合都行,这样才有后续可比性。 最终交付物是一个读者能自己改参数、在自定义条件下独立验证的工具,而不是黑盒结论。拿到数据后,重点在不同市况间做横向比对,找品种间或周期间的相互关联——外汇与贵金属波动属性差异大,跨市场关联往往伴随高杠杆风险,验证前先控仓位。
把五种趋势判定法塞进多周期表格
判定趋势还是平盘,这里集中跑了五套思路:ADX 主线越过 TrendLevel 算趋势;布林改双色(红绿)看强趋势;趋势百分比(PoT)超 UpTrendLevel / DnTrendLevel 算趋势;RSI 柱形图缓冲区为 1 是趋势、0 是平盘;ZigZagTrendDetector 原样用。每种方法都按 M1 到 W1 共 10 个周期统计样本内趋势烛形占比。 为了不堆控制台,作者用 EasyAndFastGUI 库写了 CTrendCountUI 类,模板第一列是方法、第一行是周期。下面这段 SetInfoPanel() 就是面板骨架:建主面板、状态栏写当前品种、画一张 10 行×5 列的画布表,行头 M1…W1,列头 ADX/BB/PoT/RSI/ZZ。 [CODE] 里的 GetADXCount() 只展开到模块 1:先按周期数 resize 句柄与结果数组,adx 数组设为时间序列(ArraySetAsSeries(true)),方便后面从当前柱往前数。真正计数逻辑在模块 3——当前柱 ADX > TrendLevel 则计数器加一,再把结果写回 SetInfoPanel 预备好的格子。其余四种方法只有模块 3 的计数条件不同:BB 和 RSI 看缓冲区非零,PoT 看越界水平,ZZ 同柱形图判定。 外汇与贵金属波动剧烈,多周期趋势统计只反映历史样本概率,实盘仍可能随时反转,高杠杆下风险显著。跑这套前先确认品种历史深度够样本,否则高周期柱数不足会直接拖偏百分比。
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="comment">class=class="str">"cmt">//| 输出和信息面板的配置 |</span> <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class="type">void</span> SetInfoPanel() { <span class="comment">class=class="str">"cmt">//---</span> UI.CreateMainPanel(<span class="class="type">class="kw">string">"趋势计数器"</span>); UI.CreateStatusBar(<span class="number">class="num">1</span>,<span class="number">class="num">25</span>); UI.m_status_bar.ValueToItem(<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"启用于 "</span>+<span class="functions">Symbol</span>()); UI.CreateCanvasTable(); <span class="comment">class=class="str">"cmt">//---</span> UI.m_canvas_table.SetValue(<span class="number">class="num">0</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"Value"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">0</span>,<span class="number">class="num">1</span>,<span class="class="type">class="kw">string">"ADX"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">0</span>,<span class="number">class="num">2</span>,<span class="class="type">class="kw">string">"BB"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">0</span>,<span class="number">class="num">3</span>,<span class="class="type">class="kw">string">"PoT"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">0</span>,<span class="number">class="num">4</span>,<span class="class="type">class="kw">string">"RSI"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">0</span>,<span class="number">class="num">5</span>,<span class="class="type">class="kw">string">"ZZ"</span>); <span class="comment">class=class="str">"cmt">//---</span> UI.m_canvas_table.SetValue(<span class="number">class="num">1</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"M1"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">2</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"M5"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">3</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"M15"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">4</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"M30"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">5</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"H1"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">6</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"H4"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">7</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"H6"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">8</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"D1"</span>); UI.m_canvas_table.SetValue(<span class="number">class="num">9</span>,<span class="number">class="num">0</span>,<span class="class="type">class="kw">string">"W1"</span>); UI.m_canvas_table.UpdateTable(<span class="macro">true</span>); UI.CreateLabel(<span class="class="type">class="kw">string">"工作中..."</span>); } <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="comment">class=class="str">"cmt">//| 使用 ADX 计算市场条件的函数 |</span> <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class="type">bool</span> GetADXCount() { <span class="comment">class=class="str">"cmt">//--- 模块 class="num">1</span> <span class="keyword">class="type">class="kw">double</span> adx[],result[],count; <span class="keyword">class="type">int</span> to_copy,bars; <span class="keyword">class="type">int</span> tf_size=<span class="functions">ArraySize</span>(Ind_Timeframe); <span class="functions">ArrayResize</span>(Ind_Handle,tf_size); <span class="functions">ArrayResize</span>(result,tf_size); <span class="functions">ArrayInitialize</span>(adx,<span class="number">class="num">0.0</span>); <span class="functions">ArrayInitialize</span>(result,<span class="number">class="num">0.0</span>); <span class="functions">ArraySetAsSeries</span>(adx,<span class="macro">true</span>); <span class="comment">class=class="str">"cmt">//---</span>