蓄势与爆发:三均线粘合突破策略源码深度解析

在技术分析的经典格言中,有一句话被无数交易者奉为圭臬:“横有多长,竖有多高”。

市场的常态是 80% 的时间处于震荡无序的"蓄势"阶段,只有 20% 的时间在走单边"爆发"趋势。绝大多数顺势交易者之所以倒下,是因为他们把子弹打光在了漫长的震荡期。

今天我们将深度拆解一份基于 TBQuant 编写的"三线合一线趋势爆发策略"。这套系统巧妙地避开了震荡市的无序厮杀,它通过精准的数学公式量化了"均线粘合(蓄势)""均线发散(爆发)"这两个极端状态,只在暴风雨来临的那一刻悍然拔剑。


一、 量化"暴风雨前的宁静":均线粘合度算法

主观交易者看盘时,常说"均线纠缠在一起了",但这在程序化交易中无法直接执行。策略的第一步,就是赋予"粘合"一个冰冷且极其精确的数学定义。

逻辑推演: 系统同时运行短(5)、中(10)、长(20)三条均线。在任何一个 K 线时刻,系统都会找出这三条均线中的最高值和最低值,并计算出它们的平均值。 所谓"粘合度(Coincide Rate)“,就是(最高值 - 最低值)/ 平均值。如果这个偏离幅度小于预设的极小阈值(如 2%),系统就判定市场进入了极度压缩的"冰点状态”。

核心源码:

// 1. 找出三线中的最大值、最小值与平均值
MA_Max = Max(MA_Short, Max(MA_Middle, MA_Long));
MA_Min = Min(MA_Short, Min(MA_Middle, MA_Long));
MA_Avg = (MA_Short + MA_Middle + MA_Long) / 3;

// 2. 计算极差与平均值的比例,得出“粘合度”
If(MA_Avg > 0)
{
    Coincide_Rate = (MA_Max - MA_Min) / MA_Avg;
}

// 3. 判断是否满足粘合条件 (Coincide_Threshold = 0.02 即 2%)
IsCoinciding = Coincide_Rate <= Coincide_Threshold;

// 4. 统计极度压缩状态持续的时间
If(IsCoinciding)
{
    Coincide_Count = Coincide_Count + 1; // 记录粘合了多少根K线
    HasCoincided = True;                 // 盖章确认:本轮行情经历过充分蓄势
}


二、 点燃趋势的导火索:发散与时间共振

明确了蓄势状态后,策略并没有着急进场,因为"盘久必跌"或"盘久必涨"都是概率事件。策略需要看到确凿的爆发证据

逻辑推演: 触发开仓必须同时满足三个苛刻的条件,缺一不可:

  1. 曾经压缩过HasCoincided 为真):过滤掉没有经过盘整、直接V型反转的脉冲行情。

  2. 压缩够久Coincide_Count >= 3):过滤掉短暂的停顿,只做充分换手后的突破。

  3. 完美发散(多头排列或空头排列):短均线 > 中均线 > 长均线,代表短期资金、中期资金、长期资金的做多意愿达成高度一致,形成合力。

核心源码:

// 1. 判定多空力量的有序排列 (均线发散)
Bull_Diverge = MA_Short > MA_Middle And MA_Middle > MA_Long; // 多头完美发散
Bear_Diverge = MA_Short < MA_Middle And MA_Middle < MA_Long; // 空头完美发散

// 2. 核心开仓信号:发散 + 经历过粘合 + 粘合时间达标
Long_Signal = Bull_Diverge And HasCoincided And Coincide_Count >= Coincide_Bars;
Short_Signal = Bear_Diverge And HasCoincided And Coincide_Count >= Coincide_Bars;

// 3. 执行开多逻辑
If(Long_Signal And MarketPosition <= 0)
{
    Buy(Lots, BuyPrice);
    // ... 记录入场状态
}


三、 进退有度的立体防线:四维出场机制

