name: Portfolio Risk Analysis Expert slug: security-portfolio-risk description: AI-powered portfolio risk analysis expert for China market — covers VaR calculation, stress testing, tail risk measurement, factor exposure analysis, and risk decomposition. Built for fund managers, risk analysts, and institutional investors. Keywords: portfolio risk, VaR, stress testing, risk decomposition, China A-share, factor risk, tail risk, 組合風險, 風險分析, VaR, 壓力測試, 風險分解, 風險管理, 最大回撤, 夏普比率, 收益風險比, 資產配置, 風險預算. version: "3.0.1"
English: AI-powered portfolio risk analysis expert — covers VaR calculation, stress testing, tail risk measurement, factor exposure, and risk attribution. Built for fund managers and risk analysts.
中文: 組合風險分析專家——覆蓋VaR計算、壓力測試、尾部風險度量、因子敞口分析、風險歸因。適用:基金經理、風險分析師、機構投資者。
| 動態型別 | 內容摘要 | 影響範圍 |
|---|---|---|
| 證券監管 | 2026年Q1:市場波動加劇,組合風險管理要求提升 | 組合風險模型需增加量化衝擊和ESG風險維度 |
| 證券監管 | 量化資金共振風險增加,極端行情止損策略需更新 | 組合風險模型需增加量化衝擊和ESG風險維度 |
| 證券監管 | ESG投資分析要求擴大,組合風險需納入ESG因素 | 組合風險模型需增加量化衝擊和ESG風險維度 |
資料截止: 2026-05-25 | 來源:證監會、NFRA、中證協、安永Q1分析 宣告: 以上動態供參考,具體以官方最新發布為準
| Pain Point / 痛點 | Impact / 影響 | Solution / 本Skill解決方案 |
|---|---|---|
| 系統風險難預測 | 黑天鵝事件導致大幅回撤 | 極端情景壓力測試+尾部風險分析 |
| 因子敞口不清晰 | 不知道組合暴露在哪些風險上 | 因子歸因模型+敞口分解 |
| 回撤控制困難 | 持有人體驗差,資金贖回壓力 | 動態回撤監控+預警機制 |
| 相關性突變 | 平時低相關的資產大跌時齊跌 | 相關性壓力測試+分散化效果評估 |
| 合規要求高 | 資管新規淨值化要求 | 標準風險指標+監管報告 |
English Triggers: portfolio risk, VaR, stress testing, risk decomposition, factor exposure, tail risk, risk attribution, China A-share, fund management, risk management
中文觸發詞(優先): 組合風險 / 風險分析 / VaR / 壓力測試 / 回撤控制 / 風險歸因 / 因子敞口 / 尾部風險 / 風險分解 / 風險預警 / 資產配置 / 分散化 / 相關性分析 / 最大回撤 / 夏普比率 / 波動率 / 風險調整收益 / 風險預算 / VaR計算 / CVaR / ES
import numpy as np
import pandas as pd
from scipy import stats
class PortfolioRiskAnalyzer:
"""組合風險分析引擎"""
def __init__(self, returns: pd.DataFrame, weights: np.ndarray):
"""
Args:
returns: 收益率序列(列=資產,行=日期)
weights: 資產權重向量
"""
self.returns = returns
self.weights = weights
self.n_assets = len(weights)
def calculate_var(self, confidence: float = 0.95,
method: str = "historical") -> dict:
"""計算VaR(Value at Risk)"""
portfolio_returns = (self.returns * self.weights).sum(axis=1)
if method == "historical":
var = np.percentile(portfolio_returns, (1 - confidence) * 100)
elif method == "parametric":
mu = portfolio_returns.mean()
sigma = portfolio_returns.std()
var = stats.norm.ppf(1 - confidence, mu, sigma)
elif method == "modified":
# Cornish-Fisher調整
mu = portfolio_returns.mean()
sigma = portfolio_returns.std()
skew = stats.skew(portfolio_returns)
kurt = stats.kurtosis(portfolio_returns)
z = stats.norm.ppf(1 - confidence)
z_cf = (z + (z**2 - 1) * skew / 6 +
(z**3 - 3*z) * kurt / 24 -
(2*z**3 - 5*z) * skew**2 / 36)
var = mu + sigma * z_cf
return {
"var": round(var * 100, 2), # 百分比
"var_amount": round(var * 1000000, 2), # 假設100萬組合
"confidence": confidence,
"method": method,
"interpretation": f"在{confidence*100}%置信度下,最大損失為{abs(var)*100:.2f}%"
}
def calculate_cvar(self, confidence: float = 0.95) -> dict:
"""計算CVaR(Conditional VaR / Expected Shortfall)"""
portfolio_returns = (self.returns * self.weights).sum(axis=1)
var = np.percentile(portfolio_returns, (1 - confidence) * 100)
cvar = portfolio_returns[portfolio_returns <= var].mean()
return {
"cvar": round(cvar * 100, 2),
"cvar_amount": round(cvar * 1000000, 2),
"interpretation": f"超過VaR時的平均損失為{abs(cvar)*100:.2f}%"
}
def calculate_max_drawdown(self) -> dict:
"""計算最大回撤"""
cumulative = (1 + self.returns @ self.weights).cumprod()
running_max = cumulative.expanding().max()
drawdown = (cumulative - running_max) / running_max
max_dd = drawdown.min()
max_dd_end = drawdown.idxmin()
max_dd_start = cumulative[:max_dd_end].idxmax()
return {
"max_drawdown": round(max_dd * 100, 2),
"peak_date": str(max_dd_start.date()),
"trough_date": str(max_dd_end.date()),
"recovery_date": None # 需後續計算
}
def factor_risk_attribution(self, factor_returns: pd.DataFrame) -> dict:
"""因子風險歸因"""
portfolio_returns = self.returns @ self.weights
# 迴歸分析
X = factor_returns.values
X = np.column_stack([np.ones(len(X)), X])
y = portfolio_returns.values
coeffs = np.linalg.lstsq(X, y, rcond=None)[0]
residuals = y - X @ coeffs
# 分解方差
total_var = np.var(y)
factor_var = np.var(X[:, 1:] @ coeffs[1:])
specific_var = np.var(residuals)
return {
"factor_exposure": {
"market": round(coeffs[1], 3),
"factors": {
col: round(coef, 3)
for col, coef in zip(factor_returns.columns, coeffs[2:])
}
},
"risk_contribution": {
"factor_risk": round(factor_var / total_var * 100, 2),
"specific_risk": round(specific_var / total_var * 100, 2)
},
"r_squared": round(1 - specific_var / total_var, 4)
}
class StressTestScenarios:
"""壓力測試情景庫"""
SCENARIOS = {
"2015股災重演": {
"description": "假設上證指數單週下跌20%",
"market_shock": -0.20,
"sector_impacts": {
"金融": -0.25,
"房地產": -0.30,
"消費": -0.15,
"科技": -0.20,
"醫藥": -0.10
},
"liquidity_shock": 0.5 # 流動性降至50%
},
"利率急升": {
"description": "假設基準利率上調100bp",
"rate_shock": 0.01,
"bond_impact": -0.08,
"equity_impact": -0.10,
"bank_impact": -0.05
},
"人民幣急貶": {
"description": "假設USD/CNY一日升值5%",
"fx_shock": 0.05,
"export_related": -0.15,
"import_related": 0.05,
"domestic_consumer": -0.08
},
"黑天鵝-新冠": {
"description": "類似2020年初疫情衝擊",
"market_shock": -0.12,
"travel": -0.30,
"retail": -0.20,
"healthcare": 0.10,
"online": 0.05
}
}
def run_stress_test(self, portfolio: dict, scenario: str) -> dict:
"""執行壓力測試"""
if scenario not in self.SCENARIOS:
raise ValueError(f"Unknown scenario: {scenario}")
s = self.SCENARIOS[scenario]
positions = portfolio["positions"]
stressed_pnl = 0
stressed_values = []
for pos in positions:
sector = pos.get("sector", "general")
weight = pos["weight"]
# 根據情景調整
if "sector_impacts" in s and sector in s["sector_impacts"]:
shock = s["sector_impacts"][sector]
else:
shock = s.get("market_shock", -0.10)
pos_stressed = weight * (1 + shock)
stressed_values.append(pos_stressed)
stressed_pnl += weight * shock
total_value = sum(stressed_values)
portfolio_stress_loss = total_value - 1 # 假設初始為1
return {
"scenario": scenario,
"description": s["description"],
"portfolio_loss": round(portfolio_stress_loss * 100, 2),
"portfolio_value_after": round(total_value * 100, 2),
"position_impacts": [
{"name": pos["name"], "weight": pos["weight"],
"shock": round(shock * 100, 2), "impact": "loss" if shock < 0 else "gain"}
for pos, shock in zip(positions,
[s.get("sector_impacts", {}).get(pos.get("sector", ""),
s.get("market_shock", -0.10)) for pos in positions])
]
}
def risk_contribution_by_asset(self) -> dict:
"""計算各資產風險貢獻"""
cov_matrix = self.returns.cov()
portfolio_vol = np.sqrt(self.weights @ cov_matrix.values @ self.weights)
# 邊際風險貢獻 (MCTR)
mctr = (cov_matrix.values @ self.weights) / portfolio_vol
# 風險貢獻
risk_contrib = self.weights * mctr
return {
"portfolio_volatility": round(portfolio_vol * 100, 2),
"asset_risk_contribution": {
self.returns.columns[i]: round(rc * 100, 2)
for i, rc in enumerate(risk_contrib)
},
"concentration_risk": {
"max_concentration": round(max(risk_contrib) * 100, 2),
"diversification_benefit": round(
(sum([self.returns[col].std() * w
for col, w in zip(self.returns.columns, self.weights)]) -
portfolio_vol) * 100, 2)
}
}
本技能來自小蔥技能站7w4.net。
組合風險評估:
分析以下組合的風險:
- 總規模:1000萬
- 持倉:[股票A 30%, 股票B 20%, 債券B 50%]
- 置信度:95%
壓力測試:
執行"2015股災重演"情景壓力測試
This skill provides risk analysis tools for educational purposes. Risk metrics are based on historical data and statistical models, which do not guarantee future accuracy. Investment decisions should be made based on comprehensive analysis and professional advice.
這是一款質量不錯的專業級金融風險分析技能,優勢在於專業性強、程式碼實現完善、貼閤中國市場實際。不足之處是缺少使用示例和操作指南,新手上手有一定難度,更適合有一定專業背景的使用者使用。