VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > python数据分析 >
  • 经典技术指标实现:均线金叉、MACD背离、布林带突破

第20章 经典技术指标实战
20.1 经典技术指标实现:均线金叉、MACD背离、布林带突破
20.1.1 先讲个真实需求:老板要我实现经典技术指标
上个月老板让我实现经典技术指标,包括均线金叉、MACD背离、布林带突破,还要能在综合看盘工具中集成。我之前只会用Tushare获取数据,完全不知道怎么自己实现这些技术指标。后来发现Pandas可以轻松实现这些技术指标,而且还能添加信号标记。今天我就把实现经典技术指标的方法讲清楚,帮你快vb.net教程C#教程python教程SQL教程access 2010教程速做出专业的技术指标分析工具。

20.1.2 核心技术:技术指标计算与信号标记

  1. 技术指标计算
    技术指标是通过对股票的价格、成交量等数据进行计算得到的,用于分析股票的走势和买卖时机。常用的技术指标有均线、MACD、布林带等。
  2. 信号标记
    信号标记是指在技术指标中标记出买入或卖出信号,帮助我们更直观地分析股票的走势和买卖时机。常用的信号标记有均线金叉、均线死叉、MACD背离、布林带突破等。

20.1.3 实战:实现均线金叉、MACD背离、布林带突破

  1. 实战代码:经典技术指标实现
    python
	# 1. 导入需要的库
	import tushare as ts
	import pandas as pd
	import numpy as np
	import plotly.graph_objects as go
	from datetime import datetime, timedelta
	
	# 2. 获取股票行情数据
	pro = ts.pro_api()
	# 获取贵州茅台的行情数据
	ts_code = '600519.SH'
	start_date = (datetime.now() - timedelta(days=365)).strftime('%Y%m%d')
	end_date = datetime.now().strftime('%Y%m%d')
	df = pro.daily(ts_code=ts_code, start_date=start_date, end_date=end_date)
	df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
	df.sort_values('trade_date', inplace=True)
	df.set_index('trade_date', inplace=True)
	
	# 3. 计算均线指标
	def calculate_ma(df, short_window=5, long_window=20):
	# 计算短期均线和长期均线
	df['ma_short'] = df['close'].rolling(window=short_window).mean()
	df['ma_long'] = df['close'].rolling(window=long_window).mean()
	
	# 标记均线金叉和死叉信号
	# 金叉:短期均线从下往上穿过长期均线
	df['ma_gold_cross'] = np.where((df['ma_short'] > df['ma_long']) & (df['ma_short'].shift(1) <= df['ma_long'].shift(1)), 1, 0)
	# 死叉:短期均线从上往下穿过长期均线
	df['ma_death_cross'] = np.where((df['ma_short'] < df['ma_long']) & (df['ma_short'].shift(1) >= df['ma_long'].shift(1)), 1, 0)
	
	return df
	
	df = calculate_ma(df)
	
	# 4. 计算MACD指标
	def calculate_macd(df, fast_period=12, slow_period=26, signal_period=9):
	# 计算短期EMA和长期EMA
	df['ema_fast'] = df['close'].ewm(span=fast_period, adjust=False).mean()
	df['ema_slow'] = df['close'].ewm(span=slow_period, adjust=False).mean()
	# 计算DIF和DEA
	df['macd_dif'] = df['ema_fast'] - df['ema_slow']
	df['macd_dea'] = df['macd_dif'].ewm(span=signal_period, adjust=False).mean()
	# 计算MACD柱状图
	df['macd_bar'] = 2 * (df['macd_dif'] - df['macd_dea'])
	
	# 标记MACD背离信号
	# 顶背离:股价创新高,但MACD不创新高
	df['price_high'] = df['close'].rolling(window=5).max()
	df['macd_high'] = df['macd_dif'].rolling(window=5).max()
	df['macd_top_divergence'] = np.where((df['close'] == df['price_high']) & (df['macd_dif'] < df['macd_high'].shift(1)), 1, 0)
	# 底背离:股价创新低,但MACD不创新低
	df['price_low'] = df['close'].rolling(window=5).min()
	df['macd_low'] = df['macd_dif'].rolling(window=5).min()
	df['macd_bottom_divergence'] = np.where((df['close'] == df['price_low']) & (df['macd_dif'] > df['macd_low'].shift(1)), 1, 0)
	
	return df
	
	df = calculate_macd(df)
	
	# 5. 计算布林带指标
	def calculate_bollinger_bands(df, window=20, num_std=2):
	# 计算中轨(均线)
	df['boll_mid'] = df['close'].rolling(window=window).mean()
	# 计算标准差
	df['boll_std'] = df['close'].rolling(window=window).std()
	# 计算上轨和下轨
	df['boll_upper'] = df['boll_mid'] + num_std * df['boll_std']
	df['boll_lower'] = df['boll_mid'] - num_std * df['boll_std']
	
	# 标记布林带突破信号
	# 上轨突破:股价从上往下突破上轨
	df['boll_upper_break'] = np.where((df['close'] > df['boll_upper']) & (df['close'].shift(1) <= df['boll_upper'].shift(1)), 1, 0)
	# 下轨突破:股价从下往上突破下轨
	df['boll_lower_break'] = np.where((df['close'] < df['boll_lower']) & (df['close'].shift(1) >= df['boll_lower'].shift(1)), 1, 0)
	
	return df
	
	df = calculate_bollinger_bands(df)
	
	# 6. 绘制技术指标图表
	# 6.1 绘制均线指标图表
	fig_ma = go.Figure()
	# 绘制K线图
	fig_ma.add_trace(go.Candlestick(
	x=df.index,
	open=df['open'],
	high=df['high'],
	low=df['low'],
	close=df['close'],
	name='K线图',
	increasing_line_color='red',
	decreasing_line_color='green'
	))
	# 绘制短期均线和长期均线
	fig_ma.add_trace(go.Scatter(
	x=df.index,
	y=df['ma_short'],
	name='5日均线',
	line=dict(color='#1f77b4', width=2),
	opacity=0.8
	))
	fig_ma.add_trace(go.Scatter(
	x=df.index,
	y=df['ma_long'],
	name='20日均线',
	line=dict(color='#ff7f0e', width=2),
	opacity=0.8
	))
	# 标记均线金叉和死叉信号
	gold_cross_df = df[df['ma_gold_cross'] == 1]
	fig_ma.add_trace(go.Scatter(
	x=gold_cross_df.index,
	y=gold_cross_df['low'] * 0.98,
	mode='markers',
	marker=dict(color='#2ca02c', size=10, symbol='triangle-up'),
	name='均线金叉'
	))
	death_cross_df = df[df['ma_death_cross'] == 1]
	fig_ma.add_trace(go.Scatter(
	x=death_cross_df.index,
	y=death_cross_df['high'] * 1.02,
	mode='markers',
	marker=dict(color='#d62728', size=10, symbol='triangle-down'),
	name='均线死叉'
	))
	# 设置图表布局
	fig_ma.update_layout(
	title=f'{ts_code}均线指标分析',
	yaxis_title='价格(元)',
	xaxis_title='日期',
	template='plotly_white',
	hovermode='x unified',
	legend={'x': 0.02, 'y': 0.98}
	)
	fig_ma.update_xaxes(rangeslider_visible=False)
	# 保存网页
	fig_ma.write_html(f'{ts_code}_均线指标分析.html')
	# 显示图表
	fig_ma.show()
	
	# 6.2 绘制MACD指标图表
	fig_macd = go.Figure()
	# 绘制DIF和DEA
	fig_macd.add_trace(go.Scatter(
	x=df.index,
	y=df['macd_dif'],
	name='DIF',
	line=dict(color='#1f77b4', width=2),
	opacity=0.8
	))
	fig_macd.add_trace(go.Scatter(
	x=df.index,
	y=df['macd_dea'],
	name='DEA',
	line=dict(color='#ff7f0e', width=2),
	opacity=0.8
	))
	# 绘制MACD柱状图
	fig_macd.add_trace(go.Bar(
	x=df.index,
	y=df['macd_bar'],
	name='MACD柱状图',
	marker_color=np.where(df['macd_bar'] > 0, '#2ca02c', '#d62728'),
	opacity=0.7
	))
	# 标记MACD背离信号
	top_divergence_df = df[df['macd_top_divergence'] == 1]
	fig_macd.add_trace(go.Scatter(
	x=top_divergence_df.index,
	y=top_divergence_df['macd_dif'] * 1.1,
	mode='markers',
	marker=dict(color='#d62728', size=10, symbol='triangle-up'),
	name='MACD顶背离'
	))
	bottom_divergence_df = df[df['macd_bottom_divergence'] == 1]
	fig_macd.add_trace(go.Scatter(
	x=bottom_divergence_df.index,
	y=bottom_divergence_df['macd_dif'] * 0.9,
	mode='markers',
	marker=dict(color='#2ca02c', size=10, symbol='triangle-down'),
	name='MACD底背离'
	))
	# 设置图表布局
	fig_macd.update_layout(
	title=f'{ts_code}MACD指标分析',
	yaxis_title='MACD值',
	xaxis_title='日期',
	template='plotly_white',
	hovermode='x unified',
	legend={'x': 0.02, 'y': 0.98}
	)
	# 保存网页
	fig_macd.write_html(f'{ts_code}_MACD指标分析.html')
	# 显示图表
	fig_macd.show()
	
	# 6.3 绘制布林带指标图表
	fig_boll = go.Figure()
	# 绘制K线图
	fig_boll.add_trace(go.Candlestick(
	x=df.index,
	open=df['open'],
	high=df['high'],
	low=df['low'],
	close=df['close'],
	name='K线图',
	increasing_line_color='red',
	decreasing_line_color='green'
	))
	# 绘制布林带
	fig_boll.add_trace(go.Scatter(
	x=df.index,
	y=df['boll_upper'],
	name='上轨',
	line=dict(color='#d62728', width=2),
	opacity=0.8
	))
	fig_boll.add_trace(go.Scatter(
	x=df.index,
	y=df['boll_mid'],
	name='中轨',
	line=dict(color='#1f77b4', width=2),
	opacity=0.8
	))
	fig_boll.add_trace(go.Scatter(
	x=df.index,
	y=df['boll_lower'],
	name='下轨',
	line=dict(color='#2ca02c', width=2),
	opacity=0.8
	))
	# 标记布林带突破信号
	upper_break_df = df[df['boll_upper_break'] == 1]
	fig_boll.add_trace(go.Scatter(
	x=upper_break_df.index,
	y=upper_break_df['high'] * 1.02,
	mode='markers',
	marker=dict(color='#d62728', size=10, symbol='triangle-up'),
	name='上轨突破'
	))
	lower_break_df = df[df['boll_lower_break'] == 1]
	fig_boll.add_trace(go.Scatter(
	x=lower_break_df.index,
	y=lower_break_df['low'] * 0.98,
	mode='markers',
	marker=dict(color='#2ca02c', size=10, symbol='triangle-down'),
	name='下轨突破'
	))
	# 设置图表布局
	fig_boll.update_layout(
	title=f'{ts_code}布林带指标分析',
	yaxis_title='价格(元)',
	xaxis_title='日期',
	template='plotly_white',
	hovermode='x unified',
	legend={'x': 0.02, 'y': 0.98}
	)
	fig_boll.update_xaxes(rangeslider_visible=False)
	# 保存网页
	fig_boll.write_html(f'{ts_code}_布林带指标分析.html')
	# 显示图表
	fig_boll.show()
	
	# 7. 保存技术指标数据
	df.to_csv(f'{ts_code}_技术指标数据_{datetime.now().strftime("%Y%m%d")}.csv', encoding='utf-8-sig')
	print(f'技术指标数据已保存到{ts_code}_技术指标数据_{datetime.now().strftime("%Y%m%d")}.csv')

