某只股票量化对冲策略计算绘图

量化对冲策略计算绘图

代码提要

代码运行环境,WIN 11 ,python 3.13

  1. 使用akshare获取股票数据,并用pandasewm函数
  2. 添加了akshare库获取真实股票数据
  3. 主程序中使用ak.stock_zh_index_daily获取上证指数数据
  4. 增加了异常处理,当获取数据失败时使用随机数据作为备选
  5. 确保数据列名与原代码兼容
  6. 截取最近200个交易日的数据进行计算

使用说明:

  1. 需要安装依赖库:pip install pandas numpy akshare
  2. 默认获取上证指数数据,可以通过修改ak.stock_zh_index_daily(symbol="sh000001")中的symbol参数获取其他股票数据
  3. 股票代码格式示例:
  • 上证指数: sh000001
  • 深证成指: sz399001
  • 创业板指: sz399006
  • 个股: sh600000(浦发银行) 或 sz000001(平安银行)
  • 本代码股票代码 sz000937 (冀中能源)

下面是添加了绘图功能的完整代码,使用matplotlib绘制股票价格和各项量化指标的图表:

import pandas as pdimport numpy as npimport akshare as akimport matplotlib.pyplot as pltimport matplotlib.dates as mdatesfrom matplotlib.ticker import MaxNLocatorimport matplotlib.patches as mpatchesimport warningsimport matplotlib.font_manager as fmimport os# 忽略警告warnings.filterwarnings('ignore')# 设置全局字体font_path = 'C:/Windows/Fonts/simhei.ttf'  # 黑体字体路径,根据实际情况修改if fm.findfont(fm.FontProperties(fname=font_path)):plt.rcParams['font.family'] = fm.FontProperties(fname=font_path).get_name()else:print("未找到指定字体,请检查路径。将使用默认字体。")# 解决负号显示问题plt.rcParams['axes.unicode_minus'] = Falsedef quant_hedge_strategy(df):# 主力暗盘资金副图指标df['量化对冲1'] = df['close'].ewm(span=9, adjust=False).mean()df['量化对冲3'] = (df['量化对冲1'] * 1.14).ewm(span=5, adjust=False).mean()df['量化对冲4'] = df['close'].ewm(span=2, adjust=False).mean()# 计算130日高低点df['130日高点'] = df['high'].rolling(130).max()df['130日低点'] = df['low'].rolling(130).min()# 计算条件柱状图df['stickline_cond'] = np.where(df['量化对冲4'] >= df['量化对冲3'], 1, 0)# 计算其他指标df['40日最低'] = df['low'].rolling(40).min()df['量化对冲2'] = (df['close'] - df['40日最低']) / df['40日最低'] * 100df['MA40'] = df['close'].rolling(40).mean()df['量化对冲7'] = (df['close'] - df['MA40']) / df['MA40'] * 100df['40日最低_MA40'] = df['40日最低'].rolling(40).mean()df['量化对冲8'] = (df['close'] - df['40日最低_MA40']) / df['40日最低_MA40'] * 100df['量化对冲9'] = 28df['量化对冲10'] = df['close'].rolling(5).mean()df['100日最高'] = df['量化对冲10'].rolling(100).max()df['量化对冲11'] = np.where(df['量化对冲10'] == df['100日最高'], df['量化对冲8'], np.nan)# 成本分布计算(简化为使用移动平均)df['cost90'] = df['close'].rolling(90).mean().shift(1)df['cost10'] = df['close'].rolling(10).mean().shift(1)df['量化对冲12'] = ((df['close'] * df['volume'] - df['cost90'] * df['volume']) / 20 + 250) * 1.2 / 5df['量化对冲13'] = ((df['cost90'] * df['volume'] - df['close'] * df['volume']) / 20 + 250) * 1.2 / 5df['量化对冲14'] = ((df['close'] * df['volume'] - df['cost10'] * df['volume']) / 20 + 250) * 1.2 / 5df['量化对冲15'] = ((df['cost10'] * df['volume'] - df['close'] * df['volume']) / 20 + 250) * 1.2 / 5# 主力暗盘资金副图指标信号条件df['量化对冲5'] = ((df['量化对冲14'] > 0) & ((df['量化对冲12'] > df['量化对冲13']) | (df['量化对冲12'] > 0))) df['量化对冲6'] = ((df['量化对冲14'] > 0) & (df['量化对冲12'] > 0) & (df['量化对冲13'] < 0) & (df['量化对冲15'] < 0))df['量化对冲5_count'] = df['量化对冲5'].rolling(10).sum()df['量化对冲6_count'] = df['量化对冲6'].rolling(60).sum()df['量化对冲16'] = ((df['量化对冲5'] & (df['量化对冲5_count'] == 1)) | (df['量化对冲6'] & (df['量化对冲6_count'] == 1)))df['量化对冲16_count'] = df['量化对冲16'].rolling(20).sum()df['起飞信号'] = np.where(df['量化对冲16'] & (df['量化对冲16_count'] == 1), df['量化对冲2'] * 1.16, np.nan)# 妖股信号df['量化对冲14_60日高点'] = df['量化对冲14'].rolling(60).max()df['量化对冲14_20日高点'] = df['量化对冲14'].rolling(20).max()df['妖股条件1'] = df['量化对冲14'] >= df['量化对冲14_60日高点']df['妖股条件2'] = (df['量化对冲14'] >= df['量化对冲14_20日高点']).rolling(20).sum() == 1df['妖股条件3'] = df['量化对冲14'] > df['量化对冲13']df['妖股信号'] = np.where(df['妖股条件1'] & df['妖股条件2'] & df['妖股条件3'],df['量化对冲2'] * 1.16, np.nan)# 交叉信号df['交叉信号'] = np.where(df['量化对冲2'].shift(1) < df['量化对冲9'], df['量化对冲2'], np.nan)return dfdef plot_quant_strategy(df, stock_name="上证指数"):"""绘制量化对冲策略图表"""# 创建一个包含4个子图的图表fig, axes = plt.subplots(4, 1, figsize=(16, 18), sharex=True)fig.suptitle(f'{stock_name}量化对冲策略分析', fontsize=16)# 绘制K线图和均线ax1 = axes[0]ax1.set_title('价格走势与均线', fontsize=14)ax1.plot(df.index, df['close'], label='收盘价', color='black', linewidth=2)ax1.plot(df.index, df['MA40'], label='MA40', color='blue', linestyle='--')ax1.plot(df.index, df['量化对冲10'], label='MA5', color='red', linestyle='--')# 绘制起飞信号signal_dates = df[~df['起飞信号'].isna()].indexsignal_values = df[~df['起飞信号'].isna()]['close']ax1.scatter(signal_dates, signal_values, color='green', s=100, label='起飞信号', marker='^')# 绘制妖股信号妖股_dates = df[~df['妖股信号'].isna()].index妖股_values = df[~df['妖股信号'].isna()]['close']ax1.scatter(妖股_dates, 妖股_values, color='purple', s=100, label='妖股信号', marker='*')# 绘制交叉信号cross_dates = df[~df['交叉信号'].isna()].indexcross_values = df[~df['交叉信号'].isna()]['close']ax1.scatter(cross_dates, cross_values, color='orange', s=100, label='交叉信号', marker='o')ax1.grid(True)ax1.legend(loc='upper left')ax1.set_ylabel('价格')# 绘制量化对冲2、9、11指标ax2 = axes[1]ax2.set_title('量化对冲指标2、9、11', fontsize=14)ax2.plot(df.index, df['量化对冲2'], label='量化对冲2', color='blue')ax2.plot(df.index, df['量化对冲9'], label='量化对冲9', color='red', linestyle='--')ax2.plot(df.index, df['量化对冲11'], label='量化对冲11', color='green', marker='o', linestyle='', alpha=0.7)# 填充量化对冲2大于量化对冲9的区域ax2.fill_between(df.index, df['量化对冲2'], df['量化对冲9'], where=(df['量化对冲2'] > df['量化对冲9']), color='lightgreen', alpha=0.3)# 填充量化对冲2小于量化对冲9的区域ax2.fill_between(df.index, df['量化对冲2'], df['量化对冲9'], where=(df['量化对冲2'] < df['量化对冲9']), color='lightcoral', alpha=0.3)ax2.grid(True)ax2.legend(loc='upper left')ax2.set_ylabel('指标值')# 绘制量化对冲12、13、14、15指标ax3 = axes[2]ax3.set_title('主力暗盘资金指标', fontsize=14)ax3.plot(df.index, df['量化对冲12'], label='量化对冲12', color='blue')ax3.plot(df.index, df['量化对冲13'], label='量化对冲13', color='red')ax3.plot(df.index, df['量化对冲14'], label='量化对冲14', color='green')ax3.plot(df.index, df['量化对冲15'], label='量化对冲15', color='purple')# 绘制起飞信号和妖股信号在这张图上的位置ax3.scatter(signal_dates, df.loc[signal_dates, '量化对冲14'], color='green', s=50, marker='^')ax3.scatter(妖股_dates, df.loc[妖股_dates, '量化对冲14'], color='purple', s=50, marker='*')ax3.grid(True)ax3.legend(loc='upper left')ax3.set_ylabel('资金指标')# 绘制量化对冲5、6指标柱状图ax4 = axes[3]ax4.set_title('量化对冲信号5、6', fontsize=14)# 绘制柱状图bar_width = 0.6quant5_positive = df['量化对冲5_count'].copy()quant5_positive[quant5_positive < 0] = 0quant6_positive = df['量化对冲6_count'].copy()quant6_positive[quant6_positive < 0] = 0ax4.bar(df.index, quant5_positive, width=bar_width, color='blue', alpha=0.7, label='量化对冲5')ax4.bar(df.index, quant6_positive, width=bar_width, color='green', alpha=0.7, label='量化对冲6')# 添加信号标记ax4.scatter(signal_dates, [0]*len(signal_dates), color='green', s=100, marker='^')ax4.scatter(妖股_dates, [0]*len(妖股_dates), color='purple', s=100, marker='*')ax4.grid(True)ax4.legend(loc='upper left')ax4.set_ylabel('信号强度')ax4.set_xlabel('日期')# 设置x轴日期格式locator = mdates.AutoDateLocator()formatter = mdates.ConciseDateFormatter(locator)for ax in axes:ax.xaxis.set_major_locator(locator)ax.xaxis.set_major_formatter(formatter)plt.tight_layout()plt.subplots_adjust(top=0.94)return fig# 使用示例if __name__ == "__main__":# 使用akshare获取股票数据try:# 获取上证指数数据,可替换为其他股票代码stock_data = ak.stock_zh_index_daily(symbol="sz000937")# 重命名列以匹配原代码df = stock_data.rename(columns={'date': 'date','open': 'open','high': 'high','low': 'low','close': 'close','volume': 'volume'})# 设置日期索引df['date'] = pd.to_datetime(df['date'])df.set_index('date', inplace=True)# 确保数据量足够if len(df) < 200:print(f"数据长度不足,只有{len(df)}行")else:# 截取最近200个交易日数据df = df.iloc[-200:]# 计算量化对冲指标result_df = quant_hedge_strategy(df)# 绘制图表fig = plot_quant_strategy(result_df, "冀中能源")# 显示图表plt.show()# 输出结果print(result_df[['量化对冲1', '量化对冲2', '量化对冲3', '量化对冲4', '量化对冲11', '起飞信号', '妖股信号', '交叉信号']].tail())except Exception as e:print(f"获取数据出错: {e}")print("使用随机数据作为替代")# 随机数据作为备选data = {'date': pd.date_range(start='2023-01-01', periods=200),'open': np.random.uniform(100, 200, 200),'high': np.random.uniform(110, 220, 200),'low': np.random.uniform(90, 190, 200),'close': np.random.uniform(100, 200, 200),'volume': np.random.randint(10000, 100000, 200)}df = pd.DataFrame(data)df.set_index('date', inplace=True)# 计算量化对冲指标result_df = quant_hedge_strategy(df)# 绘制图表fig = plot_quant_strategy(result_df, "随机数据")# 显示图表plt.show()# 输出结果print(result_df[['量化对冲1', '量化对冲2', '量化对冲3', '量化对冲4', '量化对冲11', '起飞信号', '妖股信号', '交叉信号']].tail())

