【交易策略】低通滤波器策略:在小时图上捕捉中期动量

本文介绍了一套针对加密货币的中期动量交易策略,核心思想是运用低通滤波器(Low Pass Filter)平滑价格序列,并借助模糊逻辑识别趋势状态。策略历经七轮迭代优化:从参数优化到风险控制,最终实现了夏普比率 1.26、盈利因子 1.81的稳健表现。本文将完整呈现从假设提出、参数扫描到样本外验证的全流程,为读者提供一套可复用的策略开发方法论。

1. 核心逻辑

1.1 为什么选择低通滤波器?

在量化交易中,趋势跟随策略的核心难题在于如何在噪声中提取有效信号。传统移动平均线(MA)存在滞后性,而低通滤波器通过频域设计,能够在平滑价格的同时保留关键的转折点信息。

策略核心假设:当价格围绕趋势线窄幅震荡时,市场处于无序状态,策略应避免交易;当价格沿趋势线方向运动时,市场处于有序状态,策略应顺势交易。

1.2 模糊逻辑

仅凭单一滤波器难以应对市场的非线性特征。我们引入模糊逻辑(Fuzzy Logic),通过概率化的方式判断趋势方向:

  • 上涨概率(RisingProb):衡量趋势向上的置信度
  • 下跌概率(FallingProb):衡量趋势向下的置信度

当置信度超过阈值(EntryProbThreshold = 0.6)时,触发相应方向的交易信号。

2. 回溯检验设置

我们将使用 Zorro 进行策略开发。

Asset BTCUSDT, ETHUSDT
BarPeriod 60
StartDate 20180101
EndDate 20251230
Lookback 5000
Leverage 5
Commission -0.1
Slippage 5
NumWFOCycles 10
DataSplit 85
FixedCapital 10000

测试时间约 8 年,涵盖 2018 年熊市、2021 年牛市及 2022 年震荡市,具备较强的样本代表性。Walk-Forward Optimization(WFO)采用 10 个周期、85% 数据分割比例,以验证参数的稳定性和泛化能力。

3. 迭代优化

3.1 基础策略

初始参数设定

  • 趋势线回溯期 TrendPeriod = 800
  • 模糊因子 FuzzyFactor = 0.1
  • 进场概率阈值 EntryProbThreshold = 0.6

回测表现分析

基础策略展现出长期正向收益 ,净值曲线整体向上。然而,在窄幅震荡行情 中,价格围绕趋势线小幅波动,策略频繁触发假信号,导致持续亏损,这是后续优化需要解决的核心问题。

3.2 优化趋势线回溯期

优化假设:低通滤波器的回溯期直接决定了趋势识别的灵敏度。过短的回溯期会引入噪声,过长则导致滞后。通过参数扫描寻找稳健区间。

参数扫描设置

  • 区间:500-1200
  • 步长:50

测试结果

  • BTC 的平稳参数区间:900-1000
  • ETH 的平稳参数区间:700-1000

样本外表现

  • 盈利因子从 1.57 微升至 1.60
  • PRR 从 1.35 提升至 1.37
  • 交易次数减少约 10%

结论:虽然策略表现提升有限,但优化回溯期能够更好地适应市场变异。建议采用优化参数,以增强策略对市场结构变化的适应能力。

3.3 优化模糊因子

优化假设:模糊因子是模糊逻辑的核心参数,它决定了识别趋势和震荡行情的准确度。优化该参数或许能够减少震荡行情中的亏损。

参数扫描设置

  • 区间:0-0.3
  • 步长:0.02

测试结果

  • BTC 的局部高点区间:0.2-0.26
  • ETH 的局部高点区间:0.12-0.20

样本外表现

  • 盈利因子和 PRR 几乎无变化
  • 夏普比率从 0.89 下降至 0.83

结论 :优化模糊因子可能导致过拟合 。局部高点在样本内表现优异,但在样本外无法保持优势。因此,不优化模糊因子,继续使用固定参数 0.1。这一决策体现了量化开发中"稳健优先于最优"的原则。

