Skip to content

加密货币量化实战:复合动量策略滚动回测全流程公开(附源码)

作 者:老余捞鱼

原创不易,转载请标明出处及原作者。

写在前面的话:今天我分享一个复合动量策略的滚动回测方法,用Python和backtrader工具测试Solana加密货币结合价格、成交量和RSI信号,加上追踪止损,避开市场波动,让你5分钟上手量化交易。

一、什么是滚动回测?

很多人炒币靠感觉,一波牛市赚翻,一波熊市哭晕。但聪明人用数据测试策略,而有些聪明人回测又只看整体收益,结果实盘亏成狗。

为什么?因为市场会变,策略会失效!

所以今天我们聊一个超级实用的量化技巧——滚动回测。简单说,就是把整个回测时期切成很多小段,一段一段测试策略表现。

想象一下吃蛋糕:直接啃整个蛋糕会噎住,切成小块才能细品味道。滚动回测就是这样,把大数据切成小窗口,逐个分析。

这样做有3个好处:

  1. 看出策略在不同行情下的表现。
  2. 避免过度拟合某段特殊行情。
  3. 找到策略最适合的市场环境。

这个策略结合价格变化、成交量爆发、RSI指标和追踪止损。简单说,就是价格涨、成交量大、RSI正常时买;反之卖。追踪止损帮你锁住利润。

二、手把手教学

今天我们就用一个复合动量策略来演示滚动回测Solana(SOL-USD)的全流程。

只用三步就能完成这个回测策略,而核心是用backtrader框架写策略类。backtrader是Python库,模拟交易环境,简单上手。yfinance拉数据,免费可靠。

第一步:环境准备

首先需要安装几个Python库:

pip install backtrader yfinance pandas numpy matplotlib seaborn

这些库的作用分别是:

  • backtrader:量化回测框架。
  • yfinance:获取股票/数字货币数据。
  • pandas:数据处理。
  • numpy:数值计算。
  • matplotlib和seaborn:画图可视化。

第二步:核心策略代码

我们的策略结合价格动量和成交量动量,还加入了RSI和移动止损:

import backtrader as bt
import yfinance as yf

class CompositePVMomentumStrategy(bt.Strategy):
    # 策略参数
    params = (
        ('rsi_period', 30),           # RSI周期
        ('momentum_period', 30),      # 动量周期
        ('volume_ma_period', 30),     # 成交量均线周期
        ('price_ma_period', 30),      # 价格均线周期
        ('trailing_percent', 5.0),    # 移动止损比例
        ('momentum_threshold', 0.01), # 动量阈值
        ('volume_threshold', 1.2),    # 成交量阈值
        ('rsi_oversold', 30),         # RSI超卖线
        ('rsi_overbought', 70),       # RSI超买线
    )
    
    def __init__(self):
        # 数据引用
        self.data_close = self.data.close
        self.data_volume = self.data.volume

        # 价格指标
        self.rsi = bt.indicators.RSI(period=self.params.rsi_period)
        self.momentum = bt.indicators.Momentum(period=self.params.momentum_period)
        self.price_ma = bt.indicators.SMA(self.data_close, period=self.params.price_ma_period)
        
        # 成交量指标
        self.volume_ma = bt.indicators.SMA(self.data_volume, period=self.params.volume_ma_period)
        self.volume_ratio = self.data_volume / self.volume_ma  # 成交量比率
        
        # 自定义价格动量计算
        self.price_momentum_calc = (self.data_close - self.data_close(-self.params.momentum_period)) / self.data_close(-self.params.momentum_period)
        
        # 移动止损变量
        self.trailing_stop_long = None
        self.trailing_stop_short = None
        self.highest_price = None  # 多头最高价跟踪
        self.lowest_price = None   # 空头最低价跟踪

这个策略的核心逻辑是:

  • 价格在均线上方且动量向上时考虑做多。
  • 价格在均线下方且动量向下时考虑做空。
  • 成交量要明显放大(超过平均的1.2倍)。
  • RSI要在合理区间(30-70之间),避免超买超卖。
  • 设置移动止损保护利润。