新增的绘图功能特点:

  1. 包含4个子图,全面展示量化策略的各项指标:
  • 子图1:股票价格走势与关键均线,标记各种信号出现位置
  • 子图2:量化对冲2、9、11指标,填充指标间区域
  • 子图3:主力暗盘资金指标(量化对冲12-15)
  • 子图4:量化对冲信号5、6的柱状图
  1. 信号标记:
  • 绿色三角:起飞信号
  • 紫色星号:妖股信号
  • 橙色圆点:交叉信号
  1. 图表美化:
  • 自动调整日期显示格式
  • 添加网格线提高可读性
  • 每个子图都有标题和图例
  • 合理的颜色搭配
  1. 交互功能:
  • 鼠标悬停可查看具体数值
  • 可放大缩小特定区域
  • 可保存图表为图片文件

使用说明:

  1. 需要安装额外依赖库:pip install matplotlib
  2. 运行代码后会自动显示绘制的图表
  3. 图表标题会显示股票名称,默认为"上证指数"
  4. 可以通过修改plot_quant_strategy函数来自定义图表样式和内容

量化对冲指标的解释

以下是代码中主要量化对冲指标的解释,这些指标用于分析股票趋势、资金流向和潜在交易信号:

1. 趋势跟踪指标

量化对冲1
  • 计算方式EMA(close, 9)(9日指数移动平均线)
  • 作用:反映短期价格趋势,比简单均线更敏感,用于识别短期方向。