3.4 距离滤波器

优化假设 :当价格偏离趋势线过远时,市场存在强烈的均值回归需求 。此时进场往往面临回调风险,导致亏损。通过引入波动性滤波器(距离滤波器),仅在价格偏离度低于阈值时允许进场,目标是降低宽幅震荡行情的亏损。

参数扫描设置

  • 区间:1-6(百分比距离)
  • 步长:0.5

测试结果

  • BTC 的平稳参数区间:4-6
  • ETH 的平稳参数区间:4-5

样本外表现(显著提升):

指标 优化前 优化后 提升幅度
盈利因子 1.60 1.75 +9.4%
PRR 1.37 1.47 +7.3%
夏普比率 0.89 1.02 +14.6%

关键洞察

⚠️ 距离阈值是一把双刃剑:它既能过滤宽幅震荡的亏损,也可能导致错过历史级别的趋势行情。

然而,从风险调整后收益的角度,降低宽幅震荡的亏损比贪婪地捕捉每一轮趋势更为重要。因此,保留距离滤波器机制。

3.5 固定止损

优化假设 :趋势策略面临的最大风险是逆趋势大幅回撤。通过基于 ATR(Average True Range)的动态止损,可以在趋势反转时及时退出。

参数扫描设置

  • 止损距离 = k * ATR(100)
  • 区间:3-8
  • 步长:0.5

测试结果

  • 两个交易对的平稳参数区间均集中在 5-8

样本外表现

  • 总收益率大幅下降
  • 连续亏损次数大幅增加
  • 风险调整收益率仅小幅下降
  • 最长回撤周数显著减少(从 34 周降至 24 周)

结论 :固定止损的核心价值在于控制回撤风险,尽管它以牺牲部分收益为代价。保留该机制。

3.6 盈亏平衡(Breakeven)

优化假设:当交易产生一定浮盈后,将止损价调整至进场价,确保该笔交易至少不亏损。这有助于改善交易心理,并降低连续亏损对资金曲线的冲击。

参数扫描设置

  • 浮盈阈值 = k * ATR(100)
  • 区间:3-8
  • 步长:0.5

样本外表现

  • 风险调整收益率进一步下降
  • 胜率提升至 45%
  • 最长连续亏损次数从 27 笔锐减至 9 笔

结论:盈亏平衡机制带来了显著改善,胜率的提升和连续亏损的锐减显著改善了资金曲线的平滑度。保留该机制。

3.7 空头部分止盈

优化假设:空头交易往往面临不对称风险(价格上涨无上限)。当浮盈达到阈值后,先平仓 50% 以锁定利润,然后对剩余头寸启用动态跟踪止损。

机制设计

  1. 设定盈利阈值,当浮盈超过阈值后平仓 50%
  2. 对剩余 50% 头寸启动跟踪止损,锁定已获利润
  3. 进入"观望模式":不再新开空头,直到价格出现强劲反弹才允许再进场

测试结果

  • 盈利因子从 1.61 提升至 1.69
  • PRR 从 1.41 提升至 1.52
  • 夏普比率从 0.91 提升至 1.19
  • 两个交易对的空头盈利因子均有提升

3.8 资金管理

优化假设:固定资金头寸法难以控制下行风险。采用固定风险头寸法(Fixed Risk),每笔交易使用账户净值的固定比例(2%)进行冒险,可以实现收益的复利增长,且有效控制回撤风险。

样本外表现

  • 净值曲线更加平滑
  • 夏普比率提升至 1.26

4. 总结

迭代优化记录总表。

