en un clic
etf-analysis
ETF分析:产品筛选、费率对比、跟踪误差、流动性评估、策略应用与中国市场ETF量化配置框架。
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Menu
ETF分析:产品筛选、费率对比、跟踪误差、流动性评估、策略应用与中国市场ETF量化配置框架。
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Basé sur la classification professionnelle SOC
Candlestick pattern recognition engine, pure pandas vectorized implementation of 15 classic candlestick patterns (5 single-candle + 5 double-candle + 4 triple-candle + 1 trend confirmation), generating a composite signal from bullish/bearish pattern scores.
基于缠论(缠中说禅)的形态识别引擎,使用czsc库自动检测K线分型、笔、中枢,并生成一买/一卖/二买/二卖/三买/三卖等买卖点信号。支持多周期分析和形态分类(3/5/7/9/11笔形态)。
A股可转债分析——转股/纯债/期权三维估值、下修/强赎/回售博弈、双低策略与转债轮动选债框架
公司事件驱动分析:并购套利价差计算、大股东增减持信号、股权激励解读、定增配股影响评估、A股ST/退市预警
Data source selection — VN-only. All data comes from vnstock (fundamentals + OHLCV) and VietFin DNSE (OHLCV fallback).
Elliott Wave Theory signal engine. Detects swing points through Zigzag, matches 5-wave impulse and 3-wave corrective structures, validates them with Fibonacci wave relationships, and generates trend-top / correction-complete signals. Pure in-house pandas implementation.
| name | etf-analysis |
| description | ETF分析:产品筛选、费率对比、跟踪误差、流动性评估、策略应用与中国市场ETF量化配置框架。 |
| category | asset-class |
ETF(交易所交易基金)是被动投资与资产配置的核心工具。本 skill 覆盖 ETF 产品分析、选择方法论、策略应用、中国市场特色以及数据驱动的量化分析方法,为构建基于 ETF 的量化策略与组合提供完整框架。
| 类型 | 代表产品 | 特点 |
|---|---|---|
| 宽基 ETF | 沪深300ETF (510300)、中证500ETF (510500)、创业板ETF (159915)、科创50ETF (588000) | 流动性最好,交易成本最低,适合核心仓位 |
| 行业 ETF | 消费ETF (159928)、医疗ETF (512170)、半导体ETF (512480)、银行ETF (512800) | 行业轮动工具,持仓集中度高 |
| 主题 ETF | 新能源ETF (516160)、碳中和ETF、元宇宙ETF | 主题炒作属性强,生命周期短 |
| 策略ETF / Smart Beta | 红利ETF (510880)、低波ETF、质量ETF、动量ETF | 因子暴露明确,费率通常略高于宽基 |
| 商品 ETF | 黄金ETF (518880)、豆粕ETF (159985)、原油ETF (162411) | 实物/期货支撑,注意展期损耗 |
| 债券 ETF | 国债ETF (511010)、信用债ETF、可转债ETF (511380) | 利率敏感,久期管理关键 |
| 跨境 ETF (QDII) | 纳指ETF (159632)、标普500ETF (513500)、日经225ETF (513880) | 汇率风险+溢价风险双重叠加 |
| 货币 ETF | 华宝添益 (511990)、银华日利 (511880) | T+0 申赎,流动性管理工具 |
衡量 ETF 复制指数能力的最核心指标。
日跟踪误差 = std(ETF日收益率 - 指数日收益率)
年化跟踪误差 = 日跟踪误差 × √252
评级标准(A股宽基ETF):
跟踪误差来源:
IR = (ETF年化收益率 - 指数年化收益率) / 年化跟踪误差
对 ETF 来说 IR 通常为负(因费率拖累),IR 越接近 0 越好。
折溢价率 = (ETF市价 - ETF净值IOPV) / ETF净值IOPV × 100%
| 指标 | 含义 | 参考阈值 |
|---|---|---|
| 日均成交额 | 买卖方便程度 | 宽基 > 1亿,行业 > 2000万 |
| 买卖价差(Spread) | 即时交易成本 | < 0.05% 为优质 |
| 盘口深度 | 单笔大额交易冲击 | 买卖各5档累计 > 500万为佳 |
| 换手率 | 活跃程度 | 过低则流动性风险高 |
综合费率 = 管理费 + 托管费 + 指数使用费
(不含交易佣金、印花税、申赎费)
长期费率影响公式:
N年费率复利损耗 = (1 - 年费率)^N
例:年费率0.5% vs 0.15%,10年差距 ≈ 3.5%,20年差距 ≈ 6.8%
主流宽基 ETF 费率对比(2025年):
规模门槛:
10亿:流动性充足,做市商活跃
100亿:旗舰 ETF,机构首选
清盘风险信号:规模持续下滑、连续90天日均规模 < 5000万
同一指数往往有多只 ETF,选择步骤:
Step 1: 规模筛选 → 剔除 < 5亿的小规模产品
Step 2: 费率比较 → 同等条件下选费率最低
Step 3: 跟踪误差 → 近1年/近3年双维度比较
Step 4: 流动性 → 日均成交额、买卖价差
Step 5: 基金公司 → 指数化投资能力、历史口碑
量化评分模型:
def etf_score(etf_data: dict) -> float:
"""
ETF 综合评分(越高越好,满分100)。
Args:
etf_data: 包含 scale, fee, tracking_error, avg_volume, spread 的字典
Returns:
综合评分 0~100
"""
score = 0.0
# 规模得分(30分)
scale = etf_data['scale_billion']
score += min(30, scale / 10 * 30)
# 费率得分(25分):费率越低越高分
fee = etf_data['total_fee_pct'] # 年费率百分比
score += max(0, 25 - fee * 50)
# 跟踪误差得分(30分):误差越小越高分
te = etf_data['tracking_error_annual_pct']
score += max(0, 30 - te * 60)
# 流动性得分(15分)
vol = etf_data['avg_daily_volume_million']
score += min(15, vol / 10 * 15)
return round(score, 2)
import numpy as np
def fee_drag_analysis(annual_return: float, years: int, fee_rates: list[float]) -> dict:
"""
分析不同费率对长期收益的拖累效果。
Args:
annual_return: 指数年化收益率(小数,如0.08)
years: 投资年限
fee_rates: 待比较的费率列表(小数,如[0.002, 0.005, 0.015])
Returns:
各费率下的终值倍数和相对拖累字典
"""
results = {}
base_value = (1 + annual_return) ** years
for fee in fee_rates:
net_return = annual_return - fee
end_value = (1 + net_return) ** years
drag = (base_value - end_value) / base_value * 100
results[f'{fee*100:.2f}%'] = {
'end_value_multiple': round(end_value, 4),
'drag_pct': round(drag, 2)
}
return results
# 示例:8% 指数收益,20年期
# fee_drag_analysis(0.08, 20, [0.002, 0.005, 0.015])
优质做市商体现在:
评估方法:
# 通过Level2数据计算有效价差
effective_spread = (ask_price - bid_price) / mid_price * 100 # 单位 %
# 价格冲击成本(Impact Cost)
# 买入N万元所需均价相对于中间价的偏离
impact_cost = (avg_buy_price - mid_price) / mid_price * 100
| 维度 | 评估要点 |
|---|---|
| ETF 管理规模 | 全市场排名,指数化投资专业度 |
| 跟踪误差历史 | 长期维度(3年+)稳定性 |
| 产品线完整性 | 宽基、行业、跨境覆盖广度 |
| 申赎效率 | T+0 实物申赎处理能力 |
| 做市商合作质量 | 与头部券商做市商的合作稳定性 |
国内 ETF 管理头部公司(规模口径):华夏、易方达、华泰柏瑞、南方、嘉实、博时
总组合 = 核心仓位(70~80%)+ 卫星仓位(20~30%)
核心仓位:宽基ETF(沪深300/中证500/全A)
→ 获取市场beta,低费率,长期持有,减少交易摩擦
卫星仓位:行业ETF/主题ETF/Smart Beta ETF
→ 增强收益,主动暴露特定因子,允许更高换手
再平衡触发条件:
动量轮动:
def sector_momentum_rotation(etf_returns: pd.DataFrame, lookback: int = 20, top_n: int = 3) -> list[str]:
"""
基于动量的行业ETF轮动选择。
Args:
etf_returns: 各行业ETF日收益率 DataFrame,列为ETF代码
lookback: 回看窗口(交易日数)
top_n: 持有ETF数量
Returns:
本期持有的ETF代码列表
"""
momentum = etf_returns.tail(lookback).sum()
selected = momentum.nlargest(top_n).index.tolist()
return selected
宏观周期轮动:
| 经济周期 | 推荐行业 ETF |
|---|---|
| 复苏期(低增长→高增长,低通胀) | 消费、科技、中小盘 |
| 过热期(高增长,高通胀) | 能源、材料、工业 |
| 滞胀期(低增长,高通胀) | 能源、公用事业、消费 |
| 衰退期(高增长→低增长) | 医疗、公用事业、债券ETF |
主要因子及对应ETF:
| 因子 | 代表ETF | 历史有效性(A股) |
|---|---|---|
| 价值(低估值) | 沪深300价值ETF | 中等,受风格切换影响 |
| 红利(高股息) | 红利ETF (510880) | 较强,尤其熊市防御 |
| 低波动 | 中证低波ETF | 较强,夏普比优于宽基 |
| 质量(高ROE) | 中证质量ETF | 较强,长期复合效果好 |
| 动量 | 目前A股产品少 | 中短期有效,长期均值回归 |
| 小盘 | 中证1000ETF (512100) | 强,但流动性风险高 |
因子暴露分析代码:
import pandas as pd
import numpy as np
from scipy import stats
def factor_exposure_analysis(etf_returns: pd.Series, factor_returns: dict[str, pd.Series]) -> pd.DataFrame:
"""
分析ETF对各因子的暴露程度(单因子回归)。
Args:
etf_returns: ETF日收益率序列
factor_returns: 各因子收益率字典 {因子名: 收益率序列}
Returns:
包含 beta, t_stat, r_squared 的 DataFrame
"""
results = []
for factor_name, factor_ret in factor_returns.items():
aligned = pd.concat([etf_returns, factor_ret], axis=1).dropna()
x = aligned.iloc[:, 1].values
y = aligned.iloc[:, 0].values
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
results.append({
'factor': factor_name,
'beta': round(slope, 4),
't_stat': round(slope / std_err, 2),
'r_squared': round(r_value ** 2, 4),
'p_value': round(p_value, 4)
})
return pd.DataFrame(results).set_index('factor')
Beta 衰减(Volatility Decay)原理:
每日恒定杠杆 N 倍 → 复合效应导致长期收益 ≠ N × 指数收益
衰减量(近似)= N²(N-1)/2 × σ² × T
其中 σ 为指数日波动率,T 为持有天数
数值示例:
适用场景:
折溢价套利(需要有实物申赎资格,通常门槛100万份):
溢价套利:
ETF市价 > IOPV + 交易成本
→ 买入一篮子成分股 → 申购ETF份额 → 卖出ETF
→ 套利利润 ≈ 溢价率 - 冲击成本 - 佣金
折价套利:
ETF市价 < IOPV - 交易成本
→ 买入ETF份额 → 赎回一篮子成分股 → 卖出成分股
→ 套利利润 ≈ 折价率 - 冲击成本 - 佣金
跨市场套利(ETF vs 期货):
IF(沪深300股指期货)基差 = 期货价格 - 沪深300指数
当基差 > 合理基差(无风险利率×剩余期限)时:
→ 卖期货 + 买ETF(正向套利)
当基差 < 合理基差时:
→ 买期货 + 卖ETF(反向套利,需融券)
统计套利(配对交易):
# 同类ETF(如不同公司发行的沪深300ETF)之间的价差均值回归
# 价差 = 价格差 或 价格比
# 当价差偏离历史均值2个标准差时建仓,回归时平仓
spread = etf_a_price / etf_b_price
z_score = (spread - spread.rolling(60).mean()) / spread.rolling(60).std()
signal = pd.Series(0, index=z_score.index)
signal[z_score > 2] = -1 # ETF_A 相对贵,卖A买B
signal[z_score < -2] = 1 # ETF_A 相对便宜,买A卖B
| 维度 | 场内 ETF | 场外联接基金 |
|---|---|---|
| 购买渠道 | 证券账户,实时交易 | 银行/基金直销,T+1申赎 |
| 申赎方式 | 实物申赎(机构)或二级市场(个人) | 现金申赎 |
| 折溢价 | 存在(有套利机制) | 不存在 |
| 最小交易单位 | 100份(约10~100元) | 1元起投 |
| 费率 | 较低(管理费+交易佣金) | 略高(申购费+管理费) |
| 适合场景 | 波段操作、大额配置 | 定投、小额长期持有 |
溢价形成原因:
溢价率警戒线:
5%:高溢价,存在显著买入风险(净值回落但溢价收窄双杀)
汇率对冲:
LOF(上市开放式基金):
分级基金(已全面转型,2020年前历史参考):
宽基指数:
| 指数 | 成分股 | 特点 |
|---|---|---|
| 沪深300 | 沪深两市市值最大300只 | 大盘蓝筹,衍生品丰富(IF期货/300期权) |
| 中证500 | 300~800名中盘股 | 中盘成长,与300互补 |
| 中证1000 | 800~1800名小盘股 | 小盘因子,波动较大 |
| 上证50 | 沪市最大50只 | 超大盘,金融地产权重高 |
| 创业板指 | 创业板前100名 | 科技成长,波动大 |
| 科创50 | 科创板前50名 | 硬科技,上市时间短 |
| 北证50 | 北交所前50名 | 新兴市场,流动性弱 |
| 中证全指 / 万得全A | 全市场 | 最宽泛的基准 |
指数调整规律:
经典配置框架(可用ETF实现):
股债 60/40 中国版:
沪深300ETF 30% + 中证500ETF 20% + 中债ETF 40% + 黄金ETF 10%
全天候组合(中国版):
股票ETF(沪深300)25%
长期国债ETF 40%
中期国债ETF 15%
黄金ETF 7.5%
商品ETF 12.5%
哑铃策略:
宽基ETF(低风险核心)50%
行业/主题ETF(高弹性进攻)50%
A股:沪深300ETF 510300 / 中证500ETF 510500
美股:纳指ETF 159632 / 标普500ETF 513500
港股:恒生ETF 159920 / 恒生科技ETF 513130
欧洲:德国DAX ETF / 欧洲50ETF(规模较小)
日本:日经225ETF 513880 / 东证ETF
新兴:越南ETF / 印度ETF(部分有QDII溢价)
固定收益:
国内:国债ETF 511010 / 政金债ETF
美国:美债ETF(QDII)
商品:
黄金ETF 518880
原油ETF 162411
CRB商品指数ETF(国内较少)
再平衡成本:
单次再平衡成本 ≈ 交易金额 × (佣金率 + 价差/2 + 冲击成本)
≈ 交易金额 × 0.05%~0.15%(宽基ETF)
年化再平衡成本 = 单次成本 × 年均调仓次数
最优再平衡频率建议:
免佣金再平衡技巧:
中国 ETF 税务规则:
税务效率策略:
from vnstock import Vnstock
import pandas as pd
stock = Vnstock().stock(symbol="VNM", source="KBS")
# 获取基金列表
def get_vn_fund_list() -> pd.DataFrame:
"""
获取越南市场基金列表。
"""
df = stock.listing.funds()
return df[['symbol', 'name', 'fund_type', 'management_company']]
# 获取基金净值历史
def get_fund_nav(symbol: str, start_date: str, end_date: str) -> pd.DataFrame:
"""
获取基金净值历史。
Args:
symbol: 基金代码 (e.g., "FUEVFVND")
start_date, end_date: YYYY-MM-DD
"""
stock = Vnstock().stock(symbol=symbol, source="KBS")
df = stock.funds.nav_history(symbol, start=start_date, end=end_date)
return df[['date', 'nav', 'accum_nav']]
# 获取基金持仓
def get_fund_holdings(symbol: str, report_date: str) -> pd.DataFrame:
"""
获取基金持仓明细。
Args:
symbol: 基金代码
report_date: 报告日期 YYYY-MM-DD
"""
df = stock.funds.holdings(symbol, report_date=report_date)
return df[['symbol', 'stock_name', 'volume', 'market_value', 'ratio']]
import numpy as np
import pandas as pd
def calc_tracking_error(
etf_prices: pd.Series,
index_prices: pd.Series,
annualize: bool = True
) -> dict:
"""
计算ETF对标的指数的跟踪误差。
Args:
etf_prices: ETF净值序列(以date为索引)
index_prices: 指数价格序列(以date为索引)
annualize: 是否年化,默认True
Returns:
包含 tracking_error, avg_daily_diff, max_daily_diff 的字典
"""
# 对齐数据
aligned = pd.concat([etf_prices, index_prices], axis=1).dropna()
aligned.columns = ['etf', 'index']
# 计算日收益率差值
etf_ret = aligned['etf'].pct_change().dropna()
idx_ret = aligned['index'].pct_change().dropna()
daily_diff = etf_ret - idx_ret
# 跟踪误差 = 差值的标准差
te_daily = daily_diff.std()
te = te_daily * np.sqrt(252) if annualize else te_daily
return {
'tracking_error': round(te * 100, 4), # 百分比
'avg_daily_diff': round(daily_diff.mean() * 100, 4), # 平均日偏差 %
'max_daily_diff': round(daily_diff.abs().max() * 100, 4), # 最大单日偏差 %
'annualized': annualize
}
def compare_etfs_same_index(
etf_codes: list[str],
index_symbol: str,
start_date: str,
end_date: str
) -> pd.DataFrame:
"""
比较追踪同一指数的多只越南ETF的跟踪表现。
Args:
etf_codes: ETF代码列表 (e.g., ["FUEVFVND", "FUESSVFL"])
index_symbol: 基准指数代码 (e.g., "VNINDEX")
start_date, end_date: YYYY-MM-DD
Returns:
各ETF的跟踪误差比较 DataFrame
"""
from app.services.dnse.intraday_tool import get_intraday_tool
from datetime import datetime, timezone, timedelta
tool = get_intraday_tool()
# Fetch index data
TZ_VN = timezone(timedelta(hours=7))
from_dt = datetime.strptime(start_date, "%Y-%m-%d").replace(tzinfo=TZ_VN)
to_dt = datetime.strptime(end_date, "%Y-%m-%d").replace(tzinfo=TZ_VN)
index_candles = tool.fetch(index_symbol, resolution="1D",
from_ts=int(from_dt.timestamp()),
to_ts=int(to_dt.timestamp()))
index_prices = pd.Series({c["time"][:10]: float(c["close"]) for c in index_candles})
results = []
for code in etf_codes:
fund_candles = tool.fetch(code, resolution="1D",
from_ts=int(from_dt.timestamp()),
to_ts=int(to_dt.timestamp()))
fund_prices = pd.Series({c["time"][:10]: float(c["close"]) for c in fund_candles})
te_result = calc_tracking_error(fund_prices, index_prices)
te_result['symbol'] = code
results.append(te_result)
return pd.DataFrame(results).set_index('symbol').sort_values('tracking_error')
def calc_premium_discount(
market_price: float,
iopv: float
) -> dict:
"""
计算越南ETF折溢价率及套利信号。
Args:
market_price: ETF场内市价
iopv: 参考净值(IOPV)
Returns:
包含 premium_pct, signal, arbitrage_feasible 的字典
"""
premium_pct = (market_price - iopv) / iopv * 100
if premium_pct > 0.3:
signal = 'PREMIUM_HIGH'
feasible = premium_pct > 0.5
elif premium_pct < -0.3:
signal = 'DISCOUNT_HIGH'
feasible = premium_pct < -0.5
else:
signal = 'NORMAL'
feasible = False
return {
'premium_pct': round(premium_pct, 2),
'signal': signal,
'arbitrage_feasible': feasible
}
from vnstock import Vnstock
import pandas as pd
def get_fund_nav_history(
symbol: str,
start_date: str,
end_date: str
) -> pd.DataFrame:
"""
获取越南基金净值历史数据。
Args:
symbol: 基金代码 (e.g., "FUEVFVND", "FUESSVFL")
start_date: 开始日期
end_date: 结束日期
Returns:
DataFrame 包含日期、净值、累计净值
"""
stock = Vnstock().stock(symbol=symbol, source="KBS")
df = stock.funds.nav_history(symbol, start=start_date, end=end_date)
return df[['date', 'nav', 'accum_nav']]
def list_vn_funds() -> pd.DataFrame:
"""
列出越南市场所有基金。
Returns:
DataFrame 包含基金代码、名称、类型、管理公司
"""
from vnstock import Vnstock
stock = Vnstock().stock(symbol="VNM", source="KBS")
return stock.listing.funds()
分析追踪 [沪深300/中证500/xxx] 指数的所有ETF,
维度:规模、费率、近1年跟踪误差、日均成交额、买卖价差。
给出综合评分排名,并推荐最适合[长期持有/波段操作/大额配置]的产品。
基于过去 [20/60] 日动量,在以下行业ETF中选出前3名:
[消费、医疗、科技、能源、金融、工业、材料、公用事业]
同时排除近30日跌幅超过15%的ETF。
构建以下ETF组合并回测 [2020-01-01 至 2025-12-31]:
- 沪深300ETF 40%
- 中证500ETF 20%
- 国债ETF 30%
- 黄金ETF 10%
每季度再平衡,计算年化收益、夏普比率、最大回撤、与沪深300的相关性。
监控以下QDII ETF的实时折溢价率:[纳指ETF 159632、标普500 513500、日经225 513880]
溢价 > 3% 时发出预警,建议等待回落后再入场。