量化对冲3
  • 计算方式EMA(量化对冲1 × 1.14, 5)(对放大后的短期均线再做5日EMA)
  • 作用:增强趋势信号,放大短期波动,用于捕捉快速变化的趋势。
量化对冲4
  • 计算方式EMA(close, 2)(2日指数移动平均线)
  • 作用:超短期趋势指标,对价格变动极为敏感,用于识别极短期转折点。

2. 相对强弱指标

量化对冲2
  • 计算方式(close - 40日最低) / 40日最低 × 100
  • 作用:衡量当前价格相对于近40日最低价的涨幅百分比,类似于RSI指标,反映价格强度。
  • 信号逻辑:值越高,表明价格距离低点越远,可能处于超买区域;反之可能处于超卖区域。
量化对冲7
  • 计算方式(close - MA40) / MA40 × 100
  • 作用:衡量当前价格相对于40日均价的偏离程度,用于判断价格是否偏离均值过远(可能回调)。

3. 资金流向指标

量化对冲12-15
  • 计算方式:基于收盘价、成交量与不同周期成本价(90日/10日均价)的差值计算
    • 量化对冲12 = ((close × volume - cost90 × volume) / 20 + 250) × 1.2 / 5
    • 量化对冲13 = ((cost90 × volume - close × volume) / 20 + 250) × 1.2 / 5
    • 量化对冲14 = ((close × volume - cost10 × volume) / 20 + 250) × 1.2 / 5
    • 量化对冲15 = ((cost10 × volume - close × volume) / 20 + 250) × 1.2 / 5
  • 作用:模拟不同周期的资金流入流出情况,正值表示资金流入,负值表示资金流出。
  • 信号逻辑:当短期资金流入(如量化对冲14)强于长期资金流出(如量化对冲13)时,视为看涨信号。

