Positioning
ETFs (Exchange-Traded Funds) are a core tool for passive investing and asset allocation. This skill covers ETF product analysis, selection methodology, strategy application, characteristics of the Chinese market, and data-driven quantitative analysis methods, providing a complete framework for building ETF-based quantitative strategies and portfolios.
1. ETF Product Classification
1.1 Classification by Underlying Asset
| Type | Representative Products | Characteristics |
|---|---|---|
| Broad-Based ETF | CSI 300 ETF (510300), CSI 500 ETF (510500), ChiNext ETF (159915), STAR 50 ETF (588000) | Best liquidity, lowest trading costs, suitable for core positions |
| Sector ETF | Consumer ETF (159928), Healthcare ETF (512170), Semiconductor ETF (512480), Bank ETF (512800) | Sector rotation tool, high position concentration |
| Thematic ETF | New Energy ETF (516160), Carbon Neutrality ETF, Metaverse ETF | Strong thematic speculation attributes, short lifecycle |
| Strategy ETF / Smart Beta | Dividend ETF (510880), Low Volatility ETF, Quality ETF, Momentum ETF | Clear factor exposure, fees usually slightly higher than broad-based |
| Commodity ETF | Gold ETF (518880), Soybean Meal ETF (159985), Crude Oil ETF (162411) | Backed by physical/futures, watch for roll yield loss |
| Bond ETF | Treasury Bond ETF (511010), Credit Bond ETF, Convertible Bond ETF (511380) | Interest rate sensitive, duration management is key |
| Cross-Border ETF (QDII) | Nasdaq ETF (159632), S&P 500 ETF (513500), Nikkei 225 ETF (513880) | Double exposure to currency risk + premium risk |
| Money Market ETF | Hwabao Tianyi (511990), Yinhua Rili (511880) | T+0 subscription/redemption, liquidity management tool |
1.2 Structural Types
- Ordinary ETF: Exchanged on-market, physical subscription/redemption (basket of stocks for shares), premium/discount automatically converges via arbitrage mechanism
- LOF (Listed Open-Ended Fund): Tradable both on-market and off-market, same premium/discount arbitrage path but slightly less efficient
- ETF Feeder Fund: ETF substitute purchased through off-market channels, T+1 subscription/redemption, no premium/discount, suitable for regular investment plans
- Leveraged/Inverse ETF: Constant intraday leverage, decay effect when held long-term (see Section 3.4)
2. Core ETF Metrics
2.1 Tracking Error
The most core metric for measuring an ETF's ability to replicate its index.
日跟踪误差 = std(ETF日收益率 - 指数日收益率)
年化跟踪误差 = 日跟踪误差 × √252
Rating Standards (A-share Broad-Based ETF):
- Excellent: annualized tracking error < 0.2%
- Qualified: 0.2% ~ 0.5%
- Poor: > 0.5%
Sources of Tracking Error:
- Management fees and custody fees (continuous drag, accrued daily)
- Dividend processing timing (delay in dividend reinvestment)
- Buy/sell impact when constituent stocks are included/excluded
- Cash position (temporary cash drag from subscriptions/redemptions)
- Handling of suspended stocks (using substitutes or cash substitutes)
- Index construction methodology (full replication vs sampling replication)
2.2 Information Ratio (IR)
IR = (ETF年化收益率 - 指数年化收益率) / 年化跟踪误差
For ETFs, IR is usually negative (due to fee drag); the closer the IR is to 0, the better.
2.3 Premium/Discount Rate
折溢价率 = (ETF市价 - ETF净值IOPV) / ETF净值IOPV × 100%
- Premium: market price > NAV; arbitrageurs sell the ETF / subscribe a basket of stocks to exchange, and the premium converges
- Discount: market price < NAV; arbitrageurs buy the ETF / redeem a basket of stocks, and the discount converges
- Abnormal premium scenario: cross-border QDII ETFs (quota restrictions lead to sustained premiums), sector ETFs with a high proportion of suspended stocks
2.4 Liquidity Indicators
| Indicator | Meaning | Reference threshold |
|---|---|---|
| Average daily turnover | Ease of buying and selling | Broad-based > 100 million, sector > 20 million |
| Bid-ask spread (Spread) | Immediate trading cost | < 0.05% is high quality |
| Order book depth | Impact of a single large trade | Cumulative 5 levels each on bid and ask > 5 million is preferable |
| Turnover rate | Activity level | Too low means high liquidity risk |
2.5 Fee Structure
综合费率 = 管理费 + 托管费 + 指数使用费
(不含交易佣金、印花税、申赎费)
Long-term fee impact formula:
N年费率复利损耗 = (1 - 年费率)^N
例:年费率0.5% vs 0.15%,10年差距 ≈ 3.5%,20年差距 ≈ 6.8%
Comparison of fee rates of mainstream broad-based ETFs (2025):
- China AMC/E Fund/Southern CSI 300 ETF: 0.15% (management) + 0.05% (custody) = 0.20%
- Some small-scale broad-based ETFs: 0.5%+, significant disadvantage for long-term holding
2.6 Scale and Liquidity Assessment
-
Scale threshold:
- < 200 million: relatively high liquidation risk, poor liquidity
- 200 million to 1 billion: normal trading possible, large funds are constrained
-
1 billion: sufficient liquidity, active market makers
-
10 billion: flagship ETF, first choice for institutions
-
Liquidation risk signals: scale continues to decline, average daily scale < 50 million for 90 consecutive days
3. ETF Selection Methodology
3.1 Framework for Comparing ETFs of the Same Category
The same index often has multiple ETFs; selection steps:
Step 1: 规模筛选 → 剔除 < 5亿的小规模产品
Step 2: 费率比较 → 同等条件下选费率最低
Step 3: 跟踪误差 → 近1年/近3年双维度比较
Step 4: 流动性 → 日均成交额、买卖价差
Step 5: 基金公司 → 指数化投资能力、历史口碑
Quantitative scoring model:
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)
3.2 Quantitative Analysis of the Impact of Fees on Long-Term Returns
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])
3.3 Market Maker Quality Assessment
High-quality market makers are reflected in:
- Stable spreads: small spread widening during volatile periods (< 3 times normal level)
- Sufficient depth: uniform amounts across order book levels
- Quote continuity: does not frequently cancel and requote
- Handling of large orders: spreads recover quickly after large trades
Evaluation methods:
# 通过Level2数据计算有效价差
effective_spread = (ask_price - bid_price) / mid_price * 100 # 单位 %
# 价格冲击成本(Impact Cost)
# 买入N万元所需均价相对于中间价的偏离
impact_cost = (avg_buy_price - mid_price) / mid_price * 100
3.4 Fund Company Strength Assessment
| Dimension | Evaluation points |
|---|---|
| ETF management scale | Whole-market ranking, expertise in index investing |
| Tracking error history | Stability over the long term (3 years+) |
| Product line completeness | Breadth of coverage in broad-based, sector, and cross-border |
| Subscription and redemption efficiency | T+0 in-kind subscription and redemption processing capability |
| Quality of market maker cooperation | Stability of cooperation with leading brokerage market makers |
Leading domestic ETF management companies (by scale): ChinaAMC, E Fund, Huatai-PineBridge, Southern, Harvest, Bosera
4. ETF Strategy Applications
4.1 Core-Satellite Strategy (Core-Satellite)
总组合 = 核心仓位(70~80%)+ 卫星仓位(20~30%)
核心仓位:宽基ETF(沪深300/中证500/全A)
→ 获取市场beta,低费率,长期持有,减少交易摩擦
卫星仓位:行业ETF/主题ETF/Smart Beta ETF
→ 增强收益,主动暴露特定因子,允许更高换手
Rebalancing Trigger Conditions:
- Time trigger: quarterly/semi-annually
- Deviation trigger: a single asset deviates from target weight > 5%
4.2 Sector Rotation ETF Strategy
Momentum rotation:
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
Macro cycle rotation:
| Economic Cycle | Recommended Sector ETFs |
|---|---|
| Recovery phase (low growth → high growth, low inflation) | Consumer, Technology, Small/Mid-cap |
| Overheating phase (high growth, high inflation) | Energy, Materials, Industrials |
| Stagflation phase (low growth, high inflation) | Energy, Utilities, Consumer |
| Recession phase (high growth → low growth) | Healthcare, Utilities, Bond ETFs |
4.3 Smart Beta ETF Factor Exposure Analysis
Main factors and corresponding ETFs:
| Factor | Representative ETF | Historical Effectiveness (A-shares) |
|---|---|---|
| Value (low valuation) | CSI 300 Value ETF | Moderate, affected by style rotation |
| Dividend (high dividend yield) | Dividend ETF (510880) | Strong, especially defensive in bear markets |
| Low Volatility | CSI Low Volatility ETF | Strong, Sharpe ratio superior to broad-based |
| Quality (high ROE) | CSI Quality ETF | Strong, good long-term compounding effect |
| Momentum | Currently few A-share products | Effective in short-to-medium term, mean reversion in long term |
| Small-cap | CSI 1000 ETF (512100) | Strong, but high liquidity risk |
Factor Exposure Analysis Code:
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')
4.4 Decay Effect of Leveraged/Inverse ETFs
Beta Decay (Volatility Decay) Principle:
每日恒定杠杆 N 倍 → 复合效应导致长期收益 ≠ N × 指数收益
衰减量(近似)= N²(N-1)/2 × σ² × T
其中 σ 为指数日波动率,T 为持有天数
Numerical Example:
- Index annualized volatility 20%, daily volatility ≈ 1.26%
- 2x leveraged ETF, held for 1 year: decay loss ≈ 2² × (2-1)/2 × (0.2)² × 1 ≈ 4%
Applicable Scenarios:
- Leveraged ETF: short-term tool in strong trend markets (holding < 1 month)
- Inverse ETF: market hedging, short-term bearish bets (not suitable for long-term holding)
- Strictly Prohibited: Using leveraged/inverse ETFs for long-term allocation positions
4.5 ETF Arbitrage Strategies
Premium/Discount Arbitrage(Requires physical creation/redemption qualification, typically threshold 1 million units):
溢价套利:
ETF市价 > IOPV + 交易成本
→ 买入一篮子成分股 → 申购ETF份额 → 卖出ETF
→ 套利利润 ≈ 溢价率 - 冲击成本 - 佣金
折价套利:
ETF市价 < IOPV - 交易成本
→ 买入ETF份额 → 赎回一篮子成分股 → 卖出成分股
→ 套利利润 ≈ 折价率 - 冲击成本 - 佣金
Cross-Market Arbitrage (ETF vs Futures):
IF(沪深300股指期货)基差 = 期货价格 - 沪深300指数
当基差 > 合理基差(无风险利率×剩余期限)时:
→ 卖期货 + 买ETF(正向套利)
当基差 < 合理基差时:
→ 买期货 + 卖ETF(反向套利,需融券)
Statistical Arbitrage (Pairs Trading):
# 同类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
5. Characteristics of China's ETF Market
5.1 On-Exchange ETF vs Off-Exchange Feeder Fund
| Dimension | On-Exchange ETF | Off-Exchange Feeder Fund |
|---|---|---|
| Purchase Channel | Securities account, real-time trading | Bank/fund direct sales, T+1 subscription/redemption |
| Subscription/Redemption Method | Physical creation/redemption (institutional) or secondary market (individual) | Cash creation/redemption |
| Premium/discount | Exists (has arbitrage mechanism) | Does not exist |
| Minimum trading unit | 100 units (about 10–100 yuan) | Minimum investment of 1 yuan |
| Fees | Relatively low (management fee + trading commission) | Slightly higher (subscription fee + management fee) |
| Suitable scenarios | Swing trading, large allocations | Regular investment plans, small long-term holdings |
5.2 Special considerations for cross-border ETFs (QDII)
Reasons for premium formation:
- QDII quota limits: after the fund company's QDII quota is used up, subscriptions are suspended, and the arbitrage mechanism ceases to function
- Exchange rate impact: when the renminbi depreciates, the net asset value of ETFs holding overseas assets rises, triggering chasing of gains
- Time zone impact: when the A-share market closes, overseas markets have not yet opened, so the IOPV reference price lags
Premium rate warning lines:
- < 2%: normal range, can be allocated normally
- 2%–5%: premium is obvious, entry requires caution, wait for it to fall back
-
5%: high premium, significant buying risk exists (net asset value falls while the premium narrows, a double hit)
Currency hedging:
- Some QDII ETFs offer hedged versions (such as S&P 500 hedged ETFs)
- Hedging cost ≈ China-US interest rate differential (about 1.5–2.5%/year in 2025), significantly reducing returns
5.3 Historical experience of LOFs and structured funds
LOF (Listed Open-Ended Fund):
- Tradable both on and off the exchange; discount arbitrage path: buy at an on-exchange discount → transfer custody → redeem off-exchange
- Custody transfer takes T+2 to T+3, with risk of net asset value changes
Structured funds (all fully transformed; historical reference before 2020):
- Class A shares: agreed-return type, similar to bonds
- Class B shares: leveraged type, linked to Class A's agreed return
- Important lesson: the downward conversion mechanism caused large losses for Class B shares; high-premium arbitrage was squeezed out
- Current status: regulators require all to be transformed into ordinary ETFs, with no new issuance
5.4 China's main ETF index systems
Broad-based indices:
| Index | Constituent stocks | Characteristics |
|---|---|---|
| CSI 300 | The 300 largest by market capitalization on the Shanghai and Shenzhen exchanges | Large-cap blue chips, rich derivatives (IF futures/CSI 300 options) |
| CSI 500 | Mid-cap stocks ranked 300–800 | Mid-cap growth, complementary to the CSI 300 |
| CSI 1000 | Small-cap stocks ranked 800–1800 | Small-cap factor, relatively high volatility |
| SSE 50 | The 50 largest on the Shanghai Stock Exchange | Ultra-large-cap, with high weightings in finance and real estate |
| ChiNext Index | Top 100 on ChiNext | Technology growth, high volatility |
| STAR 50 | Top 50 on the STAR Market | Hard technology, short time since listing |
| BSE 50 | Top 50 on the Beijing Stock Exchange | Emerging market, weak liquidity |
| CSI All Share / Wind All A | Whole market | The broadest benchmark |
Index adjustment rules:
- CSI 300/CSI 500: adjusted once each in June and December every year
- Before/after adjustment: included stocks rise, excluded stocks fall (short term), providing event-driven opportunities
6. ETF Portfolio Construction
6.1 Implementation of ETF-Based Asset Allocation
Classic Allocation Frameworks (Implementable with ETFs):
股债 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%
6.2 ETF Tool Selection for Global Allocation
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(国内较少)
6.3 Trade-off Between Rebalancing Frequency and Trading Costs
Rebalancing Costs:
单次再平衡成本 ≈ 交易金额 × (佣金率 + 价差/2 + 冲击成本)
≈ 交易金额 × 0.05%~0.15%(宽基ETF)
年化再平衡成本 = 单次成本 × 年均调仓次数
Recommended Optimal Rebalancing Frequency:
- Pure passive allocation (low volatility): twice a year (June/December)
- Sector rotation (high volatility): monthly or quarterly
- Threshold-triggered method: triggered when deviation from target weight > 5%, usually better than fixed frequency
Commission-Free Rebalancing Techniques:
- Use new capital to top up underweight positions in a targeted manner, reducing sell operations
- Allocate dividend income preferentially to underweight assets
6.4 Tax Efficiency Considerations
China ETF Tax Rules:
- Individual Investors:
- Capital gains on equity ETFs are tax-exempt (during holding period)
- ETF dividends: cash dividends are tax-exempt, dividend reinvestment is not taxed
- Money market ETF interest income: temporarily exempt from individual income tax
- Institutional Investors:
- Capital gains must be included in corporate income tax (25%)
- Dividends during holding period: tax-exempt if held > 12 months
Tax Efficiency Strategies:
- Place high-turnover sector rotation strategies in individual accounts as much as possible (leveraging capital gains tax exemption)
- Regular fixed-amount long-term holding, reducing the frequency of realizing short-term capital gains
7. Data Analysis Methods
7.1 Using Tushare to Obtain ETF Data
import tushare as ts
import pandas as pd
def get_etf_list(pro: ts.pro_api) -> pd.DataFrame:
"""
获取全市场ETF列表。
Args:
pro: tushare pro_api 实例
Returns:
ETF基本信息 DataFrame
"""
df = pro.fund_basic(market='E', status='L') # E=ETF, L=上市中
return df[['ts_code', 'name', 'management', 'found_date', 'issue_date']]
def get_etf_nav(pro: ts.pro_api, ts_code: str, start_date: str, end_date: str) -> pd.DataFrame:
"""
获取ETF净值数据(IOPV)。
Args:
pro: tushare pro_api 实例
ts_code: ETF代码,如 '510300.SH'
start_date: 开始日期 'YYYYMMDD'
end_date: 结束日期 'YYYYMMDD'
Returns:
包含 trade_date, nav, accum_nav 的 DataFrame
"""
df = pro.fund_nav(ts_code=ts_code, start_date=start_date, end_date=end_date)
return df.sort_values('end_date').reset_index(drop=True)
def get_etf_daily(pro: ts.pro_api, ts_code: str, start_date: str, end_date: str) -> pd.DataFrame:
"""
获取ETF场内日行情(市价)。
Args:
pro: tushare pro_api 实例
ts_code: ETF代码
start_date: 开始日期
end_date: 结束日期
Returns:
包含 trade_date, open, high, low, close, vol, amount 的 DataFrame
"""
df = pro.fund_daily(ts_code=ts_code, start_date=start_date, end_date=end_date)
return df.sort_values('trade_date').reset_index(drop=True)
def get_index_daily(pro: ts.pro_api, index_code: str, start_date: str, end_date: str) -> pd.DataFrame:
"""
获取基准指数日行情(用于计算跟踪误差)。
Args:
pro: tushare pro_api 实例
index_code: 指数代码,如 '000300.SH'(沪深300)
start_date: 开始日期
end_date: 结束日期
Returns:
包含 trade_date, close 的 DataFrame
"""
df = pro.index_daily(ts_code=index_code, start_date=start_date, end_date=end_date)
return df[['trade_date', 'close', 'pct_chg']].sort_values('trade_date').reset_index(drop=True)
7.2 Tracking Error Calculation Code Template
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_code: str,
pro,
start_date: str,
end_date: str
) -> pd.DataFrame:
"""
比较追踪同一指数的多只ETF的跟踪表现。
Args:
etf_codes: ETF代码列表
index_code: 基准指数代码
pro: tushare pro_api 实例
start_date: 开始日期
end_date: 结束日期
Returns:
各ETF的跟踪误差比较 DataFrame
"""
index_df = get_index_daily(pro, index_code, start_date, end_date)
index_prices = index_df.set_index('trade_date')['close']
results = []
for code in etf_codes:
nav_df = get_etf_nav(pro, code, start_date, end_date)
etf_prices = nav_df.set_index('end_date')['nav']
te_result = calc_tracking_error(etf_prices, index_prices)
te_result['ts_code'] = code
results.append(te_result)
return pd.DataFrame(results).set_index('ts_code').sort_values('tracking_error')
7.3 Premium/Discount Rate Monitoring
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' # 溢价:卖出ETF或申购套利
feasible = premium_pct > 0.5 # 扣除成本后是否可套利
elif premium_pct < -0.3:
signal = 'DISCOUNT_HIGH' # 折价:买入ETF或赎回套利
feasible = premium_pct < -0.5
else:
signal = 'NORMAL'
feasible = False
return {
'premium_pct': round(premium_pct, 4),
'signal': signal,
'arbitrage_feasible': feasible
}
def monitor_qdii_premium(pro, qdii_codes: list[str], date: str) -> pd.DataFrame:
"""
监控QDII ETF溢价率(溢价过高时发出预警)。
Args:
pro: tushare pro_api 实例
qdii_codes: QDII ETF代码列表
date: 查询日期 'YYYYMMDD'
Returns:
各QDII ETF的溢价率和风险等级 DataFrame
"""
results = []
for code in qdii_codes:
# 获取市价
price_df = pro.fund_daily(ts_code=code, trade_date=date)
# 获取净值
nav_df = pro.fund_nav(ts_code=code, end_date=date)
if not price_df.empty and not nav_df.empty:
market_price = price_df.iloc[0]['close']
nav = nav_df.iloc[0]['nav']
premium_pct = (market_price - nav) / nav * 100
risk_level = (
'HIGH' if premium_pct > 5
else 'MEDIUM' if premium_pct > 2
else 'LOW'
)
results.append({
'ts_code': code,
'market_price': market_price,
'nav': nav,
'premium_pct': round(premium_pct, 2),
'risk_level': risk_level
})
return pd.DataFrame(results).sort_values('premium_pct', ascending=False)
7.4 Capital Inflow and Outflow Analysis
def etf_fund_flow_analysis(
pro,
ts_code: str,
start_date: str,
end_date: str
) -> pd.DataFrame:
"""
分析ETF规模变化与资金净流入/流出。
Args:
pro: tushare pro_api 实例
ts_code: ETF代码
start_date: 开始日期
end_date: 结束日期
Returns:
包含规模变化和资金流向估算的 DataFrame
"""
nav_df = get_etf_nav(pro, ts_code, start_date, end_date)
nav_df['end_date'] = pd.to_datetime(nav_df['end_date'])
nav_df = nav_df.sort_values('end_date')
# 规模(单位亿元)
nav_df['scale'] = nav_df['unit_nav'] * nav_df['fund_share'] / 1e8
# 净值变动引起的规模变化(被动)
nav_df['nav_return'] = nav_df['unit_nav'].pct_change()
nav_df['passive_change'] = nav_df['scale'].shift(1) * nav_df['nav_return']
# 资金净流入 ≈ 规模变化 - 净值带来的被动变化
nav_df['net_flow'] = nav_df['scale'].diff() - nav_df['passive_change']
# 统计区间
summary = {
'total_net_flow': nav_df['net_flow'].sum(), # 区间总净流入(亿元)
'avg_daily_flow': nav_df['net_flow'].mean(), # 日均净流入
'inflow_days': (nav_df['net_flow'] > 0).sum(), # 净流入天数
'outflow_days': (nav_df['net_flow'] < 0).sum(), # 净流出天数
'current_scale': nav_df['scale'].iloc[-1] # 最新规模
}
return nav_df[['end_date', 'unit_nav', 'scale', 'net_flow']], summary
def cross_etf_flow_comparison(
pro,
etf_codes: list[str],
start_date: str,
end_date: str
) -> pd.DataFrame:
"""
比较同类ETF的资金流向,判断资金偏好。
Args:
pro: tushare pro_api 实例
etf_codes: 同类ETF代码列表
start_date: 开始日期
end_date: 结束日期
Returns:
各ETF资金流向汇总对比 DataFrame
"""
rows = []
for code in etf_codes:
_, summary = etf_fund_flow_analysis(pro, code, start_date, end_date)
summary['ts_code'] = code
rows.append(summary)
return pd.DataFrame(rows).set_index('ts_code').sort_values('total_net_flow', ascending=False)
8. Common Analysis Scenarios and Prompt Templates
Scenario 1: Screening for the Best ETF in the Same Category
分析追踪 [沪深300/中证500/xxx] 指数的所有ETF,
维度:规模、费率、近1年跟踪误差、日均成交额、买卖价差。
给出综合评分排名,并推荐最适合[长期持有/波段操作/大额配置]的产品。
Scenario 2: Sector ETF Rotation Signals
基于过去 [20/60] 日动量,在以下行业ETF中选出前3名:
[消费、医疗、科技、能源、金融、工业、材料、公用事业]
同时排除近30日跌幅超过15%的ETF。
Scenario 3: ETF Portfolio Backtesting
构建以下ETF组合并回测 [2020-01-01 至 2025-12-31]:
- 沪深300ETF 40%
- 中证500ETF 20%
- 国债ETF 30%
- 黄金ETF 10%
每季度再平衡,计算年化收益、夏普比率、最大回撤、与沪深300的相关性。
Scenario 4: QDII Premium Risk Monitoring
监控以下QDII ETF的实时折溢价率:[纳指ETF 159632、标普500 513500、日经225 513880]
溢价 > 3% 时发出预警,建议等待回落后再入场。
9. Key Considerations
- Trading Suspension Substitution: If a sector ETF has a large number of suspended stocks, IOPV becomes distorted, and the reference value of premium/discount declines
- QDII Quota: When the quota is exhausted, subscriptions are suspended, and the premium may persist for months, making it unsuitable for arbitrage
- Constituent Stock Adjustment: There are certain regular opportunities 1~2 weeks before and after the June/December index adjustments each year
- Leveraged ETFs Prohibited for Long-Term Holding: The decay effect is extremely pronounced in oscillating markets; strictly limit the holding period
- Money Market ETFs: Essentially money market funds, with logic different from ordinary ETFs; they are liquidity management tools rather than investment tools
- ETFs with Poor Liquidity: Large trades should be split across multiple days to avoid self-impact
- Tax Treatment: If ETF fund dividends include dividend income, the taxation rules differ from those for capital gains; be careful to distinguish them