diff --git "a/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/README.md" "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/README.md"
new file mode 100644
index 0000000..c0f9af3
--- /dev/null
+++ "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/README.md"
@@ -0,0 +1,5 @@
+# 说明
+
+数据位置
+
+https://drive.google.com/drive/folders/1AKnaQVwp_DdZ6wl27miQTWwuJAcAPDPv?usp=share_link
\ No newline at end of file
diff --git "a/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__init__.py" "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__init__.py"
new file mode 100644
index 0000000..a8ce586
--- /dev/null
+++ "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__init__.py"
@@ -0,0 +1 @@
+from .core import *
\ No newline at end of file
diff --git "a/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__pycache__/__init__.cpython-38.pyc" "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__pycache__/__init__.cpython-38.pyc"
new file mode 100644
index 0000000..0e8f9d5
Binary files /dev/null and "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__pycache__/__init__.cpython-38.pyc" differ
diff --git "a/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__pycache__/core.cpython-38.pyc" "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__pycache__/core.cpython-38.pyc"
new file mode 100644
index 0000000..62d5abf
Binary files /dev/null and "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/__pycache__/core.cpython-38.pyc" differ
diff --git "a/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/core.py" "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/core.py"
new file mode 100644
index 0000000..f4d1de5
--- /dev/null
+++ "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/scr/core.py"
@@ -0,0 +1,178 @@
+"""
+Author: hugo2046 shen.lan123@gmail.com
+Date: 2023-03-07 15:42:11
+LastEditors: hugo2046 shen.lan123@gmail.com
+LastEditTime: 2023-03-07 15:47:21
+Description:
+"""
+
+from collections import Counter
+from typing import Dict
+
+import numpy as np
+import pandas as pd
+import plotly.graph_objects as go
+
+
+def find_stage_stock(
+ pivot_price: pd.DataFrame,
+ window: int,
+ method: str = "high",
+ offset: int = None,
+) -> pd.DataFrame:
+ """获取近期创新高/新低股票数量
+
+ Args:
+ pivot_price (pd.DataFrame): index-date columns-code values-price
+ window (int): 窗口期
+ method (str, optional): high-创新高/low-创新低. Defaults to "high".
+ offset (int, optional): 是否offset. Defaults to None.
+
+ Returns:
+ pd.DataFrame: index-date columns-code values-True/False
+ """
+ oper: str = {"high": "ge", "low": "le"}[method]
+ method: str = {"high": "max", "low": "min"}[method]
+
+ roll_: pd.DataFrame = pivot_price.rolling(window)
+
+ roll_df: pd.DataFrame = getattr(roll_, method)()
+
+ if offset is not None:
+
+ roll_df: pd.DataFrame = roll_df.shift(offset)
+
+ return getattr(pivot_price, oper)(roll_df)
+
+
+def get_ind_stage_num(pivot_num: pd.DataFrame, sw_cons_dict: Dict) -> pd.DataFrame:
+ """通过个股数量统计行业创新高情况
+
+ Args:
+ pivot_num (pd.DataFrame): 个股创新高数量标记 index-date columns-code values-True/False
+ sw_cons_dict (Dict): 个股所属行业字典 k-code v-industry_code
+
+ Returns:
+ pd.DataFrame: index-date columns-indutsry_code values-num
+ """
+ industry_num: pd.DataFrame = pivot_num.copy()
+ industry_num.columns = industry_num.columns.map(sw_cons_dict)
+
+ return industry_num.groupby(level=0, axis=1).sum()
+
+
+def calc_industry_nhnl(
+ pivot_price: pd.DataFrame,
+ sw_cons_dict: Dict,
+ window: int,
+ classify_num: pd.DataFrame = None,
+ tradition: bool = True,
+) -> pd.DataFrame:
+ """获取行业净新高占比(NHNL)
+
+ Args:
+ pivot_price (pd.DataFrame): 个股价格数据 index-date columns MultiIndex level0 fields have low|high;level1 codes
+ sw_cons_dict (Dict): k-code v-indutsry_name/industry_code
+ window (int): 窗口期
+ tradition:True-传统构建方法;False-研报方式 使用close判断创新高/新低;默认为true
+
+ Returns:
+ pd.DataFrame: index-date columns-industry_code values-per
+ """
+ if classify_num is None:
+ classify_num: pd.Series = pd.Series(Counter(tuple(sw_cons_dict.values())))
+
+ h_field: str = "high"
+ l_field: str = "low"
+ if tradition:
+ h_field, l_field = "close", "close"
+
+ high_num: pd.DataFrame = find_stage_stock(pivot_price[h_field], window, "high", 5)
+ low_num: pd.DataFrame = find_stage_stock(pivot_price[l_field], window, "low", 5)
+
+ ind_high: pd.DataFrame = get_ind_stage_num(high_num, sw_cons_dict)
+ ind_low: pd.DataFrame = get_ind_stage_num(low_num, sw_cons_dict)
+
+ return (ind_high - ind_low).div(classify_num)
+
+
+def plot_nhnl_signal(
+ price: pd.Series,
+ siganl: pd.Series,
+ cons_num: int = None,
+ title: str = "",
+ align: bool = False,
+) -> go.Figure:
+ """画NH-NL图
+ plotly >= 5.13
+ Args:
+ price (pd.Series): 价格数据 index-date values-price
+ siganl (pd.Series): NH-NL信号 index-date values-sigbal
+ cons_num (int): 行业个股上市天数超过一年的个数.Defaults is None
+ title (str, optional): 标题. Defaults to "".
+ align (bool, optional): 是否按照信号对齐价格数据. Defaults to False.
+
+ Returns:
+ go.Figure: 图表
+ """
+ fig = go.Figure()
+
+ THRESHOLD: Dict = {
+ "normal": {"贪婪": 0.3, "乐观": 0.2, "悲观": -0.2, "恐惧": -0.3},
+ "other": {"贪婪": 0.4, "乐观": 0.3, "悲观": -0.3, "恐惧": -0.4},
+ }
+
+ COLOR: Dict = {
+ "贪婪": {"color": "LightSeaGreen"},
+ "乐观": {"color": "LightSeaGreen", "dash": "dashdot"},
+ "悲观": {"color": "Crimson", "dash": "dashdot"},
+ "恐惧": {"color": "Crimson"},
+ }
+
+ if align:
+ siganl, price = siganl.align(price, join="inner")
+
+ price_ax = go.Scatter(
+ x=price.index,
+ y=price.values,
+ line=dict(color="darkgray"),
+ name="close",
+ )
+ nhnl_ax = go.Scatter(
+ x=siganl.index,
+ y=siganl.values,
+ line=dict(color="DarkSalmon"),
+ name="NH-NL",
+ yaxis="y2",
+ )
+
+ fig.add_trace(price_ax)
+ fig.add_trace(nhnl_ax)
+
+ method: str = "normal" if (cons_num > 40 or cons_num is None) else "other"
+ threshold_range: Dict = THRESHOLD[method]
+
+ for name, value in threshold_range.items():
+
+ fig.add_trace(
+ go.Scatter(
+ x=price.index,
+ y=np.ones(len(price)) * value,
+ line=COLOR[name],
+ name=name,
+ yaxis="y2",
+ )
+ )
+
+ fig.update_layout(
+ hovermode="x unified",
+ yaxis2=dict(
+ title="NHNL",
+ overlaying="y",
+ side="right",
+ ),
+ title={"text": title},
+ legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
+ )
+
+ return fig
diff --git "a/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267.ipynb" "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267.ipynb"
new file mode 100644
index 0000000..b1a5e03
--- /dev/null
+++ "b/C-\346\213\251\346\227\266\347\261\273/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267/\350\241\214\344\270\232\346\214\207\346\225\260\351\241\266\351\203\250\345\222\214\345\272\225\351\203\250\344\277\241\345\217\267.ipynb"
@@ -0,0 +1,1570 @@
+{
+ "cells": [
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# 行业指数顶部和底部信号:净新高占比((NH-NL)%)\n",
+ "\n",
+ "## 背景\n",
+ "\n",
+ "**行业涨跌分化增加了行业指数顶部和底部信号的必要性:**\n",
+ "\n",
+ "一方面,近年来A股行业指数同涨同跌的现象减弱,尤其是2020年以来,**行业指数间的分化越来越严重,因此寻找行业指数的顶部和底部信号显得尤为重要**。28个中信一级行业估值分位数的波动率验证了行情的分化。另一方面,各行业指数ETF、主题基金的兴起和壮大,增加了对行业指数顶部和底部判断的需求。\n",
+ "\n",
+ "**行业指数顶部和底部信号的构建及简单反转策略:**\n",
+ "我们通过构建净新高占比((NH-NL)%)指标来刻画行业指数的情绪,这延 续了我们对价格新高和价格新低的重视,与我们衡量宽基指数的情绪指标 (NHNL)一脉相承,**其核心逻辑仍基于行为金融学的锚定效应**。在净新高占比((NH-NL)%)信号的基础上,我们构建了一个简单的反转策略,包括买入、卖出、仓位、止损及移动等要素。\n",
+ "\n",
+ "**净新高占比能较好地提示科技板块行业指数的顶部和底部:**\n",
+ "\n",
+ "通过对科技板块的电子、通信、计算机和传媒行业的逐一复盘,从准确率 和简单反转策略盈利性等角度进行分析,我们发现净新高占比((NH-NL)%) 指标能较好地提示行业指数的顶部和顶部;简单反转策略有效,且2020年 以来策略在科技板块的表现较好。考虑到反转策略资金占用时间较少,因此比较适合作为指数增强型策略。\n",
+ "\n",
+ "\n",
+ "近年来,A 股行业指数同涨同跌的现象减弱,尤其是 2020 年行业指数间分化更 加明显;同时,伴随各行业指数 ETF、主题基金的兴起和壮大,增加了对行业指数顶部和底部判断的需求。因此,我们尝试寻找提示行业指数顶部和底部的信号。我们通过构建净新高占比指标(简称“(NH-NL)%”),来寻找行业指数(中信一 级行业指数)的顶部和底部。通过回溯检验发现,净新高占比((NH-NL)%)在科技 板块和周期板块表现较好。本篇报告并以科技板块为例,复盘了净新高占比((NH-NL)%)提示科技板块行业指数的准确率及简单反转策略的有效性。"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "from typing import Dict, List\n",
+ "from tqdm.notebook import tqdm\n",
+ "from scr import calc_industry_nhnl,plot_nhnl_signal"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 构建逻辑\n",
+ "\n",
+ "净新高占比指标((NH-NL)%)即行业指数中创年度新高与年度新低之差的个股 数占全行业个股数的百分比,其逻辑自洽性来源包括以下四个方面:\n",
+ "\n",
+ "- 锚定效应与新高新低。行为金融学告诉我们,绝大多数投资者都有很强的锚 定效应,他们都清楚地记得所持有个股/基金的成本价(即“锚定成本”), 甚至他们的很多决定都是视他们处于浮盈还是浮亏状态而定。创年度新高的 个股,其股票持有者均为浮盈状态,因此即使其计划卖出,也愿意等行情再 上涨一段时间,因此其抛压相对较小;而创年度新低的个股,因其股票持有者均为浮亏状态,因此只要行情反弹便有投资者卖出,抛压反而较大。\n",
+ " \n",
+ "- 新高新低是个股走强走弱最直接的刻画。创新高/新低是个股走强/走弱最直 接的刻画,10 倍股都是从 1 倍股开始涨的,优秀的个股能不断创出新高;另一方面,个股跌到 2 折前都是先腰斩,而最开始的表现则是创年度新低。\n",
+ " \n",
+ "- 新高新低差代表行业内个股整体强弱,亦即代表行业指数的强弱。如果一 个行业指数中创年度新高多于创年度新低的个股数,即表示其中更多个股正在走强,反之亦然。\n",
+ " \n",
+ "- 净新高占比((NH-NL)%)能较好地刻画行业指数强弱及市场情绪。净新高占比通过归一化(指标值在【-1,1】之间),能有效去除行业规模的影响(机 械行业目前有接近 500 个公司上市超过 1 年,煤炭行业上市超过 1 年的上\n",
+ "市公司仅 36 个),而且能进行横向比较,去除行业的特殊性。\n",
+ "\n",
+ "## 信号构建方法\n",
+ "\n",
+ "我们通过构建指标净新高占比(Net Percent of New High Minus New Low,简 称“(NH-NL)%”,亦简称“NPNMN”)来衡量中信一级行业指数的强弱:\n",
+ "\n",
+ "$$净新高占比(NH-NL)\\%=\\frac{创年度新高的个股数-创年度新低的个股数}{行业内部上市超过1年的个股数}$$\n",
+ "\n",
+ "其中,\"创年度新高/新低\"指*收盘价大于/小于过去52周至一周前的区间最高/最低收盘价*\n",
+ "\n",
+ "这里有两个注意:\n",
+ "1. 传统使用high>Max(high)表示最高(最低同),而这里用的close>Max(close);\n",
+ "2. 识别前期高点的时间是$T_{1-52}$而非$T_{0-51}$\n",
+ "\n",
+ "## (NH-NL)%指标的阈值选择\n",
+ "\n",
+ "我们用20%和30%作为中信一级行业指数**乐观**和**贪婪**的阈值,用-20%和-30% 作为**悲观**和**恐惧**的阈值。\n",
+ "\n",
+ "$$NHNL = \\begin{cases} \n",
+ "x \\geq 30\\% \\ 贪婪\\\\\\\n",
+ "20\\% \\leq x \\lt 30\\% \\ 乐观\\\\\\\n",
+ "-20\\% \\lt x \\lt 20\\% \\ 正常区间\\\\\\\n",
+ "-30\\% \\lt x \\leq -20\\% \\ 悲观\\\\\\\n",
+ "x \\leq -30\\% \\ 恐惧\n",
+ "\\end{cases}$$\n",
+ "\n",
+ "为了防止一级行业指数个股数太少引发的跳跃,当一级行业指数上市超过 1 年的个股数小于 40 时,将阈值放宽为±30%/40%:\n",
+ "\n",
+ "$$NHNL = \\begin{cases} \n",
+ "x \\geq 40\\% \\ 贪婪\\\\\\\n",
+ "30\\% \\leq x \\lt 40\\% \\ 乐观\\\\\\\n",
+ "-30\\% \\lt x \\lt 30\\% \\ 正常区间\\\\\\\n",
+ "-40\\% \\lt x \\leq -30\\% \\ 悲观\\\\\\\n",
+ "x \\leq -40\\ \\ 恐惧%\n",
+ "\\end{cases}$$\n",
+ "\n",
+ "## 跟踪方法\n",
+ "\n",
+ "我们构建一个基于净新高占比指标((NH-NL)%)简单的反转策略:当净新高占比指标提示贪婪后开始关注,第一天回到阈值内视为做空信号,下一个交易日开盘做空,止损点为前一周(5 个交易日)区间最高点,否则持有30天后以收盘价平仓,入场一周后若未止损则将止损位移至成本价。\n",
+ "\n",
+ "当净新高占比指标提示恐慌后开始关注,第一天回到阈值内视为做多信号,下一个交易日开盘做多,止损点为前一周区间最低点,否则持有 30 天后以收盘价平仓,入场一周后若未止损则将止损位移至成本价。"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 数据获取\n",
+ "\n",
+ "**此部分可以跳过直接读取data文件中的数据构建信号**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 68,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "import sys\n",
+ "from pathlib import Path\n",
+ "\n",
+ "sys.path.append(str(Path().resolve().parents[0]))\n",
+ "\n",
+ "from knight_scr.scr.sql_service import (\n",
+ " get_ts_price,\n",
+ " get_ind_classify,\n",
+ " get_ind_concept_cons,\n",
+ " get_ind_price,\n",
+ " get_ts_stock_basic,\n",
+ " get_trade_days,\n",
+ ")\n",
+ "\n",
+ "def get_ind_overthreshold_num(\n",
+ " sw_cons_name: Dict, start_dt: str, end_dt: str, limit: int\n",
+ ") -> pd.DataFrame:\n",
+ " \"\"\"交易日至ipodate的天数(自然日)\n",
+ "\n",
+ " Args:\n",
+ " sw_cons_name (Dict): k-codes v-industry_name\n",
+ " start_dt (str): 起始日期\n",
+ " end_dt (str): 结束日期\n",
+ " limit (int): 阈值\n",
+ "\n",
+ " Returns:\n",
+ " pd.DataFrame: index-date columns-code values-days\n",
+ " \"\"\"\n",
+ " # 获取股票基础数据\n",
+ " stock_basic: pd.DataFrame = get_ts_stock_basic()\n",
+ " codes: List = list(sw_cons_name.keys())\n",
+ "\n",
+ " cond: pd.DataFrame = stock_basic[\"code\"].isin(codes)\n",
+ " stock_basic: pd.DataFrame = stock_basic[cond]\n",
+ " # 获取交易日期\n",
+ " periods: np.ndarray = get_trade_days(start_dt, end_dt)\n",
+ "\n",
+ " stock_ipo_list: pd.Series = stock_basic.set_index(\"code\")[\"list_date\"]\n",
+ " stock_ipo_list: pd.Series = stock_ipo_list.astype(np.datetime64)\n",
+ "\n",
+ " data: np.ndarray = np.broadcast_to(periods, (len(codes), len(periods))).T\n",
+ " ipo_date: pd.DataFrame = (\n",
+ " pd.DataFrame(data=data, index=periods, columns=codes)\n",
+ " .sub(stock_ipo_list)\n",
+ " .applymap(lambda x: x.days)\n",
+ " )\n",
+ "\n",
+ " ipo_date.columns = ipo_date.columns.map(sw_cons_name)\n",
+ "\n",
+ " return ipo_date.apply(lambda x: x > limit).groupby(level=0, axis=1).sum()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "watch_date = \"2023-03-03\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sw_classify: pd.DataFrame = get_ind_classify(watch_date, \"sw_level1\")\n",
+ "sw_cons: pd.DataFrame = get_ind_concept_cons(watch_date, \"sw_level1\")\n",
+ "\n",
+ "# k-code v-industry_code\n",
+ "sw_cons_dict: Dict = sw_cons.set_index(\"code\")[\"industry_code\"].to_dict()\n",
+ "# k-industry_code v-industry_name\n",
+ "classify_dict: Dict = sw_classify.set_index(\"code\")[\"sec_name\"].to_dict()\n",
+ "# k-code v-industry_code\n",
+ "sw_cons_name: Dict = {k: classify_dict[v] for k, v in sw_cons_dict.items()}\n",
+ "# name-cons_num\n",
+ "# classify_num: pd.Series = pd.Series(Counter(sw_cons_name.values()))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 70,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " code | \n",
+ " trade_date | \n",
+ " sec_name | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 801010.SI | \n",
+ " 2023-03-03 | \n",
+ " 农林牧渔 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 801030.SI | \n",
+ " 2023-03-03 | \n",
+ " 基础化工 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 801040.SI | \n",
+ " 2023-03-03 | \n",
+ " 钢铁 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 801050.SI | \n",
+ " 2023-03-03 | \n",
+ " 有色金属 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 801080.SI | \n",
+ " 2023-03-03 | \n",
+ " 电子 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " code trade_date sec_name\n",
+ "0 801010.SI 2023-03-03 农林牧渔\n",
+ "1 801030.SI 2023-03-03 基础化工\n",
+ "2 801040.SI 2023-03-03 钢铁\n",
+ "3 801050.SI 2023-03-03 有色金属\n",
+ "4 801080.SI 2023-03-03 电子"
+ ]
+ },
+ "execution_count": 70,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sw_classify.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 71,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " code | \n",
+ " trade_date | \n",
+ " sec_name | \n",
+ " industry_code | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 000019.SZ | \n",
+ " 2023-03-03 | \n",
+ " 深粮控股 | \n",
+ " 801010.SI | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 000505.SZ | \n",
+ " 2023-03-03 | \n",
+ " 京粮控股 | \n",
+ " 801010.SI | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 000592.SZ | \n",
+ " 2023-03-03 | \n",
+ " 平潭发展 | \n",
+ " 801010.SI | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 000639.SZ | \n",
+ " 2023-03-03 | \n",
+ " 西王食品 | \n",
+ " 801010.SI | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 000663.SZ | \n",
+ " 2023-03-03 | \n",
+ " 永安林业 | \n",
+ " 801010.SI | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " code trade_date sec_name industry_code\n",
+ "0 000019.SZ 2023-03-03 深粮控股 801010.SI\n",
+ "1 000505.SZ 2023-03-03 京粮控股 801010.SI\n",
+ "2 000592.SZ 2023-03-03 平潭发展 801010.SI\n",
+ "3 000639.SZ 2023-03-03 西王食品 801010.SI\n",
+ "4 000663.SZ 2023-03-03 永安林业 801010.SI"
+ ]
+ },
+ "execution_count": 71,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sw_cons.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ind_price: pd.DataFrame = get_ind_price(\n",
+ " list(classify_dict.keys()),\n",
+ " start_date=\"2014-01-01\",\n",
+ " end_date=\"2023-03-03\",\n",
+ " fields=[\"close\"],\n",
+ " level=\"sw_level1\",\n",
+ ")\n",
+ "ind_price[\"name\"] = ind_price[\"code\"].map(classify_dict)\n",
+ "pivot_ind_price: pd.DataFrame = pd.pivot_table(\n",
+ " ind_price, index=\"trade_date\", columns=\"name\", values=\"close\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 72,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " code | \n",
+ " close | \n",
+ " trade_date | \n",
+ " name | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 801010.SI | \n",
+ " 3265.37 | \n",
+ " 2022-11-16 | \n",
+ " 农林牧渔 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 801030.SI | \n",
+ " 4242.14 | \n",
+ " 2022-11-16 | \n",
+ " 基础化工 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 801040.SI | \n",
+ " 2350.87 | \n",
+ " 2022-11-16 | \n",
+ " 钢铁 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 801050.SI | \n",
+ " 5028.19 | \n",
+ " 2022-11-16 | \n",
+ " 有色金属 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 801080.SI | \n",
+ " 3808.33 | \n",
+ " 2022-11-16 | \n",
+ " 电子 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " code close trade_date name\n",
+ "0 801010.SI 3265.37 2022-11-16 农林牧渔\n",
+ "1 801030.SI 4242.14 2022-11-16 基础化工\n",
+ "2 801040.SI 2350.87 2022-11-16 钢铁\n",
+ "3 801050.SI 5028.19 2022-11-16 有色金属\n",
+ "4 801080.SI 3808.33 2022-11-16 电子"
+ ]
+ },
+ "execution_count": 72,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ind_price.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 74,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "d13a966d2f6d4ba39c2d30ad20af16bf",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "数据查询: 0%| | 0/11 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# 获取2013至2023申万一级行的数据\n",
+ "codes: List = sw_cons[\"code\"].unique().tolist()\n",
+ "begin_periods = pd.date_range(\"2013-01-01\", watch_date, freq=\"YS\")\n",
+ "end_periods = (\n",
+ " pd.date_range(\"2013-01-01\", watch_date, freq=\"Y\")\n",
+ " .append(pd.to_datetime([watch_date]))\n",
+ " .unique()\n",
+ ")\n",
+ "\n",
+ "dfs: List = [\n",
+ " get_ts_price(\n",
+ " codes,\n",
+ " start_date=start.strftime(\"%Y-%m-%d\"),\n",
+ " end_date=end.strftime(\"%Y-%m-%d\"),\n",
+ " fields=[\"high\", \"low\"],\n",
+ " fq=\"post\",\n",
+ " )\n",
+ " for start, end in tqdm(\n",
+ " zip(begin_periods, end_periods), total=len(begin_periods), desc=\"数据查询\"\n",
+ " )\n",
+ "]\n",
+ "\n",
+ "price: pd.DataFrame = pd.concat(dfs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 76,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " trade_date | \n",
+ " code | \n",
+ " high | \n",
+ " low | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 2013-01-04 | \n",
+ " 600839.SH | \n",
+ " 56.35894 | \n",
+ " 55.28030 | \n",
+ "
\n",
+ " \n",
+ " 1532 | \n",
+ " 2013-01-04 | \n",
+ " 300271.SZ | \n",
+ " 24.45246 | \n",
+ " 23.45694 | \n",
+ "
\n",
+ " \n",
+ " 1533 | \n",
+ " 2013-01-04 | \n",
+ " 002678.SZ | \n",
+ " 11.80000 | \n",
+ " 11.50000 | \n",
+ "
\n",
+ " \n",
+ " 1534 | \n",
+ " 2013-01-04 | \n",
+ " 002394.SZ | \n",
+ " 24.86005 | \n",
+ " 24.03910 | \n",
+ "
\n",
+ " \n",
+ " 1535 | \n",
+ " 2013-01-04 | \n",
+ " 300323.SZ | \n",
+ " 11.83000 | \n",
+ " 11.28000 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " trade_date code high low\n",
+ "0 2013-01-04 600839.SH 56.35894 55.28030\n",
+ "1532 2013-01-04 300271.SZ 24.45246 23.45694\n",
+ "1533 2013-01-04 002678.SZ 11.80000 11.50000\n",
+ "1534 2013-01-04 002394.SZ 24.86005 24.03910\n",
+ "1535 2013-01-04 300323.SZ 11.83000 11.28000"
+ ]
+ },
+ "execution_count": 76,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "price.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pivot_table: pd.DataFrame = pd.pivot_table(price,\n",
+ " index=\"trade_date\",\n",
+ " columns=\"code\",\n",
+ " values=[\"low\", \"high\"])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "start_dt = pivot_table.index.min()\n",
+ "end_dt = pivot_table.index.max()\n",
+ "\n",
+ "classify_num: pd.DataFrame = get_ind_overthreshold_num(\n",
+ " sw_cons_name, start_dt, end_dt, 252\n",
+ ")"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 信号构建\n",
+ "\n",
+ "这里直接构建已有数据构建"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "\n",
+ "with open('data/sw_cons_name.json','r') as f:\n",
+ " \n",
+ " sw_cons_name:Dict = json.load(f)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "price: pd.DataFrame = pd.read_csv(\"data/data.csv\", index_col=[0], parse_dates=[0])\n",
+ "\n",
+ "pivot_table: pd.DataFrame = pd.pivot_table(\n",
+ " price, index=\"trade_date\", columns=\"code\", values=[\"low\", \"high\"]\n",
+ ")\n",
+ "\n",
+ "ind_price: pd.DataFrame = pd.read_csv(\n",
+ " \"data/industry_price.csv\", index_col=[0], parse_dates=[0]\n",
+ ")\n",
+ "\n",
+ "pivot_ind_price:pd.DataFrame = pd.pivot_table(\n",
+ " ind_price, index=\"trade_date\", columns=\"name\", values='close'\n",
+ ")\n",
+ "classify_num: pd.DataFrame = pd.read_csv(\n",
+ " \"data/industry_classify_num.csv\", index_col=[0], parse_dates=[0]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nhnl_df: pd.DataFrame = calc_industry_nhnl(\n",
+ " pivot_table, sw_cons_name, 52 * 5, classify_num,tradition=False\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " name | \n",
+ " 交通运输 | \n",
+ " 传媒 | \n",
+ " 公用事业 | \n",
+ " 农林牧渔 | \n",
+ " 医药生物 | \n",
+ " 商贸零售 | \n",
+ " 国防军工 | \n",
+ " 基础化工 | \n",
+ " 家用电器 | \n",
+ " 建筑材料 | \n",
+ " ... | \n",
+ " 纺织服饰 | \n",
+ " 综合 | \n",
+ " 美容护理 | \n",
+ " 计算机 | \n",
+ " 轻工制造 | \n",
+ " 通信 | \n",
+ " 钢铁 | \n",
+ " 银行 | \n",
+ " 非银金融 | \n",
+ " 食品饮料 | \n",
+ "
\n",
+ " \n",
+ " trade_date | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 2014-01-02 | \n",
+ " 1615.66 | \n",
+ " 869.63 | \n",
+ " 1830.18 | \n",
+ " 1910.49 | \n",
+ " 5051.73 | \n",
+ " 3068.11 | \n",
+ " 967.03 | \n",
+ " 1820.03 | \n",
+ " 2949.75 | \n",
+ " 3110.23 | \n",
+ " ... | \n",
+ " 1654.62 | \n",
+ " 1633.07 | \n",
+ " 4451.86 | \n",
+ " 2442.39 | \n",
+ " 1641.97 | \n",
+ " 1446.49 | \n",
+ " 1561.16 | \n",
+ " 2085.20 | \n",
+ " 1061.48 | \n",
+ " 4658.96 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-03 | \n",
+ " 1600.54 | \n",
+ " 883.52 | \n",
+ " 1814.65 | \n",
+ " 1896.49 | \n",
+ " 5028.63 | \n",
+ " 3047.10 | \n",
+ " 952.46 | \n",
+ " 1803.59 | \n",
+ " 2881.53 | \n",
+ " 3041.16 | \n",
+ " ... | \n",
+ " 1633.76 | \n",
+ " 1608.18 | \n",
+ " 4436.66 | \n",
+ " 2468.34 | \n",
+ " 1638.41 | \n",
+ " 1445.33 | \n",
+ " 1562.54 | \n",
+ " 2051.37 | \n",
+ " 1034.81 | \n",
+ " 4615.06 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-06 | \n",
+ " 1547.14 | \n",
+ " 864.40 | \n",
+ " 1771.89 | \n",
+ " 1818.07 | \n",
+ " 4919.26 | \n",
+ " 2953.29 | \n",
+ " 914.79 | \n",
+ " 1752.00 | \n",
+ " 2807.65 | \n",
+ " 2945.86 | \n",
+ " ... | \n",
+ " 1581.04 | \n",
+ " 1562.43 | \n",
+ " 4320.38 | \n",
+ " 2402.11 | \n",
+ " 1605.00 | \n",
+ " 1403.29 | \n",
+ " 1517.68 | \n",
+ " 2028.91 | \n",
+ " 1028.31 | \n",
+ " 4500.21 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-07 | \n",
+ " 1549.88 | \n",
+ " 877.56 | \n",
+ " 1777.65 | \n",
+ " 1818.74 | \n",
+ " 4970.16 | \n",
+ " 2966.80 | \n",
+ " 920.69 | \n",
+ " 1759.83 | \n",
+ " 2813.32 | \n",
+ " 2943.22 | \n",
+ " ... | \n",
+ " 1587.11 | \n",
+ " 1569.97 | \n",
+ " 4364.41 | \n",
+ " 2418.80 | \n",
+ " 1611.90 | \n",
+ " 1410.63 | \n",
+ " 1508.78 | \n",
+ " 2022.18 | \n",
+ " 1022.42 | \n",
+ " 4521.77 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-08 | \n",
+ " 1538.35 | \n",
+ " 914.00 | \n",
+ " 1783.92 | \n",
+ " 1818.81 | \n",
+ " 5016.00 | \n",
+ " 2961.86 | \n",
+ " 934.77 | \n",
+ " 1755.68 | \n",
+ " 2830.83 | \n",
+ " 2939.19 | \n",
+ " ... | \n",
+ " 1576.37 | \n",
+ " 1564.09 | \n",
+ " 4294.82 | \n",
+ " 2466.13 | \n",
+ " 1624.17 | \n",
+ " 1427.98 | \n",
+ " 1493.70 | \n",
+ " 2032.83 | \n",
+ " 1030.18 | \n",
+ " 4552.21 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 2023-02-27 | \n",
+ " 2386.26 | \n",
+ " 583.41 | \n",
+ " 2250.09 | \n",
+ " 3404.76 | \n",
+ " 9416.41 | \n",
+ " 2744.15 | \n",
+ " 1588.84 | \n",
+ " 4473.79 | \n",
+ " 7041.16 | \n",
+ " 6537.20 | \n",
+ " ... | \n",
+ " 1695.06 | \n",
+ " 2997.43 | \n",
+ " 7324.37 | \n",
+ " 4516.41 | \n",
+ " 2586.31 | \n",
+ " 2132.33 | \n",
+ " 2554.97 | \n",
+ " 3127.16 | \n",
+ " 1547.29 | \n",
+ " 24368.50 | \n",
+ "
\n",
+ " \n",
+ " 2023-02-28 | \n",
+ " 2400.09 | \n",
+ " 590.74 | \n",
+ " 2271.14 | \n",
+ " 3422.68 | \n",
+ " 9577.38 | \n",
+ " 2761.72 | \n",
+ " 1593.42 | \n",
+ " 4491.05 | \n",
+ " 7045.12 | \n",
+ " 6576.73 | \n",
+ " ... | \n",
+ " 1725.23 | \n",
+ " 3020.47 | \n",
+ " 7378.86 | \n",
+ " 4617.62 | \n",
+ " 2605.86 | \n",
+ " 2180.57 | \n",
+ " 2563.84 | \n",
+ " 3139.45 | \n",
+ " 1562.79 | \n",
+ " 24394.10 | \n",
+ "
\n",
+ " \n",
+ " 2023-03-01 | \n",
+ " 2424.65 | \n",
+ " 611.74 | \n",
+ " 2283.59 | \n",
+ " 3427.02 | \n",
+ " 9572.93 | \n",
+ " 2762.03 | \n",
+ " 1601.77 | \n",
+ " 4499.70 | \n",
+ " 7169.86 | \n",
+ " 6705.74 | \n",
+ " ... | \n",
+ " 1724.57 | \n",
+ " 3027.17 | \n",
+ " 7356.28 | \n",
+ " 4800.49 | \n",
+ " 2625.23 | \n",
+ " 2264.47 | \n",
+ " 2574.99 | \n",
+ " 3178.12 | \n",
+ " 1592.56 | \n",
+ " 24651.70 | \n",
+ "
\n",
+ " \n",
+ " 2023-03-02 | \n",
+ " 2436.05 | \n",
+ " 623.22 | \n",
+ " 2282.97 | \n",
+ " 3404.21 | \n",
+ " 9469.68 | \n",
+ " 2746.05 | \n",
+ " 1604.84 | \n",
+ " 4492.88 | \n",
+ " 7141.95 | \n",
+ " 6760.43 | \n",
+ " ... | \n",
+ " 1728.87 | \n",
+ " 3014.66 | \n",
+ " 7351.53 | \n",
+ " 4825.39 | \n",
+ " 2627.05 | \n",
+ " 2287.31 | \n",
+ " 2586.22 | \n",
+ " 3187.21 | \n",
+ " 1591.15 | \n",
+ " 24573.10 | \n",
+ "
\n",
+ " \n",
+ " 2023-03-03 | \n",
+ " 2451.72 | \n",
+ " 620.29 | \n",
+ " 2302.85 | \n",
+ " 3404.76 | \n",
+ " 9473.96 | \n",
+ " 2763.93 | \n",
+ " 1629.94 | \n",
+ " 4476.90 | \n",
+ " 7165.70 | \n",
+ " 6755.17 | \n",
+ " ... | \n",
+ " 1717.34 | \n",
+ " 3040.54 | \n",
+ " 7315.95 | \n",
+ " 4774.17 | \n",
+ " 2599.05 | \n",
+ " 2272.00 | \n",
+ " 2600.95 | \n",
+ " 3212.64 | \n",
+ " 1600.36 | \n",
+ " 24429.90 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
2231 rows × 31 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ "name 交通运输 传媒 公用事业 农林牧渔 医药生物 商贸零售 国防军工 \\\n",
+ "trade_date \n",
+ "2014-01-02 1615.66 869.63 1830.18 1910.49 5051.73 3068.11 967.03 \n",
+ "2014-01-03 1600.54 883.52 1814.65 1896.49 5028.63 3047.10 952.46 \n",
+ "2014-01-06 1547.14 864.40 1771.89 1818.07 4919.26 2953.29 914.79 \n",
+ "2014-01-07 1549.88 877.56 1777.65 1818.74 4970.16 2966.80 920.69 \n",
+ "2014-01-08 1538.35 914.00 1783.92 1818.81 5016.00 2961.86 934.77 \n",
+ "... ... ... ... ... ... ... ... \n",
+ "2023-02-27 2386.26 583.41 2250.09 3404.76 9416.41 2744.15 1588.84 \n",
+ "2023-02-28 2400.09 590.74 2271.14 3422.68 9577.38 2761.72 1593.42 \n",
+ "2023-03-01 2424.65 611.74 2283.59 3427.02 9572.93 2762.03 1601.77 \n",
+ "2023-03-02 2436.05 623.22 2282.97 3404.21 9469.68 2746.05 1604.84 \n",
+ "2023-03-03 2451.72 620.29 2302.85 3404.76 9473.96 2763.93 1629.94 \n",
+ "\n",
+ "name 基础化工 家用电器 建筑材料 ... 纺织服饰 综合 美容护理 \\\n",
+ "trade_date ... \n",
+ "2014-01-02 1820.03 2949.75 3110.23 ... 1654.62 1633.07 4451.86 \n",
+ "2014-01-03 1803.59 2881.53 3041.16 ... 1633.76 1608.18 4436.66 \n",
+ "2014-01-06 1752.00 2807.65 2945.86 ... 1581.04 1562.43 4320.38 \n",
+ "2014-01-07 1759.83 2813.32 2943.22 ... 1587.11 1569.97 4364.41 \n",
+ "2014-01-08 1755.68 2830.83 2939.19 ... 1576.37 1564.09 4294.82 \n",
+ "... ... ... ... ... ... ... ... \n",
+ "2023-02-27 4473.79 7041.16 6537.20 ... 1695.06 2997.43 7324.37 \n",
+ "2023-02-28 4491.05 7045.12 6576.73 ... 1725.23 3020.47 7378.86 \n",
+ "2023-03-01 4499.70 7169.86 6705.74 ... 1724.57 3027.17 7356.28 \n",
+ "2023-03-02 4492.88 7141.95 6760.43 ... 1728.87 3014.66 7351.53 \n",
+ "2023-03-03 4476.90 7165.70 6755.17 ... 1717.34 3040.54 7315.95 \n",
+ "\n",
+ "name 计算机 轻工制造 通信 钢铁 银行 非银金融 食品饮料 \n",
+ "trade_date \n",
+ "2014-01-02 2442.39 1641.97 1446.49 1561.16 2085.20 1061.48 4658.96 \n",
+ "2014-01-03 2468.34 1638.41 1445.33 1562.54 2051.37 1034.81 4615.06 \n",
+ "2014-01-06 2402.11 1605.00 1403.29 1517.68 2028.91 1028.31 4500.21 \n",
+ "2014-01-07 2418.80 1611.90 1410.63 1508.78 2022.18 1022.42 4521.77 \n",
+ "2014-01-08 2466.13 1624.17 1427.98 1493.70 2032.83 1030.18 4552.21 \n",
+ "... ... ... ... ... ... ... ... \n",
+ "2023-02-27 4516.41 2586.31 2132.33 2554.97 3127.16 1547.29 24368.50 \n",
+ "2023-02-28 4617.62 2605.86 2180.57 2563.84 3139.45 1562.79 24394.10 \n",
+ "2023-03-01 4800.49 2625.23 2264.47 2574.99 3178.12 1592.56 24651.70 \n",
+ "2023-03-02 4825.39 2627.05 2287.31 2586.22 3187.21 1591.15 24573.10 \n",
+ "2023-03-03 4774.17 2599.05 2272.00 2600.95 3212.64 1600.36 24429.90 \n",
+ "\n",
+ "[2231 rows x 31 columns]"
+ ]
+ },
+ "execution_count": 24,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pivot_ind_price"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "KeyError",
+ "evalue": "'电子'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)",
+ "File \u001b[1;32md:\\anaconda3\\lib\\site-packages\\pandas\\core\\indexes\\base.py:3803\u001b[0m, in \u001b[0;36mIndex.get_loc\u001b[1;34m(self, key, method, tolerance)\u001b[0m\n\u001b[0;32m 3802\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[1;32m-> 3803\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_engine\u001b[39m.\u001b[39;49mget_loc(casted_key)\n\u001b[0;32m 3804\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mKeyError\u001b[39;00m \u001b[39mas\u001b[39;00m err:\n",
+ "File \u001b[1;32md:\\anaconda3\\lib\\site-packages\\pandas\\_libs\\index.pyx:138\u001b[0m, in \u001b[0;36mpandas._libs.index.IndexEngine.get_loc\u001b[1;34m()\u001b[0m\n",
+ "File \u001b[1;32md:\\anaconda3\\lib\\site-packages\\pandas\\_libs\\index.pyx:165\u001b[0m, in \u001b[0;36mpandas._libs.index.IndexEngine.get_loc\u001b[1;34m()\u001b[0m\n",
+ "File \u001b[1;32mpandas\\_libs\\hashtable_class_helper.pxi:5745\u001b[0m, in \u001b[0;36mpandas._libs.hashtable.PyObjectHashTable.get_item\u001b[1;34m()\u001b[0m\n",
+ "File \u001b[1;32mpandas\\_libs\\hashtable_class_helper.pxi:5753\u001b[0m, in \u001b[0;36mpandas._libs.hashtable.PyObjectHashTable.get_item\u001b[1;34m()\u001b[0m\n",
+ "\u001b[1;31mKeyError\u001b[0m: '电子'",
+ "\nThe above exception was the direct cause of the following exception:\n",
+ "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[1;32mIn[18], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m plot_nhnl_signal(pivot_ind_price[\u001b[39m\"\u001b[39;49m\u001b[39m电子\u001b[39;49m\u001b[39m\"\u001b[39;49m], nhnl_df[\u001b[39m\"\u001b[39m\u001b[39m电子\u001b[39m\u001b[39m\"\u001b[39m], \u001b[39m40\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39m电子行业净新高占比\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mTrue\u001b[39;00m)\n",
+ "File \u001b[1;32md:\\anaconda3\\lib\\site-packages\\pandas\\core\\frame.py:3805\u001b[0m, in \u001b[0;36mDataFrame.__getitem__\u001b[1;34m(self, key)\u001b[0m\n\u001b[0;32m 3803\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mcolumns\u001b[39m.\u001b[39mnlevels \u001b[39m>\u001b[39m \u001b[39m1\u001b[39m:\n\u001b[0;32m 3804\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_getitem_multilevel(key)\n\u001b[1;32m-> 3805\u001b[0m indexer \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mcolumns\u001b[39m.\u001b[39;49mget_loc(key)\n\u001b[0;32m 3806\u001b[0m \u001b[39mif\u001b[39;00m is_integer(indexer):\n\u001b[0;32m 3807\u001b[0m indexer \u001b[39m=\u001b[39m [indexer]\n",
+ "File \u001b[1;32md:\\anaconda3\\lib\\site-packages\\pandas\\core\\indexes\\base.py:3805\u001b[0m, in \u001b[0;36mIndex.get_loc\u001b[1;34m(self, key, method, tolerance)\u001b[0m\n\u001b[0;32m 3803\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_engine\u001b[39m.\u001b[39mget_loc(casted_key)\n\u001b[0;32m 3804\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mKeyError\u001b[39;00m \u001b[39mas\u001b[39;00m err:\n\u001b[1;32m-> 3805\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mKeyError\u001b[39;00m(key) \u001b[39mfrom\u001b[39;00m \u001b[39merr\u001b[39;00m\n\u001b[0;32m 3806\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mTypeError\u001b[39;00m:\n\u001b[0;32m 3807\u001b[0m \u001b[39m# If we have a listlike key, _check_indexing_error will raise\u001b[39;00m\n\u001b[0;32m 3808\u001b[0m \u001b[39m# InvalidIndexError. Otherwise we fall through and re-raise\u001b[39;00m\n\u001b[0;32m 3809\u001b[0m \u001b[39m# the TypeError.\u001b[39;00m\n\u001b[0;32m 3810\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_check_indexing_error(key)\n",
+ "\u001b[1;31mKeyError\u001b[0m: '电子'"
+ ]
+ }
+ ],
+ "source": [
+ "plot_nhnl_signal(pivot_ind_price[\"电子\"], nhnl_df[\"电子\"], 40, \"电子行业净新高占比\", True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " code | \n",
+ " 801010.SI | \n",
+ " 801030.SI | \n",
+ " 801040.SI | \n",
+ " 801050.SI | \n",
+ " 801080.SI | \n",
+ " 801110.SI | \n",
+ " 801120.SI | \n",
+ " 801130.SI | \n",
+ " 801140.SI | \n",
+ " 801150.SI | \n",
+ " ... | \n",
+ " 801760.SI | \n",
+ " 801770.SI | \n",
+ " 801780.SI | \n",
+ " 801790.SI | \n",
+ " 801880.SI | \n",
+ " 801890.SI | \n",
+ " 801950.SI | \n",
+ " 801960.SI | \n",
+ " 801970.SI | \n",
+ " 801980.SI | \n",
+ "
\n",
+ " \n",
+ " trade_date | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 2014-01-02 | \n",
+ " 1910.49 | \n",
+ " 1820.03 | \n",
+ " 1561.16 | \n",
+ " 2395.99 | \n",
+ " 1777.25 | \n",
+ " 2949.75 | \n",
+ " 4658.96 | \n",
+ " 1654.62 | \n",
+ " 1641.97 | \n",
+ " 5051.73 | \n",
+ " ... | \n",
+ " 869.63 | \n",
+ " 1446.49 | \n",
+ " 2085.20 | \n",
+ " 1061.48 | \n",
+ " 2842.70 | \n",
+ " 945.51 | \n",
+ " 1653.59 | \n",
+ " 1921.99 | \n",
+ " 2328.37 | \n",
+ " 4451.86 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-03 | \n",
+ " 1896.49 | \n",
+ " 1803.59 | \n",
+ " 1562.54 | \n",
+ " 2396.36 | \n",
+ " 1787.51 | \n",
+ " 2881.53 | \n",
+ " 4615.06 | \n",
+ " 1633.76 | \n",
+ " 1638.41 | \n",
+ " 5028.63 | \n",
+ " ... | \n",
+ " 883.52 | \n",
+ " 1445.33 | \n",
+ " 2051.37 | \n",
+ " 1034.81 | \n",
+ " 2804.03 | \n",
+ " 941.09 | \n",
+ " 1628.32 | \n",
+ " 1909.65 | \n",
+ " 2320.01 | \n",
+ " 4436.66 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-06 | \n",
+ " 1818.07 | \n",
+ " 1752.00 | \n",
+ " 1517.68 | \n",
+ " 2344.21 | \n",
+ " 1748.58 | \n",
+ " 2807.65 | \n",
+ " 4500.21 | \n",
+ " 1581.04 | \n",
+ " 1605.00 | \n",
+ " 4919.26 | \n",
+ " ... | \n",
+ " 864.40 | \n",
+ " 1403.29 | \n",
+ " 2028.91 | \n",
+ " 1028.31 | \n",
+ " 2726.38 | \n",
+ " 912.47 | \n",
+ " 1563.52 | \n",
+ " 1886.21 | \n",
+ " 2279.28 | \n",
+ " 4320.38 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-07 | \n",
+ " 1818.74 | \n",
+ " 1759.83 | \n",
+ " 1508.78 | \n",
+ " 2345.52 | \n",
+ " 1775.57 | \n",
+ " 2813.32 | \n",
+ " 4521.77 | \n",
+ " 1587.11 | \n",
+ " 1611.90 | \n",
+ " 4970.16 | \n",
+ " ... | \n",
+ " 877.56 | \n",
+ " 1410.63 | \n",
+ " 2022.18 | \n",
+ " 1022.42 | \n",
+ " 2725.25 | \n",
+ " 920.70 | \n",
+ " 1555.65 | \n",
+ " 1895.22 | \n",
+ " 2298.87 | \n",
+ " 4364.41 | \n",
+ "
\n",
+ " \n",
+ " 2014-01-08 | \n",
+ " 1818.81 | \n",
+ " 1755.68 | \n",
+ " 1493.70 | \n",
+ " 2322.49 | \n",
+ " 1803.61 | \n",
+ " 2830.83 | \n",
+ " 4552.21 | \n",
+ " 1576.37 | \n",
+ " 1624.17 | \n",
+ " 5016.00 | \n",
+ " ... | \n",
+ " 914.00 | \n",
+ " 1427.98 | \n",
+ " 2032.83 | \n",
+ " 1030.18 | \n",
+ " 2724.76 | \n",
+ " 923.90 | \n",
+ " 1529.75 | \n",
+ " 1892.09 | \n",
+ " 2324.57 | \n",
+ " 4294.82 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 2023-02-27 | \n",
+ " 3404.76 | \n",
+ " 4473.79 | \n",
+ " 2554.97 | \n",
+ " 5061.12 | \n",
+ " 3770.89 | \n",
+ " 7041.16 | \n",
+ " 24368.50 | \n",
+ " 1695.06 | \n",
+ " 2586.31 | \n",
+ " 9416.41 | \n",
+ " ... | \n",
+ " 583.41 | \n",
+ " 2132.33 | \n",
+ " 3127.16 | \n",
+ " 1547.29 | \n",
+ " 5858.12 | \n",
+ " 1577.72 | \n",
+ " 2912.48 | \n",
+ " 2295.91 | \n",
+ " 1893.76 | \n",
+ " 7324.37 | \n",
+ "
\n",
+ " \n",
+ " 2023-02-28 | \n",
+ " 3422.68 | \n",
+ " 4491.05 | \n",
+ " 2563.84 | \n",
+ " 5067.31 | \n",
+ " 3804.57 | \n",
+ " 7045.12 | \n",
+ " 24394.10 | \n",
+ " 1725.23 | \n",
+ " 2605.86 | \n",
+ " 9577.38 | \n",
+ " ... | \n",
+ " 590.74 | \n",
+ " 2180.57 | \n",
+ " 3139.45 | \n",
+ " 1562.79 | \n",
+ " 5885.11 | \n",
+ " 1585.71 | \n",
+ " 2892.28 | \n",
+ " 2301.03 | \n",
+ " 1908.33 | \n",
+ " 7378.86 | \n",
+ "
\n",
+ " \n",
+ " 2023-03-01 | \n",
+ " 3427.02 | \n",
+ " 4499.70 | \n",
+ " 2574.99 | \n",
+ " 5133.68 | \n",
+ " 3852.09 | \n",
+ " 7169.86 | \n",
+ " 24651.70 | \n",
+ " 1724.57 | \n",
+ " 2625.23 | \n",
+ " 9572.93 | \n",
+ " ... | \n",
+ " 611.74 | \n",
+ " 2264.47 | \n",
+ " 3178.12 | \n",
+ " 1592.56 | \n",
+ " 5928.54 | \n",
+ " 1601.62 | \n",
+ " 2898.94 | \n",
+ " 2314.55 | \n",
+ " 1912.48 | \n",
+ " 7356.28 | \n",
+ "
\n",
+ " \n",
+ " 2023-03-02 | \n",
+ " 3404.21 | \n",
+ " 4492.88 | \n",
+ " 2586.22 | \n",
+ " 5069.66 | \n",
+ " 3826.16 | \n",
+ " 7141.95 | \n",
+ " 24573.10 | \n",
+ " 1728.87 | \n",
+ " 2627.05 | \n",
+ " 9469.68 | \n",
+ " ... | \n",
+ " 623.22 | \n",
+ " 2287.31 | \n",
+ " 3187.21 | \n",
+ " 1591.15 | \n",
+ " 5855.66 | \n",
+ " 1602.82 | \n",
+ " 2903.87 | \n",
+ " 2329.61 | \n",
+ " 1907.04 | \n",
+ " 7351.53 | \n",
+ "
\n",
+ " \n",
+ " 2023-03-03 | \n",
+ " 3404.76 | \n",
+ " 4476.90 | \n",
+ " 2600.95 | \n",
+ " 5055.96 | \n",
+ " 3861.06 | \n",
+ " 7165.70 | \n",
+ " 24429.90 | \n",
+ " 1717.34 | \n",
+ " 2599.05 | \n",
+ " 9473.96 | \n",
+ " ... | \n",
+ " 620.29 | \n",
+ " 2272.00 | \n",
+ " 3212.64 | \n",
+ " 1600.36 | \n",
+ " 5847.44 | \n",
+ " 1600.26 | \n",
+ " 2908.11 | \n",
+ " 2354.67 | \n",
+ " 1914.78 | \n",
+ " 7315.95 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
2231 rows × 31 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ "code 801010.SI 801030.SI 801040.SI 801050.SI 801080.SI 801110.SI \\\n",
+ "trade_date \n",
+ "2014-01-02 1910.49 1820.03 1561.16 2395.99 1777.25 2949.75 \n",
+ "2014-01-03 1896.49 1803.59 1562.54 2396.36 1787.51 2881.53 \n",
+ "2014-01-06 1818.07 1752.00 1517.68 2344.21 1748.58 2807.65 \n",
+ "2014-01-07 1818.74 1759.83 1508.78 2345.52 1775.57 2813.32 \n",
+ "2014-01-08 1818.81 1755.68 1493.70 2322.49 1803.61 2830.83 \n",
+ "... ... ... ... ... ... ... \n",
+ "2023-02-27 3404.76 4473.79 2554.97 5061.12 3770.89 7041.16 \n",
+ "2023-02-28 3422.68 4491.05 2563.84 5067.31 3804.57 7045.12 \n",
+ "2023-03-01 3427.02 4499.70 2574.99 5133.68 3852.09 7169.86 \n",
+ "2023-03-02 3404.21 4492.88 2586.22 5069.66 3826.16 7141.95 \n",
+ "2023-03-03 3404.76 4476.90 2600.95 5055.96 3861.06 7165.70 \n",
+ "\n",
+ "code 801120.SI 801130.SI 801140.SI 801150.SI ... 801760.SI \\\n",
+ "trade_date ... \n",
+ "2014-01-02 4658.96 1654.62 1641.97 5051.73 ... 869.63 \n",
+ "2014-01-03 4615.06 1633.76 1638.41 5028.63 ... 883.52 \n",
+ "2014-01-06 4500.21 1581.04 1605.00 4919.26 ... 864.40 \n",
+ "2014-01-07 4521.77 1587.11 1611.90 4970.16 ... 877.56 \n",
+ "2014-01-08 4552.21 1576.37 1624.17 5016.00 ... 914.00 \n",
+ "... ... ... ... ... ... ... \n",
+ "2023-02-27 24368.50 1695.06 2586.31 9416.41 ... 583.41 \n",
+ "2023-02-28 24394.10 1725.23 2605.86 9577.38 ... 590.74 \n",
+ "2023-03-01 24651.70 1724.57 2625.23 9572.93 ... 611.74 \n",
+ "2023-03-02 24573.10 1728.87 2627.05 9469.68 ... 623.22 \n",
+ "2023-03-03 24429.90 1717.34 2599.05 9473.96 ... 620.29 \n",
+ "\n",
+ "code 801770.SI 801780.SI 801790.SI 801880.SI 801890.SI 801950.SI \\\n",
+ "trade_date \n",
+ "2014-01-02 1446.49 2085.20 1061.48 2842.70 945.51 1653.59 \n",
+ "2014-01-03 1445.33 2051.37 1034.81 2804.03 941.09 1628.32 \n",
+ "2014-01-06 1403.29 2028.91 1028.31 2726.38 912.47 1563.52 \n",
+ "2014-01-07 1410.63 2022.18 1022.42 2725.25 920.70 1555.65 \n",
+ "2014-01-08 1427.98 2032.83 1030.18 2724.76 923.90 1529.75 \n",
+ "... ... ... ... ... ... ... \n",
+ "2023-02-27 2132.33 3127.16 1547.29 5858.12 1577.72 2912.48 \n",
+ "2023-02-28 2180.57 3139.45 1562.79 5885.11 1585.71 2892.28 \n",
+ "2023-03-01 2264.47 3178.12 1592.56 5928.54 1601.62 2898.94 \n",
+ "2023-03-02 2287.31 3187.21 1591.15 5855.66 1602.82 2903.87 \n",
+ "2023-03-03 2272.00 3212.64 1600.36 5847.44 1600.26 2908.11 \n",
+ "\n",
+ "code 801960.SI 801970.SI 801980.SI \n",
+ "trade_date \n",
+ "2014-01-02 1921.99 2328.37 4451.86 \n",
+ "2014-01-03 1909.65 2320.01 4436.66 \n",
+ "2014-01-06 1886.21 2279.28 4320.38 \n",
+ "2014-01-07 1895.22 2298.87 4364.41 \n",
+ "2014-01-08 1892.09 2324.57 4294.82 \n",
+ "... ... ... ... \n",
+ "2023-02-27 2295.91 1893.76 7324.37 \n",
+ "2023-02-28 2301.03 1908.33 7378.86 \n",
+ "2023-03-01 2314.55 1912.48 7356.28 \n",
+ "2023-03-02 2329.61 1907.04 7351.53 \n",
+ "2023-03-03 2354.67 1914.78 7315.95 \n",
+ "\n",
+ "[2231 rows x 31 columns]"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pivot_ind_price"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "base",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.8"
+ },
+ "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}