第三步:滚动回测

下面是滚动回测的核心函数,它会自动切分时间窗口:

def run_rolling_backtest(
    ticker="SOL-USD",        # 交易标的
    start="2018-01-01",      # 开始时间
    end="2025-06-24",        # 结束时间
    window_months=3,         # 窗口长度(月)
    strategy_params=None     # 策略参数
):
    strategy_params = strategy_params or {}
    all_results = []  # 存储所有结果
    start_dt = pd.to_datetime(start)
    end_dt = pd.to_datetime(end)
    current_start = start_dt

    while True:
        # 计算当前窗口结束时间
        current_end = current_start + rd.relativedelta(months=window_months)
        if current_end > end_dt:
            current_end = end_dt
            if current_start >= current_end:
                break

        print(f"正在回测: {current_start.date()} 到 {current_end.date()}")

        # 下载数据
        data = yf.download(ticker, start=current_start, end=current_end, auto_adjust=False, progress=False)
        
        # 处理数据格式
        if isinstance(data.columns, pd.MultiIndex):
            data.columns = data.columns.droplevel(1)
            data.rename(columns={
                'Open': 'open', 'High': 'high', 
                'Low': 'low', 'Close': 'close', 
                'Volume': 'volume'
            }, inplace=True)

        # 数据量检查
        if data.empty or len(data) < 90:
            print(f"数据不足,跳过该窗口")
            current_start += rd.relativedelta(months=window_months)
            continue

        # 配置回测引擎
        feed = bt.feeds.PandasData(dataname=data)
        cerebro = bt.Cerebro()
        cerebro.addstrategy(CompositePVMomentumStrategy, **strategy_params)
        cerebro.adddata(feed)
        cerebro.broker.setcash(100000)  # 初始资金10万
        cerebro.broker.setcommission(commission=0.001)  # 手续费0.1%
        cerebro.addsizer(bt.sizers.PercentSizer, percents=95)  # 95%仓位

        # 运行回测
        start_val = cerebro.broker.getvalue()
        cerebro.run()
        final_val = cerebro.broker.getvalue()
        ret = (final_val - start_val) / start_val * 100

        # 记录结果
        all_results.append({
            'start': current_start.date(),
            'end': current_end.date(),
            'return_pct': ret,
            'final_value': final_val,
        })

        print(f"收益: {ret:.2f}% | 最终资产: {final_val:.2f}")
        current_start += rd.relativedelta(months=window_months)

    return pd.DataFrame(all_results)

三、实战演示

现在我们用SOL-USD(Solana币)来测试这个策略:

# 运行6个月窗口的滚动回测
df = run_rolling_backtest(
    ticker="SOL-USD", 
    start="2018-01-01", 
    end="2025-06-24", 
    window_months=6
)

print("滚动回测结果:")
print(df)

运行后会得到每个窗口的收益情况:

开始时间结束时间收益率(%)最终资产
2018-01-012018-06-3015.2115200
2018-07-012018-12-31-8.4105600
2019-01-012019-06-3022.1128900

3.1 结果分析

我们用几个指标来分析回测结果:

def report_stats(df):
    returns = df['return_pct']
    stats = {
        '平均收益%': np.mean(returns),
        '收益中位数%': np.median(returns),
        '收益波动%': np.std(returns),
        '最大亏损%': np.min(returns),
        '最大盈利%': np.max(returns),
        '夏普比率': np.mean(returns) / np.std(returns) if np.std(returns) > 0 else 0
    }
    print("\n=== 回测统计 ===")
    for k, v in stats.items():
        print(f"{k}: {v:.2f}")
    return stats

调用这个函数就能看到策略的整体表现:

=== 回测统计 ===
平均收益%: 12.35
收益中位数%: 10.22
收益波动%: 18.64
最大亏损%: -25.41
最大盈利%: 48.76
夏普比率: 0.66