核心指标 基础策略 优化趋势线 距离滤波器 固定止损 盈亏平衡 优化空头平仓 资金管理
最大回撤 12% 12.5% 11% 15% 14% 12% 10.7%
MAE 18% 18.7% 20% 25% 24% 16% 14%
最长回撤周数 34 34 34 24 34 24 24
交易次数 440 403 332 346 467 748 748
每周交易 2 2 1 1 2 3 3
胜率 28% 27% 28% 26% 45% 45% 45%
最长连续亏损 18 14 13 27 9 18 18
年收益率 119% 116% 121% 99% 100% 117% 45.8%
盈利因子 1.57 1.60 1.75 1.70 1.61 1.69 1.81
PRR 1.35 1.37 1.47 1.43 1.41 1.52 1.63
夏普比率 0.91 0.89 1.02 0.98 0.91 1.19 1.26
R2 77% 75% 83% 77% 80% 89% 83%
平均回撤 7.2% 7.3% 8.1% 9.4% 9.5% 5.8% 5.2%
BTC PF 1.43 1.57 1.84 1.80 1.74 1.83 1.86
ETH PF 1.80 1.62 1.68 1.62 1.51 1.58 1.76

关键发现:

  1. 距离滤波器是风险调整后收益提升的核心驱动力,夏普比率首次突破 1.0
  2. 盈亏平衡机制大幅改善了胜率(从 28% 跃升至 45%)和降低连续亏损次数
  3. 空头优化显著提升了策略的夏普比率,证明了单独优化空头平仓的价值
  4. 固定风险资金管理虽然降低了名义收益率(45.8% vs 117%),但实现了更平滑的资金曲线和更高的夏普比率(1.26)

长期表现特征:

  • 表现最糟糕的时期:2022 年下半年,连续四个月亏损
  • 整体表现:其余年份均能稳定盈利,平均每年约四个月亏损,三分之二时间盈利
  • 震荡市应对 :当市场陷入窄幅震荡时,策略会持续亏损。未来可考虑加入波动性滤波器(当波动性过低时暂停交易)作为进一步优化方向

5. 稳健性检验

为验证策略的稳健性,我们对 Walk-Forward Optimization(WFO)的周期数进行敏感性分析。

5.1 测试设置

Asset BTCUSDT, ETHUSDT
BarPeriod 60
StartDate 20180101
EndDate 20251230
Lookback 5000
Leverage 5
Commission -0.1
Slippage 5
NumWFOCycles 2-30
DataSplit 85

5.2 固定资金模式(每交易对 10000 美元)

当周期数处于 10-16 时,PRR 创局部高点并保持稳定。

5.3 固定风险模式(初始资金 10000,风险率 2%)

当周期数处于 10-20 时,PRR 创局部高点并保持稳定,局部高点区间为 1.6-1.7

5.4 稳健性结论

策略通过稳健性检验。

推荐的 WFO 参数设置:

  • StartDate = 20180101
  • EndDate = 20251230
  • NumWFOCycles = 15
  • DataSplit = 85

附录:策略源码

以下代码完整呈现了策略的实现逻辑,包含指标计算、信号生成、状态管理、风险控制、资金管理和订单执行等模块。

c 复制代码
/*
基于低通滤波器识别中期趋势反转
*/

#include <profile.c>
#include <utils.c>
#include <myindicators.c>