逐行讲解:
df['ma_short'] = df['close'].rolling(window=short_window).mean():计算短期均线,rolling(window=short_window)表示滑动窗口大小为short_window,mean()表示计算窗口内的平均值
df['ma_gold_cross'] = np.where((df['ma_short'] > df['ma_long']) & (df['ma_short'].shift(1) <= df['ma_long'].shift(1)), 1, 0):标记均线金叉信号,np.where(condition, value_if_true, value_if_false)表示如果条件满足则返回value_if_true,否则返回value_if_false
df['ema_fast'] = df['close'].ewm(span=fast_period, adjust=False).mean():计算短期EMA,ewm(span=fast_period, adjust=False)表示指数加权移动平均,span表示窗口大小,adjust=False表示使用递归计算方法
df['macd_top_divergence'] = np.where((df['close'] == df['price_high']) & (df['macd_dif'] < df['macd_high'].shift(1)), 1, 0):标记MACD顶背离信号,当股价创新高但MACD不创新高时标记为1
df['boll_upper'] = df['boll_mid'] + num_std * df['boll_std']:计算布林带上轨,num_std表示标准差的倍数,通常为2
df['boll_upper_break'] = np.where((df['close'] > df['boll_upper']) & (df['close'].shift(1) <= df['boll_upper'].shift(1)), 1, 0):标记布林带上轨突破信号,当股价从上往下突破上轨时标记为1
运行结果:
会生成三个HTML文件和一个CSV文件:
1.600519.SH_均线指标分析.html:均线指标分析图表,包含K线图、均线、均线金叉和死叉信号
2.600519.SH_MACD指标分析.html:MACD指标分析图表,包含DIF、DEA、MACD柱状图、MACD顶背离和底背离信号
3.600519.SH_布林带指标分析.html:布林带指标分析图表,包含K线图、布林带、布林带上轨和下轨突破信号
4.600519.SH_技术指标数据_20250710.csv:保存技术指标数据,包括均线、MACD、布林带和信号标记