4. 信号生成指标

起飞信号
  • 触发条件
    1. 量化对冲16为True(满足量化对冲5量化对冲6条件)
    2. 量化对冲16在近20天内首次出现
  • 作用:捕捉价格启动初期的信号,可能预示短期快速上涨。
妖股信号
  • 触发条件
    1. 量化对冲14 ≥ 量化对冲14_60日高点(短期资金流入创60日新高)
    2. 量化对冲14 ≥ 量化对冲14_20日高点在近20天内仅出现1次
    3. 量化对冲14 > 量化对冲13(短期资金流入强于长期流出)
  • 作用:识别可能出现大幅上涨的"妖股"特征,通常伴随强资金推动。
交叉信号
  • 触发条件量化对冲2的前一日值低于量化对冲9(阈值28),当日值高于或等于阈值
  • 作用:捕捉价格从弱势区域向上突破的转折点,类似MACD金叉信号。

5. 辅助指标

量化对冲5 & 量化对冲6
  • 量化对冲5:短期资金流入为正,且(短期资金流入>长期资金流出 或 短期资金流入为正)
  • 量化对冲6:短期资金流入为正,且短期和长期资金流入均为正,同时短期和长期资金流出均为负
  • 作用:量化对冲5侧重短期资金流向,量化对冲6要求更严格的资金面条件,两者结合用于确认强势信号。

