双均线策略用Python怎么回测股票期货数据

企业微信

双均线策略到底在赚什么钱

股票和期货市场里,大部分人亏钱是因为总想预测明天涨跌。双均线策略不猜明天,它只做一件事:趋势来了就跟上,趋势走了就离开。短期均线代表最近价格的平均成本,长期均线代表更长时间的平均成本。短期均线从下往上穿过长期均线,说明近期买入的人愿意用更高的价格接手,趋势可能向上。短期均线从上往下穿过长期均线,说明近期卖出的人愿意用更低的价格抛售,趋势可能向下。

这个策略赚的是趋势的钱。震荡市里它会连续亏损,因为价格来回穿越均线。趋势市里它能抓住一大段行情。股票T+1制度下,当天买入不能卖出,双均线策略的信号频率不能太高。期货T+0且带杠杆,信号执行更灵活,但杠杆会放大亏损。

双均线策略用Python怎么回测股票期货数据

用Python准备股票期货数据

回测第一步是拿到干净的数据。股票数据可以从免费接口获取,期货数据需要主力连续合约。这里用pandas和yfinance演示股票,期货数据可以用akshare或者本地CSV。


import pandas as pd

import yfinance as yf

import numpy as np

import matplotlib.pyplot as plt

# 获取股票数据,以苹果公司为例

df = yf.download('AAPL', start='2020-01-01', end='2024-12-31')

df = df[['Close']].copy()

df.columns = ['close']

# 获取期货数据,以国内螺纹钢主力连续为例

# import akshare as ak

# df = ak.futures_main_sina(symbol="RB0", start_date="2020-01-01", end_date="2024-12-31")

# df = df[['收盘价']].rename(columns={'收盘价':'close'})

# df.index = pd.to_datetime(df['日期'])

print(df.head())

print(df.tail())

数据必须按时间升序排列,缺失值用前值填充或者删除。股票有分红拆股,yfinance默认返回调整后价格。期货主力连续合约在换月时会有跳空,需要做后复权处理,否则均线会被假信号干扰。

计算双均线并生成交易信号

短期均线参数常用5到20,长期均线常用20到60。股票波动小,可以用10和30。期货波动大,可以用5和20。参数不是固定的,不同品种需要测试。


short_window = 10

long_window = 30

df['short_ma'] = df['close'].rolling(window=short_window).mean()

df['long_ma'] = df['close'].rolling(window=long_window).mean()

df['signal'] = 0

df.loc[df['short_ma'] > df['long_ma'], 'signal'] = 1

df.loc[df['short_ma'] <= df['long_ma'], 'signal'] = 0

df['position'] = df['signal'].diff()

print(df[['close','short_ma','long_ma','signal','position']].dropna().head(20))

position等于1是买入信号,等于-1是卖出信号。信号在收盘后产生,第二天开盘执行。股票不能做空,signal为0时只能空仓。期货可以做空,signal为0时可以开空仓。

回测收益与风险指标

回测要算清楚每笔交易的成本。股票佣金万分之二点五,卖出印花税千分之一。期货手续费按手数或者成交额比例。滑点按一个最小变动价位计算。


df['market_return'] = df['close'].pct_change()

df['strategy_return'] = df['signal'].shift(1) * df['market_return']

# 扣除交易成本,假设每次换仓成本为0.1%

cost = 0.001

df['trade'] = df['position'].abs()

df['strategy_return_net'] = df['strategy_return'] - df['trade'].shift(1) * cost

df['cum_market'] = (1 + df['market_return']).cumprod()

df['cum_strategy'] = (1 + df['strategy_return_net']).cumprod()

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

total_days = len(df)

annual_return = df['cum_strategy'].iloc[-1] ** (252/total_days) - 1

drawdown = (df['cum_strategy'] / df['cum_strategy'].cummax() - 1).min()

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

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

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

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

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

plt.plot(df['cum_market'], label='买入持有')

plt.plot(df['cum_strategy'], label='双均线策略')

plt.legend()

plt.title('双均线策略回测')

plt.show()

年化收益高不代表策略好。最大回撤太大,实盘时心理压力会让人提前离场。夏普比率低于1,说明承担的风险没有换来足够收益。股票买入持有在牛市中可能跑赢双均线,因为均线信号滞后。期货带杠杆,双均线能控制单笔亏损,但连续亏损会吃掉本金。

参数怎么选才不坑自己

参数优化最容易犯的错是拿全部历史数据找最优参数。这样找到的是历史最幸运的参数,未来一定失效。正确做法是把数据分成训练集和测试集。训练集找参数,测试集验证。

股票和期货的均线参数不一样。股票趋势慢,长期均线可以到60。期货趋势快,长期均线20到40足够。不同品种的波动率不同,参数需要单独测试。螺纹钢和原油的节奏完全不同,用同一套参数一定有一个亏钱。

双均线策略在震荡市会反复止损。加一个过滤条件能减少假信号。价格在长期均线上方才允许做多,价格在长期均线下方才允许做空。或者用ATR指标过滤,波动太小的时候不交易。

实盘前必须知道的坑

回测用收盘价计算均线,实盘收盘前几分钟均线还没固定。用盘中价格计算均线,信号会闪烁。解决办法是收盘前5分钟用当前价格预估均线,或者等收盘后第二天开盘执行。

股票T+1,当天买入不能卖出。双均线信号如果当天买入又当天卖出,股票无法执行。期货T+0没有这个限制,但期货有涨跌停板,信号触发时可能无法成交。

滑点对高频信号影响很大。双均线策略信号不多,一年几次到几十次。每次滑点按一个最小变动价位算,期货一个点对应10元或者100元。滑点吃掉利润,参数越短信号越多,滑点成本越高。

双均线策略不是圣杯。它在大趋势里赚钱,在震荡里亏钱。股票市场牛短熊长,双均线能躲过大跌。期货市场杠杆高,双均线能控制单笔风险。用Python回测只是第一步,理解策略的赚钱逻辑和亏钱场景,才能决定要不要实盘。

转载请注明出处:https://www.lianghuajiaoyi.top/wenzhang/shuang-junxian-celve-Python-882.html