在趋势突破策略中,"假突破"是不可避免的副产品。为了应对复杂多变的市场走势,策略在防守端布置了由四道逻辑交织而成的立体防线。

逻辑推演: 一旦持仓,系统不仅有刚性的跳数止损和止盈,还引入了动态追踪机制。

  • 防线一(主动认错): 如果多头持仓期间,短期均线下穿了中期均线(死叉),说明爆发动能衰竭,无需等待打止损,立刻主动平仓。

  • 防线二(底线止损): 进场即设 20 跳固定止损,防止遇到突发黑天鹅。

  • 防线三(目标止盈): 行情超预期顺利,达到 40 跳直接落袋为安。

  • 防线四(回撤止盈): 这是最精妙的一环。记录持仓期间的最高价,如果距离最高价回撤了"目标止盈的一半"(20跳),说明趋势可能见顶,提前截断利润。

核心源码:

// --- 以平多条件为例 ---
If(MarketPosition > 0)
{
    Bool Close_Long = False;

    // 条件 1: 均线死叉 (动能反转,主动撤退)
    If(CrossUnder(MA_Short, MA_Middle))
    {
        Close_Long = True;
    }

    // 条件 2: 刚性止损 (跌破入场价 20 跳)
    If(UseStopLoss == 1 And Close - EntryPrice < -StopLoss_Tick * PriceTick)
    {
        Close_Long = True;
    }

    // 条件 3: 刚性止盈 (涨超入场价 40 跳)
    If(UseTakeProfit == 1 And Close - EntryPrice > TakeProfit_Tick * PriceTick)
    {
        Close_Long = True;
    }

    // 条件 4: 追踪回撤止盈 (从最高点回撤 20 跳,即止盈目标的一半)
    If(UseTakeProfit == 1 And Highest_Price - Close > TakeProfit_Tick * PriceTick * 0.5)
    {
        Close_Long = True;
    }

    // 触发任意条件即平仓
    If(Close_Long)
    {
        Sell(0, SellPrice);
    }
}


结语

从"粘合"的冰点,到"发散"的沸点,"三线合一线策略"用极其凝练的代码,描绘了市场多空力量从分歧走向统一的全过程。

它摒弃了主观画线带来的视觉误差,用冰冷的比例公式(极差/均值)锁定了市场波动的下限。对于崇尚"不开仓则已,一开仓必见血"的突破型交易者来说,这份源码提供了一个逻辑严密、进退有据的绝佳实战框架。

//------------------------------------------------------------------------
// 简称:ThreeLine_Coincide
// 名称:三线合一线趋势爆发策略
// 类别:趋势跟踪
// 描述:三均线粘合后发散时开仓,捕捉趋势启动点
//------------------------------------------------------------------------

Params
    // ========== 均线参数 ==========
    Numeric MA_Short_Period(5);       // 短期均线
    Numeric MA_Middle_Period(10);     // 中期均线
    Numeric MA_Long_Period(20);       // 长期均线

    // ========== 粘合判断参数 ==========
    Numeric Coincide_Threshold(0.02); // 粘合阈值 (2%=三线最大偏离不超过 2%)
    Numeric Coincide_Bars(3);         // 粘合持续最少 K 线数

    // ========== 发散确认参数 ==========
    Numeric Diverge_Threshold(0.01);  // 发散阈值 (1%=确认趋势启动)

    // ========== 资金参数 ==========
    Numeric Fund(1000000);            // 初始资金
    Numeric RiskPercent(0.2);         // 单笔风险比例
    Numeric PriceTick(1);             // 最小变动价位 (根据品种设置)
    Numeric PriceOffset(1);           // 委托偏移跳数

    // ========== 止损止盈 ==========
    Numeric StopLoss_Tick(20);        // 止损跳数
    Numeric TakeProfit_Tick(40);      // 止盈跳数
    Numeric UseStopLoss(1);           // 是否使用止损 (1=使用,0=不使用)
    Numeric UseTakeProfit(1);         // 是否使用止盈 (1=使用,0=不使用)