function tradeStrategy() {
    // ---------------------------------------------------------
    // 参数设置
    // ---------------------------------------------------------
    int TrendPeriod = 800;
    var FuzzyFactor = 0.1;
    var EntryProbThreshold = 0.6;
    var DeviationThreshold = 0;
    var AtrStopFactor = 0;
    var AtrTrailFactor = 0;
    var ShortProfitThreshold = 0;
    var FixedCapital = 10000;
    var FixedRisk = 0;

    // ---------------------------------------------------------
    // 指标计算
    // ---------------------------------------------------------
    vars Prices = series(price());
    vars Trends = series(LowPass(Prices, TrendPeriod));
    var ATR100 = ATR(100);
    var PercentDeviation = abs(Prices[0]-Trends[0])/Trends[0]*100;

    var LongNormalizedProfit = getLongNormalizedProfit(ATR100);
    var ShortNormalizedProfit = getShortNormalizedProfit(ATR100);

    // ---------------------------------------------------------
    // 交易信号
    // ---------------------------------------------------------
    FuzzyRange = FuzzyFactor*ATR100;
    var RisingProb = risingF(Trends);
    var FallingProb = fallingF(Trends);

    bool LongEntry = RisingProb >= EntryProbThreshold;
    bool LongExit = peak(Trends);
    bool ShortEntry = FallingProb >= EntryProbThreshold;
    bool ShortExit = valley(Trends);

    if(DeviationThreshold > 0) {
        LongEntry = LongEntry && PercentDeviation <= DeviationThreshold;
        ShortEntry = ShortEntry && PercentDeviation <= DeviationThreshold;
    }

    // ---------------------------------------------------------
    // 状态管理:再进场限制 (AlgoVar[0])
    // ---------------------------------------------------------

    // 触发部分止盈后,开始跟踪跟踪剩余头寸,并进入观望期
    if(AlgoVar[0] == 1) {
        // 限制进场
        ShortEntry = false;

        // 管理剩余持仓:锁定 50% 利润
        for(current_trades) {
            if(TradeIsOpen && TradeIsShort) {
                TradeTrailLock = 0.5;
            }
        }

        // 解锁条件:空仓且趋势反转
        if(NumOpenShort == 0) {
            if(RisingProb > 0.4 || valley(Trends) || peak(Trends)) {
                AlgoVar[0] = 0;
            }
        }
    }

    // ---------------------------------------------------------
    // 风控
    // ---------------------------------------------------------
    Stop = AtrStopFactor*ATR100;
    Trail = AtrTrailFactor*ATR100;
    TrailLock = 10;
    TrailSlope = 0;

    // ---------------------------------------------------------
    // 资金管理
    // ---------------------------------------------------------
    Lots = 100;
    var MinLots = getMinLots();
    if(!Train && FixedCapital > 0)
        Lots = floor(FixedCapital/priceC()/LotAmount);
    if(!Train && Capital > 0 && FixedRisk > 0 && AtrStopFactor > 0)
        Lots = fixedRiskLots(FixedRisk);
    if(Lots < MinLots) Lots = MinLots;

    // ---------------------------------------------------------
    // 订单管理
    // ---------------------------------------------------------
    if(NumOpenLong > 0 && LongExit)
        exitLong();
    if(NumOpenShort > 0 && ShortExit)
        exitShort();
    if(NumOpenLong == 0 && LongEntry)
        enterLong();
    if(NumOpenShort == 0 && ShortEntry) {
        if(ShortProfitThreshold > 0)
            enterShortMultipleOrders(2, MinLots);
        else
            enterShort();
    }

    // 空头部分止盈逻辑
    if(ShortProfitThreshold > 0 && NumOpenShort > 0 && AlgoVar[0] == 0) {
        if(ShortNormalizedProfit >= ShortProfitThreshold) {
            // 平仓50%
            exitProfitShortOrders(1);
            // 标记进入剩余头寸管理模式
            AlgoVar[0] = 1;
        }
    }

    // ---------------------------------------------------------
    // 绘图
    // ---------------------------------------------------------
    if((Test && !is(LOOKBACK)) || Live) {
        plot2("Trend", Trends[0], MAIN, rising(Trends), GREEN, RED);

        var BullishState = ifelse(RisingProb >= EntryProbThreshold, 1, 0);
        var BearishState = ifelse(FallingProb >= EntryProbThreshold, 1, 0);
        plot("BullishState", BullishState, NEW|BARS, GREEN+TRANSP);
        plot("BearishState", BearishState, 0|BARS, RED+TRANSP);
        plot("RisingProb", RisingProb, 0|LINE, BLUE);
        plot("BullT", EntryProbThreshold, 0, GREY);
        plot("BearT", 1-EntryProbThreshold, 0, GREY);

        if(DeviationThreshold > 0) {
            plot("Deviation", PercentDeviation, NEW, RED);
            plot("Deviation+", DeviationThreshold, 0, GREY);
        }

        if(ShortProfitThreshold > 0) {
            plot("LongProfit", LongNormalizedProfit, NEW|BARS, GREEN+TRANSP);
            plot("ShortProfit", ShortNormalizedProfit, 0|BARS, RED+TRANSP);
            plot("ShortProfitT", ShortProfitThreshold, 0, RED);
        }

        if(AtrStopFactor > 0 && NumOpenTotal > 0) {
            var CurrentStop = 0;
            for(current_trades) {
                CurrentStop = (var)TradeStopLimit;
                break_trades;
            }
            if(CurrentStop > 0) plot("Stop", CurrentStop, MAIN|DOT, LIGHTBLUE);
        }

        // if(AlgoVar[0] > 0) plot("LockMode", 10, NEW|BARS, BLUE);
    }
}