20.1.4 基础知识拓展:技术指标的分析方法

  1. 均线指标分析
    均线指标是最常用的技术指标之一,用于分析股票的走势和买卖时机。均线金叉通常是买入信号,均线死叉通常是卖出信号。但需要注意的是,均线指标是滞后指标,不能单独作为买卖决策的依据,需要结合其他技术指标和基本面分析。
  2. MACD指标分析
    MACD指标是一种趋势跟踪指标,用于分析股票的走势和买卖时机。MACD金叉(DIF上穿DEA)通常是买入信号,MACD死叉(DIF下穿DEA)通常是卖出信号。MACD背离是一种更高级的分析方法,顶背离通常是卖出信号,底背离通常是买入信号。
  3. 布林带指标分析
    布林带指标是一种波动率指标,用于分析股票的走势和买卖时机。布林带上轨突破通常是卖出信号,布林带下轨突破通常是买入信号。但需要注意的是,布林带指标是基于波动率的,当股票的波动率较低时,布林带会收窄,此时突破信号的可靠性较低。

20.1.5 实战优化:添加技术指标信号的回测

  1. 实战代码:添加技术指标信号的回测
    python
	# 8. 技术指标信号回测
	def backtest_signals(df):
	# 初始化回测参数
	initial_capital = 100000 # 初始资金
	position = 0 # 持仓数量
	cash = initial_capital # 现金
	portfolio_value = [] # 投资组合价值
	
	for index, row in df.iterrows():
	# 均线金叉买入信号
	if row['ma_gold_cross'] == 1 and position == 0:
	position = cash // row['close']
	cash -= position * row['close']
	print(f'{index.strftime("%Y-%m-%d")} 均线金叉买入,买入价格: {row["close"]:.2f}元,持仓数量: {position}股')
	# 均线死叉卖出信号
	elif row['ma_death_cross'] == 1 and position > 0:
	cash += position * row['close']
	position = 0
	print(f'{index.strftime("%Y-%m-%d")} 均线死叉卖出,卖出价格: {row["close"]:.2f}元,现金: {cash:.2f}元')
	# MACD底背离买入信号
	elif row['macd_bottom_divergence'] == 1 and position == 0:
	position = cash // row['close']
	cash -= position * row['close']
	print(f'{index.strftime("%Y-%m-%d")} MACD底背离买入,买入价格: {row["close"]:.2f}元,持仓数量: {position}股')
	# MACD顶背离卖出信号
	elif row['macd_top_divergence'] == 1 and position > 0:
	cash += position * row['close']
	position = 0
	print(f'{index.strftime("%Y-%m-%d")} MACD顶背离卖出,卖出价格: {row["close"]:.2f}元,现金: {cash:.2f}元')
	# 布林带下轨突破买入信号
	elif row['boll_lower_break'] == 1 and position == 0:
	position = cash // row['close']
	cash -= position * row['close']
	print(f'{index.strftime("%Y-%m-%d")} 布林带下轨突破买入,买入价格: {row["close"]:.2f}元,持仓数量: {position}股')
	# 布林带上轨突破卖出信号
	elif row['boll_upper_break'] == 1 and position > 0:
	cash += position * row['close']
	position = 0
	print(f'{index.strftime("%Y-%m-%d")} 布林带上轨突破卖出,卖出价格: {row["close"]:.2f}元,现金: {cash:.2f}元')
	
	# 计算投资组合价值
	portfolio_value.append(cash + position * row['close'])
	
	# 计算回测指标
	portfolio_value = pd.Series(portfolio_value, index=df.index)
	# 累计收益率
	cumulative_return = (portfolio_value.iloc[-1] - initial_capital) / initial_capital * 100
	# 年化收益率
	annualized_return = (1 + cumulative_return / 100) ** (252 / len(df)) - 1
	# 最大回撤
	rolling_max = portfolio_value.cummax()
	drawdown = (portfolio_value - rolling_max) / rolling_max
	max_drawdown = drawdown.min() * 100
	
	print(f'回测结果:')
	print(f'初始资金: {initial_capital:.2f}元')
	print(f'最终资金: {portfolio_value.iloc[-1]:.2f}元')
	print(f'累计收益率: {cumulative_return:.2f}%')
	print(f'年化收益率: {annualized_return:.2f}%')
	print(f'最大回撤: {max_drawdown:.2f}%')
	
	# 绘制回测曲线
	fig_backtest = go.Figure()
	fig_backtest.add_trace(go.Scatter(
	x=portfolio_value.index,
	y=portfolio_value,
	name='投资组合价值',
	line=dict(color='#1f77b4', width=2),
	opacity=0.8
	))
	fig_backtest.add_trace(go.Scatter(
	x=df.index,
	y=initial_capital + (df['close'] - df['close'].iloc[0]) * (initial_capital // df['close'].iloc[0]),
	name='持有股票价值',
	line=dict(color='#ff7f0e', width=2),
	opacity=0.8
	))
	fig_backtest.update_layout(
	title=f'{ts_code}技术指标信号回测',
	yaxis_title='投资组合价值(元)',
	xaxis_title='日期',
	template='plotly_white',
	hovermode='x unified',
	legend={'x': 0.02, 'y': 0.98}
	)
	fig_backtest.write_html(f'{ts_code}_技术指标信号回测.html')
	fig_backtest.show()
	
	return portfolio_value
	
	portfolio_value = backtest_signals(df)

运行结果:
会打印回测结果,包括初始资金、最终资金、累计收益率、年化收益率、最大回撤等指标,同时会生成一个HTML文件600519.SH_技术指标信号回测.html,包含投资组合价值和持有股票价值的对比曲线。

20.1.6 总结:技术指标的应用场景
1.投资决策:通过技术指标分析,可以识别股票的走势和买卖时机,辅助投资决策。
2.量化策略:在量化策略中,技术指标可以用于构建交易策略,当技术指标发出买入信号时买入股票,当技术指标发出卖出信号时卖出股票。
3.风险控制:通过技术指标分析,可以识别股票的走势和风险,及时卖出股票,控制投资风险。
4.市场监控:通过技术指标分析,可以监控市场的热点板块和龙头股票,把握市场的投资机会。
通过这个实战,你应该已经掌握了实现均线金叉、MACD背离、布林带突破等经典技术指标的方法,包括技术指标计算、信号标记、图表绘制、回测分析等功能。接下来可以尝试用这些方法制作更专业的技术指标分析工具和量化交易系统。
下一节咱们就讲如何用Python做量化策略回测,帮你验证策略的有效性。

 本站原创,转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49716.html


相关教程