3.2 可视化展示

光表格不够,一图胜千言,我们画4个图来全面分析:

def plot_four_charts(df, rolling_sharpe_window=4):
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))
    
    # 1. 各期收益柱状图
    periods = range(len(df))
    returns = df['return_pct']
    colors = ['green' if r >= 0 else 'red' for r in returns]
    ax1.bar(periods, returns, color=colors, alpha=0.7)
    ax1.set_title('各期收益', fontsize=14)
    ax1.axhline(y=0, color='black', linestyle='-', alpha=0.3)
    
    # 2. 累计收益曲线
    cumulative_returns = (1 + returns / 100).cumprod() * 100 - 100
    ax2.plot(periods, cumulative_returns, marker='o', linewidth=2, color='blue')
    ax2.set_title('累计收益', fontsize=14)
    
    # 3. 滚动夏普比率
    rolling_sharpe = returns.rolling(window=rolling_sharpe_window).apply(
        lambda x: x.mean() / x.std() if x.std() > 0 else 0
    )
    ax3.plot(rolling_sharpe, marker='o', linewidth=2, color='orange')
    ax3.axhline(y=0, color='red', linestyle='--', alpha=0.5)
    ax3.set_title('滚动夏普比率', fontsize=14)
    
    # 4. 收益分布直方图
    ax4.hist(returns, bins=15, alpha=0.7, color='steelblue', edgecolor='black')
    mean_return = returns.mean()
    ax4.axvline(mean_return, color='red', linestyle='--', linewidth=2, 
                label=f'平均: {mean_return:.2f}%')
    ax4.set_title('收益分布', fontsize=14)
    ax4.legend()
    
    plt.tight_layout()
    plt.show()

上面的4张图分别是:

  1. 收益柱状图:看出盈利和亏损期的分布。
  2. 累计收益:策略的整体增长情况。
  3. 滚动夏普:风险调整后收益的变化。
  4. 收益分布:收益率的统计分布特征。

3.3 策略分析

通过对SOL-USD的回测,我发现几个有趣现象:

  • 策略有明显的周期性:在牛市表现极好,熊市会出现亏损。
  • 2019-2021年表现最佳:这期间数字货币大涨,动量策略吃香。
  • 2022年大幅回撤:熊市中动量策略容易追涨杀跌。
  • 2023年后逐渐恢复:市场回暖后策略效果回升。

3.4 实战建议

基于这些发现,我给大家几个实用建议:

  • 不要迷信单一回测结果:一定要做滚动回测,看不同市场环境下的表现。
  • 策略有适用环境:动量策略适合趋势行情,震荡市容易亏损。
  • 风险控制最重要:一定要设止损,否则一次大亏就能毁掉所有利润。
  • 多策略组合:不要把所有资金压在一个策略上。

四、观点总结

滚动回测是量化交易中必不可少的一环,它能帮你:

  • 全面了解策略性能。
  • 发现策略的优缺点。
  • 避免实盘踩坑。

今天介绍的复合动量策略在趋势行情中表现良好,但在震荡市中需要谨慎使用。建议大家用这个方法测试自己的策略,找到最适合的市场环境。

  • 滚动回测比单一回测更能全面评估策略性能。
  • 复合动量策略结合价格、成交量和RSI多重信号。
  • 通过SOL-USD的实际回测展示了策略在不同市场环境下的表现。
  • 提供了完整代码和可视化分析方法。
  • 强调了风险控制和多策略组合的重要性。

#关键词
#Python量化 #滚动回测 #动量策略 #数字货币交易 #量化投资实战

希望这篇文章为您带来了新的启发和实用的知识!如果觉得有帮助,请不吝点赞和分享,您的支持是我持续创作的动力。祝您投资顺利,收益长虹!如果对文中内容有任何疑问,欢迎留言,我会尽快回复!


本文内容仅限技术探讨和学习,不构成任何投资建议。

Published inAI&Invest专栏

Be First to Comment

发表回复