8 月 13 日前后,半导体、芯片、科创 50、半导体设备这几个关键词又成了资金面讨论的高频词。这篇文章不是行情预测,更不是荐股,而是把一套完整的“板块跟踪流程”拆成数据获取、指标计算、策略回测、盘前盘后分析四个部分,用 Python 全部跑通。如果你也关心半导体设备和科创 50 的走势,想自己动手验证策略,而不是靠感觉拍板,这篇文章可以收藏。
先说清楚边界:技术分析只是辅助工具,所有代码、指标、回测框架都用于学习交流,不构成任何投资建议。文章会以“8.13 盯盘”为应用场景,演示怎么在当天快速拉取半导体板块和科创 50 指数数据,计算常用技术指标,并搭建一个最小可用的策略回测脚本。最终你会得到一套可以每日重复运行的本地分析工具箱。
1. 半导体板块跟踪的核心指标与数据源
先梳理一下标题里几个概念的关系。半导体是产业链的总称,芯片是半导体的下游产品,半导体设备则是支撑整个芯片制造环节的上游。科创 50 指数则是一个以科创板为样本的宽基指数,里面包含不少半导体产业链公司。它们之间的关系是:先看行业景气度,再看设备端订单,最后落到指数走势。
做板块跟踪,不建议只看单一股票。个股容易受消息面干扰,板块指数和行业指数更能反映整体趋势。常用观察维度包括:
- 指数点位与涨跌幅
- 成交额与换手率
- 5 日、10 日、20 日均线关系
- MACD、RSI 等动量指标
- 板块资金流
- 设备端龙头个股的相对强弱
数据源方面,国内常用的公开接口有 AKShare、Tushare,海外有 Yahoo Finance。其中 AKShare 免费、无需注册 token,适合做入门级行情获取;Tushare 数据更规整,但部分接口需要积分权限。对于普通个人研究者,推荐先用 AKShare 跑通流程,后续再按需切换数据源。
| 数据源 | 是否需要注册 | 数据频率 | 适用场景 |
|---|---|---|---|
| AKShare | 不需要 | 日线、分钟线 | 快速验证、个人研究 |
| Tushare | 需要 token | 日线、分钟线、资金流 | 数据规整、量化回测 |
| Yahoo Finance | 不需要 | 日线 | 指数历史数据补充 |
| 东方财富网页 | 不需要 | 实时行情 | 盘中快速查看 |
2. 量化分析环境准备
这一节的内容偏工程化。建议使用一个独立的 Python 环境,避免依赖冲突。推荐 Python 3.9 或更高版本,使用 venv 或 conda 创建虚拟目录。
# 创建并激活虚拟环境 python -m venv quant_env source quant_env/bin/activate # Windows 下使用 quant_env\Scripts\activate需要安装的库并不多,核心是 pandas、numpy、matplotlib、akshare、tushare。pandas 负责数据处理,numpy 做数值计算,matplotlib 画图,akshare/tushare 拉取行情。
pip install pandas numpy matplotlib akshare tushare安装完成后,可以快速验证数据接口是否正常:
import akshare as ak # 尝试获取科创50指数日线数据 df = ak.stock_zh_index_daily(symbol="sh000688") print(df.tail())如果这一步能打印出包含 date、open、high、low、close、volume 的 DataFrame,说明环境基本可用。接口名称可能随 AKShare 版本更新而变化,遇到调用失败时,优先查当前版本官方文档。
这套环境没有 GPU 依赖,普通办公电脑就能跑。唯一的注意点是网络环境要能正常访问数据源接口,部分数据源对请求频率有限制,连续拉取时加一点延时更稳妥。
3. 获取科创50与半导体板块行情数据
行情数据是整个分析的地基。这里给出两个最常用的获取场景:一是获取科创50指数日线,二是获取半导体板块历史行情。
3.1 获取科创50指数日线
科创50代码是 000688,在 AKShare 中常用sh000688表示。这个接口返回的字段相对稳定,包含日期、开盘、最高、最低、收盘、成交量等基础行情字段。
import akshare as ak import pandas as pd # 拉取科创50指数历史日线 df_index = ak.stock_zh_index_daily(symbol="sh000688") # 字段标准化 df_index.rename( columns={ "date": "trade_date", "open": "open", "high": "high", "low": "low", "close": "close", "volume": "volume" }, inplace=True ) # 将日期列转为标准化格式 df_index["trade_date"] = pd.to_datetime(df_index["trade_date"]) # 只保留最近一年的数据 df_index = df_index[df_index["trade_date"] >= "2023-08-01"].reset_index(drop=True) print(df_index.tail(10))拿到数据后可以做两步检查:第一判断日期是否连续,第二判断收盘价是否存在异常跳变。这两步是数据清洗的前提,直接决定后续指标计算的可靠性。
3.2 获取半导体板块历史行情
板块历史行情在 AKShare 中通常走行业板块接口,需要先确认当前版本支持的接口名称。一个常用写法是stock_board_industry_hist_em,参数里指定板块名为“半导体”,再设置起止日期。
# 获取半导体板块历史行情 # 注意:接口名称和参数以当前AKShare版本为准 df_semi = ak.stock_board_industry_hist_em( symbol="半导体", start_date="20240101", end_date="20240813", period="日k", adjust="" ) print(df_semi.tail(10))如果接口不可用,也可以用本地 CSV 文件兜底。比如从行情软件导出半导体板块指数日线数据,保存为 CSV 后读取:
df_semi = pd.read_csv("semi_industry_daily.csv", parse_dates=["date"]) df_semi["trade_date"] = pd.to_datetime(df_semi["date"]) df_semi = df_semi.sort_values("trade_date").reset_index(drop=True)建议在工程目录里固定一个data/raw文件夹存放原始数据,一个data/processed文件夹存放清洗后的数据。这样每天增量更新时,不会破坏历史数据。
4. 技术指标计算:MA、MACD、RSI 实战
拿到行情数据后,下一步就是计算指标。这里给出三个最常用且逻辑透明的指标:双均线 MA、MACD、RSI。它们分别从趋势、动能、超买超卖三个角度描述板块状态。
4.1 双均线
均线的核心用途是观察趋势方向。5 日均线代表短期成本,20 日均线代表中期成本。当短期均线运行在长期均线上方时,盘面偏强;反之偏弱。
# 基于科创50指数计算均线 df = df_index.copy() df["ma5"] = df["close"].rolling(5).mean() df["ma10"] = df["close"].rolling(10).mean() df["ma20"] = df["close"].rolling(20).mean() # 标记短期趋势状态 df["trend"] = "震荡" df.loc[df["ma5"] > df["ma20"], "trend"] = "短期偏强" df.loc[df["ma5"] < df["ma20"], "trend"] = "短期偏弱" # 只看最近几天 print(df[["trade_date", "close", "ma5", "ma20", "trend"]].tail(10))这里有一个容易踩的坑:当日收盘时的均线值要等到收盘后才会确定,盘中实时计算时均线会随着价格波动不断变化,回测时要注意避免使用未来数据。
4.2 MACD
MACD 是趋势型动量指标,由 DIF、DEA 和柱状图组成。DIF 上穿 DEA 通常视为金叉信号,下穿视为死叉信号。金叉不一定代表上涨,但可以辅助判断短期动能是否转强。
# 计算MACD df["ema12"] = df["close"].ewm(span=12, adjust=False).mean() df["ema26"] = df["close"].ewm(span=26, adjust=False).mean() df["dif"] = df["ema12"] - df["ema26"] df["dea"] = df["dif"].ewm(span=9, adjust=False).mean() df["macd"] = (df["dif"] - df["dea"]) * 2 # 找出最近的交叉点 df["cross"] = "无" df.loc[(df["dif"] > df["dea"]) & (df["dif"].shift(1) <= df["dea"].shift(1)), "cross"] = "金叉" df.loc[(df["dif"] < df["dea"]) & (df["dif"].shift(1) >= df["dea"].shift(1)), "cross"] = "死叉" print(df[["trade_date", "dif", "dea", "macd", "cross"]].tail(10))4.3 RSI
RSI 衡量一段时间内涨跌力量的相对强弱。默认周期是 14,常用 70 和 30 作为参考阈值。RSI 超过 70 说明短线偏热,跌破 30 说明短线偏冷。
# 计算RSI 14 delta = df["close"].diff() gain = delta.clip(lower=0) loss = -delta.clip(upper=0) avg_gain = gain.rolling(14).mean() avg_loss = loss.rolling(14).mean() rs = avg_gain / avg_loss df["rsi14"] = 100 - (100 / (1 + rs)) print(df[["trade_date", "close", "rsi14"]].tail(10))三个指标配合使用,逻辑是:均线定方向,MACD 定动量,RSI 观察是否过热或超卖。比如均线偏强、MACD 金叉、RSI 未超过 70,可以视为一个相对健康的偏强状态;如果均线偏弱、MACD 死叉、RSI 持续在 50 以下,则需要警惕继续走弱的风险。
5. 量价关系与资金流向观察
技术指标只能反映价格自身的运动轨迹。要判断一个板块的上涨是否真实,还需要观察成交量。资金面的验证逻辑很简单:价格涨、成交额放大,代表有资金参与;价格涨、成交额萎缩,说明可能是无量反弹。
对于半导体板块,建议重点观察三个指标:
- 板块成交额变化
- 换手率
- 龙头个股相对强弱
成交额可以从板块行情接口直接获取,也可以通过close * volume估算。以科创50为例,可以用成交量乘以收盘价得到近似的成交金额,但严格来说应该用实际成交额字段。
# 观察量价配合情况 df["amount_approx"] = df["close"] * df["volume"] # 最近5日量价对比 df["volume_ma5"] = df["volume"].rolling(5).mean() df["amount_ma5"] = df["amount_approx"].rolling(5).mean() # 量价同步判断 df["量价状态"] = "待观察" df.loc[(df["close"] > df["close"].shift(1)) & (df["volume"] > df["volume_ma5"]), "量价状态"] = "放量上涨" df.loc[(df["close"] < df["close"].shift(1)) & (df["volume"] > df["volume_ma5"]), "量价状态"] = "放量下跌" df.loc[(df["close"] > df["close"].shift(1)) & (df["volume"] < df["volume_ma5"]), "量价状态"] = "缩量上涨" df.loc[(df["close"] < df["close"].shift(1)) & (df["volume"] < df["volume_ma5"]), "量价状态"] = "缩量回调" print(df[["trade_date", "close", "volume", "volume_ma5", "量价状态"]].tail(8))资金流接口在 AKShare 中也有提供,比如个股资金流、行业资金流,但接口参数变化较多。稳妥的办法是先确认当前版本支持的接口,再封装到自己的函数里。如果拿不到资金流数据,可以用成交额环比变化替代,做一次数据降维。
| 量价组合 | 可能的含义 | 注意点 |
|---|---|---|
| 放量上涨 | 资金关注度高 | 需要观察是否持续 |
| 缩量上涨 | 抛压不重但追涨意愿弱 | 容易出现冲高回落 |
| 放量下跌 | 抛压明显 | 需要警惕趋势转弱 |
| 缩量回调 | 回踩不破结构 | 是相对健康的回调 |
6. 策略回测:用历史数据验证规则
“明天策略”听起来很玄,但在量化框架里,它其实是一个可以被验证的规则。规则不能凭感觉定,而是要先在历史数据上做回测,看看如果过去一直按这套规则操作,结果会怎样。
这里演示一个最简单的双均线策略:5 日均线上穿 20 日均线时买入并持有,5 日均线下穿 20 日均线时空仓。这个策略不追求高收益,重点是展示完整的回测流程。
import numpy as np # 准备数据 df_bt = df_index.copy() df_bt = df_bt.sort_values("trade_date").reset_index(drop=True) # 计算均线 df_bt["ma5"] = df_bt["close"].rolling(5).mean() df_bt["ma20"] = df_bt["close"].rolling(20).mean() # 生成信号:5日均线在上方为1,否则为0 df_bt["signal"] = (df_bt["ma5"] > df_bt["ma20"]).astype(int) # 避免未来函数:持仓信号延后一天 df_bt["position"] = df_bt["signal"].shift(1).fillna(0) # 计算策略每日收益 df_bt["ret"] = df_bt["close"].pct_change().fillna(0) df_bt["strategy_ret"] = df_bt["position"] * df_bt["ret"] # 计算累计收益 df_bt["strategy_cum"] = (1 + df_bt["strategy_ret"]).cumprod() df_bt["buy_hold_cum"] = (1 + df_bt["ret"]).cumprod() print(df_bt[["trade_date", "close", "ma5", "ma20", "position", "strategy_cum", "buy_hold_cum"]].tail(10))回测结束不要只看最后收益,还需要统计几个关键数字:
def evaluate_backtest(df): total_return = df["strategy_cum"].iloc[-1] - 1 buy_hold_return = df["buy_hold_cum"].iloc[-1] - 1 # 年化收益估算 trading_days = len(df) years = trading_days / 250 annual_return = (1 + total_return) ** (1 / years) - 1 if years > 0 else 0 # 最大回撤 drawdown = df["strategy_cum"] / df["strategy_cum"].cummax() - 1 max_drawdown = drawdown.min() # 交易次数 trade_days = df["position"].diff().fillna(0).abs().sum() print(f"策略累计收益: {total_return:.2%}") print(f"买入持有收益: {buy_hold_return:.2%}") print(f"策略年化收益: {annual_return:.2%}") print(f"最大回撤: {max_drawdown:.2%}") print(f"模拟交易次数: {trade_days}") evaluate_backtest(df_bt)回测结果只代表历史规律,不代表未来。A 股板块轮动快,半导体又是高波动的方向,任何简单策略都会在特定行情下失效。所以回测的意义不是找到“圣杯”,而是让自己对规则的优劣势有清晰的认知:什么时候该按规则做,什么时候规则可能失真。
7. “明天策略”的拆解:盘前、盘中、盘后分析框架
把“明天策略”这四个字落到实处,不应该是押注明天的涨跌,而是建立一套可重复执行的决策流程。这里给出一个既适合人工盯盘、也适合脚本自动化的分析框架。
7.1 盘前准备
盘前的主要工作是更新数据、检查信号。每天开盘前 30 分钟,可以运行一个 Python 脚本,自动拉取前一交易日收盘数据,计算均线、MACD、RSI、量价状态,然后输出一份格式化报告。
# 盘前数据更新与信号汇总示例 def generate_morning_report(): # 这里假设 df 已经是更新到最新收盘的数据 latest = df.iloc[-1] prev = df.iloc[-2] report = f""" 科创50盘前检查报告 最新收盘: {latest['close']:.2f} 涨跌幅: {latest['close'] / prev['close'] - 1:.2%} 5日均线: {latest['ma5']:.2f} 20日均线: {latest['ma20']:.2f} 趋势状态: {latest['trend']} RSI14: {latest['rsi14']:.2f} 量价状态: {latest['量价状态']} """ if latest["close"] > latest["ma20"]: report += "\n整体状态: 位于20日均线上方,趋势偏强\n" else: report += "\n整体状态: 位于20日均线下方,趋势偏弱\n" return report # print(generate_morning_report())这份报告的价值不是给出买卖点,而是帮助复盘昨天的策略执行是否到位。如果昨天制定了“跌破 20 日均线减仓”的规则,今天报告显示收盘价已经低于 20 日均线,那么盘前就该把这条规则标记为待执行。
7.2 盘中监控
盘中监控不建议频繁盯分钟线,否则容易被噪音干扰。更合理的方式是设置几个关键价格位,比如 5 日均线、10 日均线、20 日均线,以及前一日高点、低点。价格触碰或者放量跌破关键位时再介入判断。
如果你有实时行情接口,可以用一个简单的定时任务实现盘中监控:
import time def check_price_alert(current_price, ma20, alert_drop_ratio=0.03): # 当前价相对20日均线跌幅超过3%时告警 if current_price < ma20 * (1 - alert_drop_ratio): return "盘中跌破20日均线3%,触发告警" return "未触发告警" # 实际使用时,按分钟或按5分钟轮询 # current_price = get_realtime_price("000688") # print(check_price_alert(current_price, latest_ma20))盘中触发告警不等于马上操作,而是提示你去人工复核成交额、板块内其他个股表现以及消息面变化,这是把机械规则和人工判断结合起来的折中方式。
7.3 盘后复盘
盘后复盘是每天最重要的一步。主要回答三个问题:今天执行了什么?哪些地方和计划不一致?不一致的原因是什么?
可以维护一个简单的交易日志 CSV:
import csv from datetime import datetime def write_trade_log(rule_name, signal, detail): with open("trade_log.csv", "a", newline="", encoding="utf-8") as f: writer = csv.writer(f) writer.writerow([datetime.now().strftime("%Y-%m-%d %H:%M:%S"), rule_name, signal, detail]) # write_trade_log("均线规则", "减仓", "收盘跌破20日均线")交易日志写久了,你会发现自己最容易犯的错误是什么:是信号触发后没有执行,还是执行时随意改了价格,又或是根本没有遵守仓位限制。这些统计价值远大于单次交易的成败。
8. 常见问题与风险控制
这里把半导体板块量化跟踪中可能遇到的问题列成一张清单。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| AKShare 接口报错 | 版本更新接口名变化 | 查看官方文档 | 更新库版本或改用 tushare |
| 数据日期不连续 | 法定节假日、停牌 | 检查日期列表 | 用交易日历对齐 |
| 计算指标出现 NaN | 滚动窗口期不足 | 查看前20行数据 | 等窗口期积累后处理 |
| 回测结果突然异常 | 使用了未来数据 | 检查 signal 是否 shift | 确认信号延后一天 |
| 盘中接口请求被封 | 请求频率过高 | 设置间隔时间 | 加 time.sleep 并降低频率 |
| 策略收益与实盘偏差大 | 未考虑手续费和滑点 | 加成本模型 | 回测中加入千分之几的交易成本 |
| 指标持续钝化 | 行情处于震荡区间 | 观察布林带或波动率 | 切换趋势/震荡判断逻辑 |
风控部分需要单独强调。无论策略是手工执行还是自动化交易,都需要先设定三个数字:每次投入比例、止损比例、最大连续亏损次数。没有这三项限制,再好的策略也会因为一次重仓失误而失去优势。
半导体板块波动大,设备类企业受产业周期影响更深。一个稳健的做法是把规则验证放在第一位:先用小额资金验证规则,不追求短期爆发,优先确保自己的判断框架能在不同行情里被解释清楚。
9. 合规提醒与最佳实践
最后这部分是硬性提醒。文章里所有代码、指标、策略示例都只是技术演示,不构成投资建议。任何实际交易行为,都应当在理解风险、确认合规的前提下,由本人独立决策。
在工程实践层面,有几点建议值得落地:
第一,数据与代码分离。把 AKShare、Tushare 的接口调用集中封装在data_fetcher.py里,策略代码不直接依赖数据源。这样即使以后换数据源,策略层不用改动。
第二,固定抽查时间。建议每天收盘后统一更新数据,生成指标报告,避免盘中数据与收盘数据混用。历史回测全部使用收盘数据,盘中只做实时观察。
第三,保留最小可运行配置。一套最简单的脚本就是三个文件:数据下载脚本、指标计算脚本、报告生成脚本。不要一上来就构建庞大的自动交易系统,先保证三个文件能稳定跑三个月再说。
第四,结果复核。任何自动化生成的信号,都必须有人工复核环节。尤其是涉及具体操作时,账户持仓、可用资金、交易规则这些现实约束必须纳入判断。
第五,版本管理。行情数据、策略参数、回测结果都要有版本记录。最简单的方式是用日期目录归档,例如outputs/20240813/,每天生成的文件放到当天目录下,方便回溯。
8 月 13 日只是又一个普通交易日,真正有价值的不是当天涨跌,而是你能不能把自己的判断流程固定下来。从环境搭建到数据获取,从指标计算到回测验证,这套纯本地、零门槛的 Python 工具链,可以帮你用结构化方式跟踪半导体、芯片、科创 50 和半导体设备板块。建议先把第一版跑通,再逐步增加资金流、个股相对强弱和波动率指标,让模型更像你自己的决策框架。