双均线策略

该博客介绍了如何实现双均线交易策略,包括计算长期和短期均线,判断买入与卖出信号,绘制交易点,计算持仓收益及交易成本,并对策略进行年化收益、波动率、夏普比率和最大回撤等绩效指标的评估。通过Python和pandas库完成整个过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:

1.导入需要的包

2.设置变量回测开始时间,股票代码名称

3.定义load_ohlc_from_local读取本地文件600519.csv,设置日期为索引,以DataFrame的格式返还

4.设置变量长期均线,短期均线并计算它们各自的平均值

5.计算做多信号,判断如果短期均线上穿长期均线则产生买入信号1,若短期均线下穿长期均线,则产生卖出信号-1,其他时候为无信号0

6.创建用于标记做多位置的标记,根据信号得到买入和不买入的位置索引

7.绘制入场和出场点,红色三角形为买入点,绿色星号为不买入点,并绘制短期和长期移动平均线

8.计算昨日的持仓状态和当日的收益计算

9.根据买入和卖出信号计算交易成本包含了印花税,滑点,佣金

10.计算年化收益,波动率和夏普比率,用于评估策略表现

11.计算最大回撤找到资产净值曲线最高最低点之间的最大回撤

12.绘制累计收益和最大回撤曲线图

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']


bt_start_date = '2018-05-01'
stk_code, stk_name ='sh600519',  u'贵州茅台'

def load_ohlc_from_local():
    df = pd.read_csv('600519.csv')
    df['datetime']=pd.to_datetime(df['date'], format='%Y-%m-%d', errors='coerce')
    df =df.set_index('datetime')
    return df


smalen = 20  # short
lmalen = 60  # long
dfohlc = load_ohlc_from_local()
dfohlc['SMA'] = dfohlc['close'].rolling(smalen).mean()
dfohlc['LMA'] = dfohlc['close'].rolling(lmalen).mean()
# 调用load_ohlc_from_local()函数加载股票数据,并在数据上计算SMA和LMA

# 计算做多信号
dfohlc['long'] = ((dfohlc['SMA'] > dfohlc['LMA']) &
                  (dfohlc['SMA'].shift(1) < dfohlc['LMA'].shift(1))
                  ).replace({True: 1, False: 0})
dfohlc['long'] += ((dfohlc['SMA'] < dfohlc['LMA']) &
                   (dfohlc['SMA'].shift(1) > dfohlc['LMA'].shift(1))
                   ).replace({True: -1, False: 0})
dfohlc['long'].replace({0: np.nan}, inplace=True)
dfohlc['long'].fillna(method='ffill', inplace=True)
dfohlc['long'].replace({-1: 0}, inplace=True)

# 创建用于标记做多位置的标记
plot_start_date = bt_start_date
# plot_start_date = '2018-05-01'
df = dfohlc.loc[plot_start_date:, 'long'].reset_index(drop=True)
idx_long_pos = df[df == 1].index.to_list()
idx_no_pos = df[df == 0].index.to_list()

# 绘制入场和出场点
dfclose = dfohlc.loc[plot_start_date:, 'close']

fig, axes = plt.subplots(2, 1)
ax0, ax1 = axes
ax0.plot(dfclose, color='gray', lw=2.)  # lw = line width
ax0.plot(dfclose, '^', markersize=3, color='r', label='Long pos', markevery=idx_long_pos)
ax0.plot(dfclose, '*', markersize=3, color='g', label='No pos', markevery=idx_no_pos)
ax0.plot(dfohlc.loc[plot_start_date:, 'SMA'], color='blue', label='SMA')
ax0.plot(dfohlc.loc[plot_start_date:, 'LMA'], color='purple', label='LMA')
ax0.legend(fontsize=12)
ax0.set_title(stk_name, fontsize=16)

ax0.tick_params(labelsize=12)
ax0.tick_params(axis='x', rotation=30)

ax0.grid()
plt.show()

dfohlc['daily_ret'] = dfohlc['long'].shift(1) * dfohlc['pctChg'] / 100

# 减去交易成本
commission = 0.0003
stamp_duty = 0.001
slippage = 0.001
dfohlc['long'].fillna(0, inplace=True)
dfohlc['buy'] = (dfohlc['long'] - dfohlc['long'].shift(1)) == 1
dfohlc['sell'] = (dfohlc['long'] - dfohlc['long'].shift(1)) == -1
dfohlc['trade_cost'] = dfohlc['buy'] * (commission + slippage)
dfohlc['trade_cost'] += dfohlc['sell'] * \
    (commission + slippage + stamp_duty)

dfohlc['daily_ret'] -= dfohlc['trade_cost']

# 计算回测资产净值
dfohlc['equity'] = (1 + dfohlc['daily_ret']).cumprod()

dfohlc.index.name = ''
dfohlc.loc[plot_start_date:, 'equity'].plot(
    title ='Backtest Performance',
    color='red', ax=ax1)
ax1.grid()
ax1.tick_params(labelsize=12)

plt.tight_layout()

# 计算年化收益率、波动率和夏普比率
rfr = .0  # risk free rate
ann_ret = dfohlc['daily_ret'].mean() * 252
ann_vol = dfohlc['daily_ret'].std() * np.sqrt(252)
Sharpe = (ann_ret - rfr) / ann_vol
print('Sharpe is %.02f.' % Sharpe)

# 计算最大回撤
dfohlc['pre_peak'] = dfohlc['equity'].cummax()
dfohlc['Maximum Drawdown'] = dfohlc['equity'] / dfohlc['pre_peak'] - 1
print('Maximum Drawdown is %.02f%%.' %
      (dfohlc['Maximum Drawdown'].min() * 100))


# 绘制累计收益和最大回撤曲线
dfohlc['Cumulative Return'] = dfohlc['equity'] - 1

fig, ax = plt.subplots()
dfohlc.index.name = ''
dfohlc['Maximum Drawdown'].plot(ax=ax)
ax.set_title('Maximum Drawdown', fontsize=16)
ax.grid()

效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值