Vars
    // ========== 均线序列 ==========
    Series<Numeric> MA_Short;
    Series<Numeric> MA_Middle;
    Series<Numeric> MA_Long;

    // ========== 粘合判断 ==========
    Series<Numeric> MA_Max;           // 三线最大值
    Series<Numeric> MA_Min;           // 三线最小值
    Series<Numeric> MA_Avg;           // 三线平均值
    Series<Numeric> Coincide_Rate;    // 粘合度 (最大偏离/平均值)
    Series<Bool> IsCoinciding;        // 是否处于粘合状态
    Series<Integer> Coincide_Count;   // 粘合持续 K 线数

    // ========== 发散判断 ==========
    Series<Bool> Bull_Diverge;        // 多头发散 (短>中>长)
    Series<Bool> Bear_Diverge;        // 空头发散 (短<中<长)

    // ========== 交易信号 ==========
    Series<Bool> Long_Signal;         // 做多信号
    Series<Bool> Short_Signal;        // 做空信号
    Series<Bool> HasCoincided;        // 是否经历过粘合

    // ========== 持仓记录 ==========
    Series<Integer> EntryBar;
    Series<Numeric> EntryPrice;
    Series<Integer> LastTradeBar;
    Series<Numeric> Signal_Buy;
    Series<Numeric> Signal_Sell;
    Series<Numeric> Signal_SellShort;
    Series<Numeric> Signal_BuyCover;

    // ========== 普通变量 ==========
    Integer Lots;
    String strLog;
    Numeric BuyPrice;
    Numeric SellPrice;
    Numeric Highest_Price;            // 持仓期间最高价
    Numeric Lowest_Price;             // 持仓期间最低价

