企业微信

双均线策略的核心逻辑

双均线策略基于两条不同周期的移动平均线。短期均线上穿长期均线形成金叉,视为买入信号;短期均线下穿长期均线形成死叉,视为卖出信号。该策略捕捉趋势行情,在单边上涨或下跌中获利,但在震荡市中易产生频繁假信号。

Python环境准备


import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import yfinance as yf

使用yfinance获取历史行情数据。以某股票为例,获取收盘价序列。

数据获取与预处理


ticker = 'AAPL'

data = yf.download(ticker, start='2020-01-01', end='2023-12-31')

close = data['Close']

清理缺失值,确保数据连续性。将索引设为日期格式,便于后续操作。

双均线策略python实证怎么做

计算均线指标

定义函数计算简单移动平均线。


def sma(series, window):

    return series.rolling(window=window).mean()

short_window = 20

long_window = 50

short_ma = sma(close, short_window)

long_ma = sma(close, long_window)

将均线数据合并到一个DataFrame中,便于处理。


df = pd.DataFrame({'Close': close, 'Short_MA': short_ma, 'Long_MA': long_ma})

df.dropna(inplace=True)

生成交易信号

根据金叉死叉生成方向信号。用1代表持有多头,-1代表持有空头(或0代表空仓)。


df['Signal'] = 0

df.loc[df['Short_MA'] > df['Long_MA'], 'Signal'] = 1

df.loc[df['Short_MA'] < df['Long_MA'], 'Signal'] = -1

策略只在信号变化时交易,因此计算信号变化点。


df['Position'] = df['Signal'].diff()

Position为1表示金叉买入,为-1表示死叉卖出。

回测框架构建

回测假设以收盘价成交,不考虑交易成本。计算每日收益率,并根据持仓状态计算策略收益。


df['Market_Return'] = df['Close'].pct_change()

df['Strategy_Return'] = df['Signal'].shift(1) * df['Market_Return']

shift(1)避免未来数据,因为信号基于当日收盘生成,次日执行。

累积净值计算:


df['Cum_Market'] = (1 + df['Market_Return']).cumprod()

df['Cum_Strategy'] = (1 + df['Strategy_Return']).cumprod()

绩效指标评估

计算年化收益率、最大回撤、夏普比率等。


def max_drawdown(series):

    peak = series.cummax()

    drawdown = (series - peak) / peak

    return drawdown.min()

ann_return = df['Cum_Strategy'].iloc[-1] ** (252/len(df)) - 1

sharpe = np.sqrt(252) * df['Strategy_Return'].mean() / df['Strategy_Return'].std()

max_dd = max_drawdown(df['Cum_Strategy'])

可视化与信号标注

绘制价格与均线,标注买卖点。


plt.figure(figsize=(14,7))

plt.plot(df['Close'], label='Close Price')

plt.plot(df['Short_MA'], label='Short MA')

plt.plot(df['Long_MA'], label='Long MA')

# 标注买入点

buy_signals = df[df['Position'] == 2]  # 实际买入出现时diff可能为2,需调整

# 正确做法:

buy = df[df['Signal'] == 1]  # 但需要区分变化点,此处简化

plt.plot(df.index[df['Signal'] == 1], df['Close'][df['Signal'] == 1], '^', markersize=10, color='g', label='Buy')

plt.plot(df.index[df['Signal'] == -1], df['Close'][df['Signal'] == -1], 'v', markersize=10, color='r', label='Sell')

plt.legend()

plt.title('Dual Moving Average Strategy')

plt.show()

更精确的买卖点需定位信号变化位置。

参数优化与敏感性分析

不同均线周期组合对策略影响巨大。通过循环测试多组参数,寻找最优解。


results = {}

for short in [5, 10, 20, 50]:

    for long in [50, 100, 200]:

        if short >= long:

            continue

        # 计算信号及收益,记录绩效指标

        results[(short, long)] = {'Annual': ann_return, 'Sharpe': sharpe}

过拟合风险需注意,可用样本外数据验证。

局限性与改进方向

双均线策略在盘整行情中会连续亏损,因均线纠缠产生多次假信号。改进方法包括添加过滤器,如ATR(平均真实波幅)过滤;结合其他指标确认;或引入动态均线周期。

完整实证示例

以下整合所有步骤,以实际数据运行策略并输出结果。


import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import yfinance as yf

# 获取数据

symbol = 'TSLA'

data = yf.download(symbol, start='2021-01-01', end='2023-12-31')

close = data['Close']

# 计算均线

short_ma = close.rolling(20).mean()

long_ma = close.rolling(50).mean()

# 构建数据框

df = pd.DataFrame({'Close': close, 'Short': short_ma, 'Long': long_ma}).dropna()

# 信号生成

df['Signal'] = np.where(df['Short'] > df['Long'], 1, 0)  # 多头持仓为1,空仓为0,可做多不做空

df['Position'] = df['Signal'].diff()

# 计算收益

df['Market_Ret'] = df['Close'].pct_change()

df['Strategy_Ret'] = df['Signal'].shift(1) * df['Market_Ret']

# 累积净值

df['Strategy_Nav'] = (1 + df['Strategy_Ret']).cumprod()

df['Market_Nav'] = (1 + df['Market_Ret']).cumprod()

# 绩效计算

ann_ret = df['Strategy_Nav'].iloc[-1] ** (252/len(df)) - 1

sharpe = np.sqrt(252) * df['Strategy_Ret'].mean() / df['Strategy_Ret'].std()

max_dd = (df['Strategy_Nav'] / df['Strategy_Nav'].cummax() - 1).min()

print(f'年化收益: {ann_ret:.2%}')

print(f'夏普比率: {sharpe:.2f}')

print(f'最大回撤: {max_dd:.2%}')

# 可视化

plt.figure(figsize=(12,6))

plt.plot(df['Strategy_Nav'], label='Strategy')

plt.plot(df['Market_Nav'], label='Buy & Hold')

plt.legend()

plt.title('Strategy vs Buy & Hold')

plt.show()

实战注意事项

回测中忽略交易成本导致业绩虚高。实盘需考虑佣金、滑点和市场冲击。策略信号可能在收盘后产生,次日开盘执行,模拟时需处理。市场风格切换导致均线参数失效,需定期调整。

双均线策略python实证流程清晰,从数据到回测均可代码化。该策略简单易懂,但盈利依赖市场趋势能持续。实证结果需结合市场环境综合评判,不可盲目依赖单一策略。通过不断测试与优化,可提升策略稳健性。