策略逻辑总结

  1. 趋势判断:通过多周期均线(量化对冲1、3、4)识别价格趋势方向。
  2. 强弱评估:通过量化对冲2评估价格相对强度,结合阈值(量化对冲9)判断超买超卖。
  3. 资金监控:通过量化对冲12-15跟踪不同周期资金流向,判断多空力量对比。
  4. 信号生成:综合上述指标,生成起飞信号、妖股信号和交叉信号,作为交易决策依据。
    该策略适合用于识别短期趋势转折点和强势股,但实际应用中需结合止损机制和仓位管理,避免假信号带来的风险。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/910698.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE初阶第五期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(三)

专栏&#xff1a;JavaEE初阶起飞计划 个人主页&#xff1a;手握风云 目录 一、线程的状态 1.1. 观察所有线程的状态 1.2. 观察线程的状态和转移 1.3. 线程状态和状态转移的意义 二、线程安全 2.1. 观察线程不安全 2.2. 线程安全的概念 2.3. 线程不安全的原因 一、线程的…

Python爬虫实战:研究xmltodict库相关技术

1. 引言 1.1 研究背景与意义 气象数据在农业生产、交通规划、灾害预警等多个领域具有重要应用价值。传统的气象数据获取方式主要依赖于气象部门发布的统计信息,存在更新不及时、数据维度有限等问题。随着互联网技术的发展,气象网站提供了丰富的实时气象数据,但这些数据通常…

暴力风扇方案介绍

炎炎夏日&#xff0c;当普通风扇只能送来 “温柔拂面”&#xff0c;暴力风扇却能吹出 “台风级” 清凉&#xff01;想知道这些 “风力狂魔” 是如何炼成的&#xff1f;答案藏在电机、电路和芯片的黄金三角组合里。​ 一、电机&#xff1a;暴力风扇的 “心脏起搏器”​ 暴力风扇…

电子计数跳绳原型

引子 这些日子和跳绳杠上了&#xff0c;前些日子的拆解&#xff0c;让我有一个大胆的想法&#xff0c;就是能不能用3D打印写程序的方式实现一个计数功能的&#xff0c;当然看到有些结构这个现在实现起来有些难度&#xff0c;只能那原有的部件充数。目标只是说明一下原理&#…

桌面小屏幕实战课程:DesktopScreen 17 HTTPS

飞书文档http://https://x509p6c8to.feishu.cn/docx/doxcn8qjiNXmw2r3vBEdc7XCBCh 源码参考&#xff1a; /home/kemp/work/esp/esp-idf/examples/protocols/https_request 源码下载方式参考&#xff1a; 源码下载方式 获取网站ca证书 openssl s_client -showcerts -connec…

Spring Cloud:高级特性与最佳实践

一、Spring Cloud 高级特性 &#xff08;一&#xff09;分布式配置管理 分布式配置管理是微服务架构中的一个重要功能&#xff0c;Spring Cloud 提供了多种配置管理解决方案&#xff0c;如 Spring Cloud Config 和 Spring Cloud Consul。 Spring Cloud Config Spring Cloud C…

理解图像的随机噪声

图像灰度信息很难精确测量&#xff0c;一般情况下测量值总在真实值附近晃动&#xff0c;使用概率模型可以对该随机性建模&#xff0c;大致如下&#xff1a; 1 概率密度函数 1&#xff09;随机变量 x 的概率密度函数 p(x) 定义为&#xff1a;当 趋近于 0 时&#xff0c;在区间 上…

spring中maven缺少包如何重新加载,报错java: 程序包org.springframework.web.reactive.function不存在

错误原因分析 java: 程序包org.springframework.web.reactive.function不存在 这个错误是由于 项目中缺少 Spring WebFlux 相关依赖 导致的。org.springframework.web.reactive.function 包属于 Spring WebFlux 模块&#xff08;用于响应式 Web 开发&#xff09;&#xff0c;如…