function run() {
    // --------------------------------------------------------- //
    // Zorro 设置
    // --------------------------------------------------------- //

    // 日志
    set(LOGFILE);
    Verbose = 3;

    // 图表
    set(PLOTNOW);
    setf(PlotMode,PL_DIFF);
    PlotScale = 8;
    PlotHeight2 = 320;
    if(Live) PlotBars = -250;

    // 训练
    set(PARAMETERS);
    setf(TrainMode,TRADES);
    DataSplit = 85;
    NumWFOCycles = 10;
    NumCores = 4;

    // 实盘
    if(Live) {
        set(NOLOCK);  // 禁止同步 zorro 实例
        setf(SaveMode,SV_STATS|SV_TRADES|SV_ALGOVARS|SV_SLIDERS);
        TickTime = 1000;
        TockTime = 60000;
        slider(1,2000,0,3000,".Risk(%)",0); // 通过滑块设置风险率
    }

    // k线生成规则,7*24交易
    resf(BarMode,BR_WEEKEND);
    StartWeek = 0;
    EndWeek = 62359;
    StartMarket = 0;
    EndMarket = 2359;
    BarPeriod = 60;
    BarZone = UTC;
    BarOffset = 0;
    TickFix = 60000;
  	  if(Live) TickFix = 0;

    // 测试样本
    StartDate = 20180101;
    EndDate = 20251230;
    LookBack = 5000;

    // 初始资本
    if(Train) Capital = 0;
    if(Test) Capital = 0;
    if(Live) Capital = 0;

    // 下一根k线开盘时进场/平仓
    Fill = 3;

    // --------------------------------------------------------- //
    // 交易策略
    // --------------------------------------------------------- //

    while(asset(loop("BTCUSDT","ETHUSDT"))) {
        Leverage = 5;
        MarginCost = priceClose()*LotAmount/Leverage;
        tradeStrategy();
    }
}
相关推荐
培培说证1 小时前
2026 大专大数据与会计专业考证书门槛低的有哪些?
大数据
智算菩萨1 小时前
上下文学习的贝叶斯推断视角:隐式梯度下降还是隐式贝叶斯?
人工智能·算法
看-是灰机1 小时前
openclaw
人工智能
骇城迷影2 小时前
从零复现GPT-2 124M
人工智能·pytorch·python·gpt·深度学习
黑巧克力可减脂2 小时前
商鞅变法与代码重构:AI正在如何重写软件工程的“耕战律令”
人工智能·重构·软件工程
大傻^2 小时前
【AI安全攻防战】提示词攻击与防护:从“奶奶漏洞“到企业级防御体系
人工智能·安全·提示词安全
大学在校生,求offer联系2 小时前
YuFeng-XGuard-Reason安全护栏模型实测评价
人工智能·安全
Hcoco_me2 小时前
深挖 TBD 核心进阶点:深度学习匹配(目标关联的“智能指纹”)
人工智能·深度学习·目标检测·计算机视觉·目标跟踪
Σίσυφος19002 小时前
四元数 欧拉角 旋转矩阵
人工智能·算法·矩阵