Events
    OnInit()
    {
        Range[0:DataCount-1]
        {
            AddDataFlag(Enum_Data_RolloverBackWard());
            AddDataFlag(Enum_Data_RolloverRealPrice());
            AddDataFlag(Enum_Data_AutoSwapPosition());
            SetOrderMap2MainSymbol();
        }

        LastTradeBar = -100;
        Coincide_Count = 0;
        HasCoincided = False;
        Highest_Price = 0;
        Lowest_Price = 999999;

        Print("═══════════════════════════════════════");
        Print("📈 三线合一线策略已启动");
        Print("═══════════════════════════════════════");
        Print("均线参数:" + Text(MA_Short_Period) + "/" + Text(MA_Middle_Period) + "/" + Text(MA_Long_Period));
        Print("粘合阈值:" + Text(Coincide_Threshold * 100, 1) + "%");
        Print("粘合最少 K 线:" + Text(Coincide_Bars));
        Print("止损:" + IIFString(UseStopLoss==1, Text(StopLoss_Tick) + "跳", "关闭"));
        Print("止盈:" + IIFString(UseTakeProfit==1, Text(TakeProfit_Tick) + "跳", "关闭"));
        Print("═══════════════════════════════════════");
    }

    OnBar(ArrayRef<Integer> indexs)
    {
        Range[0:DataCount-1]
        {
            // ========== 1. 计算三条均线 ==========
            MA_Short = Average(Close, MA_Short_Period);
            MA_Middle = Average(Close, MA_Middle_Period);
            MA_Long = Average(Close, MA_Long_Period);

            // ========== 2. 计算粘合度 ==========
            // 找出三线中的最大值和最小值
            MA_Max = Max(MA_Short, Max(MA_Middle, MA_Long));
            MA_Min = Min(MA_Short, Min(MA_Middle, MA_Long));
            MA_Avg = (MA_Short + MA_Middle + MA_Long) / 3;

            // 粘合度 = (最大值 - 最小值) / 平均值
            If(MA_Avg > 0)
            {
                Coincide_Rate = (MA_Max - MA_Min) / MA_Avg;
            }
            Else
            {
                Coincide_Rate = 0;
            }

            // 判断是否粘合
            IsCoinciding = Coincide_Rate <= Coincide_Threshold;

            // 统计粘合持续 K 线数
            If(IsCoinciding)
            {
                Coincide_Count = Coincide_Count + 1;
                HasCoincided = True;
            }
            Else
            {
                Coincide_Count = 0;
            }

            // ========== 3. 判断发散状态 ==========
            // 多头排列:短>中>长
            Bull_Diverge = MA_Short > MA_Middle And MA_Middle > MA_Long;
            // 空头排列:短<中<长
            Bear_Diverge = MA_Short < MA_Middle And MA_Middle < MA_Long;

            // ========== 4. 生成交易信号 ==========
            // 核心逻辑:必须经历过粘合 + 当前形成有序排列 + 粘合持续时间达标
            Long_Signal = Bull_Diverge And HasCoincided And Coincide_Count >= Coincide_Bars;
            Short_Signal = Bear_Diverge And HasCoincided And Coincide_Count >= Coincide_Bars;

            // ========== 5. 初始化变量 ==========
            Signal_Buy = InvalidNumeric();
            Signal_Sell = InvalidNumeric();
            Signal_SellShort = InvalidNumeric();
            Signal_BuyCover = InvalidNumeric();

            // ========== 6. 更新持仓极值 (用于移动止盈) ==========
            If(MarketPosition != 0)
            {
                If(High > Highest_Price) Highest_Price = High;
                If(Low < Lowest_Price) Lowest_Price = Low;
            }
            Else
            {
                // 无持仓时重置极值
                Highest_Price = 0;
                Lowest_Price = 999999;
            }

            // ========== 7. 防重复下单 ==========
            If(CurrentBar - LastTradeBar < 1)
            {
                // 间隔太短,跳过
            }
            Else
            {
                // ========== 计算委托价格 ==========
                BuyPrice = High + PriceOffset * PriceTick;
                SellPrice = Low - PriceOffset * PriceTick;

                // ========== 资金管理 ==========
                Lots = Max(1, IntPart(Fund * RiskPercent / (Close * ContractUnit * BigPointValue)));

                // ========== 交易逻辑 ==========

                // --- 开多条件 ---
                If(Long_Signal And MarketPosition <= 0)
                {
                    Buy(Lots, BuyPrice);
                    EntryBar = CurrentBar;
                    EntryPrice = BuyPrice;
                    LastTradeBar = CurrentBar;
                    Signal_Buy = Low;
                    Highest_Price = High;
                    Lowest_Price = Low;

                    strLog = "🟢 三线合一线开多 | 粘合:" + Text(Coincide_Count) + "K 线 | 粘合度:" + Text(Coincide_Rate * 100, 2) + "%";
                    Print(strLog);
                }

                // --- 开空条件 ---
                If(Short_Signal And MarketPosition >= 0)
                {
                    SellShort(Lots, SellPrice);
                    EntryBar = CurrentBar;
                    EntryPrice = SellPrice;
                    LastTradeBar = CurrentBar;
                    Signal_SellShort = High;
                    Highest_Price = High;
                    Lowest_Price = Low;

                    strLog = "🔴 三线合一线开空 | 粘合:" + Text(Coincide_Count) + "K 线 | 粘合度:" + Text(Coincide_Rate * 100, 2) + "%";
                    Print(strLog);
                }

                // --- 平多条件 ---
                If(MarketPosition > 0)
                {
                    Bool Close_Long = False;
                    String Close_Reason = "";

                    // 条件 1: 均线死叉 (短期下穿中期) - 趋势反转
                    If(CrossUnder(MA_Short, MA_Middle))
                    {
                        Close_Long = True;
                        Close_Reason = "均线死叉";
                    }

                    // 条件 2: 固定止损
                    If(UseStopLoss == 1 And Close - EntryPrice < -StopLoss_Tick * PriceTick)
                    {
                        Close_Long = True;
                        Close_Reason = "止损";
                    }

                    // 条件 3: 固定止盈
                    If(UseTakeProfit == 1 And Close - EntryPrice > TakeProfit_Tick * PriceTick)
                    {
                        Close_Long = True;
                        Close_Reason = "止盈";
                    }

                    // 条件 4: 回撤止盈 (从最高点回撤一定幅度)
                    If(UseTakeProfit == 1 And Highest_Price - Close > TakeProfit_Tick * PriceTick * 0.5)
                    {
                        Close_Long = True;
                        Close_Reason = "回撤止盈";
                    }

                    If(Close_Long)
                    {
                        Sell(0, SellPrice);
                        LastTradeBar = CurrentBar;
                        Signal_Sell = High;
                        Print("🔴 平多 | 原因:" + Close_Reason);
                    }
                }

                // --- 平空条件 ---
                If(MarketPosition < 0)
                {
                    Bool Close_Short = False;
                    String Close_Reason = "";

                    // 条件 1: 均线金叉 (短期上穿中期) - 趋势反转
                    If(CrossOver(MA_Short, MA_Middle))
                    {
                        Close_Short = True;
                        Close_Reason = "均线金叉";
                    }

                    // 条件 2: 固定止损
                    If(UseStopLoss == 1 And EntryPrice - Close < -StopLoss_Tick * PriceTick)
                    {
                        Close_Short = True;
                        Close_Reason = "止损";
                    }

                    // 条件 3: 固定止盈
                    If(UseTakeProfit == 1 And EntryPrice - Close > TakeProfit_Tick * PriceTick)
                    {
                        Close_Short = True;
                        Close_Reason = "止盈";
                    }

                    // 条件 4: 回撤止盈
                    If(UseTakeProfit == 1 And Close - Lowest_Price > TakeProfit_Tick * PriceTick * 0.5)
                    {
                        Close_Short = True;
                        Close_Reason = "回撤止盈";
                    }

                    If(Close_Short)
                    {
                        BuyToCover(0, BuyPrice);
                        LastTradeBar = CurrentBar;
                        Signal_BuyCover = Low;
                        Print("🟢 平空 | 原因:" + Close_Reason);
                    }
                }
            }

            // ========== 8. 绘图 ==========

            // 主图:三条均线
            PlotNumeric("MA_Short", MA_Short);
            PlotNumeric("MA_Middle", MA_Middle);
            PlotNumeric("MA_Long", MA_Long);

            // 信号标记
            If(Signal_Buy != InvalidNumeric())
            {
                PlotNumeric("Signal_Buy", Signal_Buy * 0.995);
            }
            If(Signal_Sell != InvalidNumeric())
            {
                PlotNumeric("Signal_Sell", Signal_Sell * 1.005);
            }
            If(Signal_SellShort != InvalidNumeric())
            {
                PlotNumeric("Signal_SellShort", Signal_SellShort * 1.005);
            }
            If(Signal_BuyCover != InvalidNumeric())
            {
                PlotNumeric("Signal_BuyCover", Signal_BuyCover * 0.995);
            }

            // 副图 1: 粘合度曲线
            PlotNumeric("Coincide_Rate", Coincide_Rate * 100);
            PlotNumeric("Coincide_Threshold", Coincide_Threshold * 100);

            // 状态显示
            Commentary("📈 三线合一 | 粘合度:" + Text(Coincide_Rate * 100, 2) + "% | 粘合 K 线:" + Text(Coincide_Count) +
                       " | 排列:" + IIFString(Bull_Diverge, "多头", IIFString(Bear_Diverge, "空头", "混乱")) +
                       " | 持仓:" + Text(MarketPosition) +
                       " | 信号:" + IIFString(Long_Signal, "🟢多", IIFString(Short_Signal, "🔴空", "⏸️")));
        }
    }