# 导入需要使用的库
import akshare as ak
import pandas as pd
import numpy as np
import pandas_ta as ta
# 在matplotlib绘图中显示中文和负号
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.family'] = 'STKAITI' # 中文字体'STKAITI'
plt.rcParams['axes.unicode_minus'] = False # 解决坐标轴负数的负号显示问题
# 关闭警告信息
import warnings
warnings.filterwarnings('ignore')
# 获取指数数据
index_code = 'sh000300'
start_date = pd.to_datetime('2014-01-01')
end_date = pd.to_datetime('2023-12-31')
price_df = ak.stock_zh_index_daily(symbol=index_code)
price_df['date'] = pd.to_datetime(price_df['date']).dt.date
price_df = price_df[(price_df['date']>=start_date) & (price_df['date']<=end_date)]
price_df = price_df.sort_values('date').set_index('date')
# 计算每日的收益率
price_df['returns'] = price_df['close'].pct_change().shift(-1).fillna(0)

# 计算长短双均线值
FastWindow = 9 # 快速均线窗口长度
SlowWindow = 2 * FastWindow # 慢速均线窗口长度
price_df['ma_s'] = ta.sma(price_df['close'], length=FastWindow)
price_df['ma_l'] = ta.sma(price_df['close'], length=SlowWindow)
# 计算布林带
std = 2.0 # 上下轨的标准差倍数
channel = ta.bbands(price_df['close'], length=SlowWindow, std=std)
up = f'BBU_{SlowWindow}_{std}' # 通道上轨
down = f'BBL_{SlowWindow}_{std}' # 通道下轨
middle = f'BBM_{SlowWindow}_{std}' # 通道中轨
price_df[['up_channel','down_channel']] = channel[[up, down]]
# 计算择时信号
# 开仓信号:当短均线位于长均线上方,并且价格突破了通道上轨时开仓
# 清仓信号:当短均线位于长均线下方,并且价格突破了通道下轨时清仓
timing_df = pd.DataFrame()
timing_df['择时'] = ((price_df['ma_s']>price_df['ma_l']) & (price_df['close']>price_df['up_channel'])) * 1. + \
((price_df['ma_s']<price_df['ma_l']) & (price_df['close']<price_df['down_channel'])) * -1.
timing_df = timing_df.replace(0, np.nan) # 先将0替换为NA
timing_df = timing_df.fillna(method='ffill').fillna(0) # 使用前值填充NA
timing_df[timing_df<=0] = 0
timing_df['不择时'] = 1.
# 设定止损触发价为通道中轨
price_df['stop_price'] = channel[middle]
# 如果收盘价低于止损触发价,则清仓止损
timing_df['择时'] = ((timing_df['择时'] == 1) & (price_df['close'] > price_df['stop_price'])) * 1.
# 计算择时和不择时的每日收益率
timing_ret = timing_df.mul(price_df['returns'], axis=0)
# 计算累计收益率
cumul_ret = (1 + timing_ret.fillna(0)).cumprod() - 1.
# 可视化输出
cumul_ret.plot(figsize=(10, 6), title='双均线结合通道突破择时和动态止损策略')

相关文章:
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/105997
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!