🧠 面试八股文:数学、编程、因子、机器学习(点击展开/收起)
🧠 面试八股文:数学、编程、因子、机器学习
数学与统计基础
概率论
Q1:什么是条件概率?贝叶斯公式的直觉是什么?
标准答案:
条件概率表示在 B 已发生的条件下 A 发生的概率:
$$P(A \mid B) = \frac{P(A \cap B)}{P(B)}$$
贝叶斯公式:
$$P(A \mid B) = \frac{P(B \mid A) \cdot P(A)}{P(B)}$$
直觉:贝叶斯公式是"用新证据更新旧信念"的数学表达。这里 P(A) 是先验(你原来的判断),P(B|A) 是似然(新证据在你判断下出现的可能性),P(A|B) 是后验(看到证据后的新判断)。
量化应用:贝叶斯方法在信号衰减判断、因子择时、Black-Litterman模型中被广泛使用。
Q2:大数定律和中心极限定理的区别是什么?
标准答案:
- 大数定律(LLN):样本均值随样本量增大而趋近于总体均值。强调的是收敛。
- 中心极限定理(CLT):无论总体分布如何,样本均值的分布在n足够大时近似正态分布。强调的是分布形态。
关键区别:LLN告诉你"平均值会收敛到真值",CLT告诉你"收敛过程的波动长什么样"。
量化应用:CLT是计算VaR、构建置信区间、进行策略回测统计检验的理论基础。如果收益率不满足独立同分布假设(如存在自相关或异方差),CLT的收敛速度会变慢,需要用Newey-West等方法修正。
Q3:什么是鞅(Martingale)?它在金融中有什么意义?
标准答案:
鞅是一种随机过程,满足 $E[X_{t+1} | \mathcal{F}_t] = X_t$,即给定当前信息,未来期望等于当前值。
金融意义:
- 在风险中性测度下,折现后的资产价格是鞅——这是期权定价的理论基础
- 如果市场价格是鞅,则不存在趋势性的可预测利润,与有效市场假说一致
- 鞅差分序列(Martingale Difference Sequence)常用于检验收益率的可预测性
Q4:解释常见的概率分布及其在量化中的应用
标准答案:
| 分布 |
特征 |
量化应用 |
| 正态分布 |
均值对称、薄尾 |
收益率建模的基准假设(但实际中有偏度和峰度) |
| 对数正态分布 |
取对数后为正态 |
股票价格建模(GBM中价格服从对数正态) |
| t 分布 |
厚尾 |
更真实地描述收益率尾部风险,小样本推断 |
| 泊松分布 |
离散事件计数 |
跳跃扩散模型中的跳跃次数 |
| 指数分布 |
等待时间 |
订单到达间隔建模(高频) |
延伸:实际收益率分布通常呈现"尖峰厚尾"(leptokurtic),正态假设会低估极端风险。用Student-t、GED或混合正态分布能更好地拟合。
数理统计与推断
Q5:什么是极大似然估计(MLE)?与矩估计(GMM)有什么区别?
标准答案:
MLE:寻找使样本似然函数达到最大值的参数,常写作:
$$L(\theta_{\text{MLE}}) = \max_{\theta} L(\theta)$$
GMM(广义矩估计):利用总体矩条件与样本矩的匹配来估计参数,不需要假定完整的分布形式
核心区别:MLE需要完整的分布假设,效率高但对错误假设敏感;GMM更灵活,只需要矩条件,是半参数方法。
量化应用:GARCH模型常用MLE估计;资产定价模型(如Fama-French)的参数常用GMM估计;Hansen(1982)提出的GMM框架是实证资产定价的核心方法论。
Q6:假设检验中的 p 值到底是什么?为什么不能说"p值是假设为真的概率"?
标准答案:
p 值是在零假设为真的前提下,观测到当前统计量或更极端值的概率。
不能说"零假设为真的概率",因为p值是条件概率 $P(\text{data} | H_0)$,而不是 $P(H_0 | \text{data})$。后者需要贝叶斯框架。
量化应用中的陷阱:
- 策略回测中对数百个参数组合做假设检验,会出现多重检验问题(Multiple Testing)
- 一个p < 0.05的策略,如果是从1000个策略中筛选出来的,真实显著性远低于5%
- 修正方法:Bonferroni 校正、Benjamini-Hochberg(FDR 控制)、Bailey-López de Prado-Marcos 的 Haircut(折减)校正
Q7:什么是协方差矩阵?为什么在量化中估计协方差矩阵是困难的?
标准答案:
协方差矩阵 $\Sigma$ 的第(i,j)个元素是资产i和资产j收益率的协方差。它是组合优化、风险管理的核心输入。
困难之处:
- 维度灾难:N个资产需要估计 $N(N+1)/2$ 个参数,当N大于样本量T时,样本协方差矩阵奇异
- 噪声放大:样本协方差矩阵中的小特征值会被取逆时放大,导致组合权重极端
- 非平稳性:协方差结构随时间变化
常用解决方案:
- Ledoit-Wolf收缩估计:将样本矩阵向结构化目标(如对角阵)收缩
- 因子模型降维:假设 $\Sigma = B F B^T + D$(因子部分 + 特异性部分)
- 随机矩阵理论(RMT):用Marchenko-Pastur分布识别并剔除噪声特征值
- DCC-GARCH:建模时变协方差
线性代数
Q8:特征值分解(EVD)和奇异值分解(SVD)有什么区别?在量化中怎么用?
标准答案:
EVD:仅适用于方阵,Λ 是特征值对角阵:
$$A = P \Lambda P^{-1}$$
SVD:适用于任意矩阵,Σ 是奇异值对角阵:
$$A = U \Sigma V^T$$
对于对称半正定的协方差矩阵,EVD和SVD等价。
量化应用:
- PCA(主成分分析):对收益率协方差矩阵做EVD,前几个主成分通常对应市场、规模、价值等系统性因子
- 降噪:去除小特征值对应的成分
- 正则化:SVD用于病态线性回归(岭回归本质上是对奇异值做收缩)
Q9:什么是正定矩阵?为什么协方差矩阵必须半正定?
标准答案:
正定矩阵满足:对任意非零向量 x,都有
$$x^T A x > 0$$
半正定则要求:
$$x^T A x \ge 0$$
协方差矩阵必须半正定,因为组合方差在物理意义上不能为负:
$$w^T \Sigma w \ge 0$$
如果估计出的协方差矩阵不是半正定的(如用不同时间窗口的数据拼接),需要做"最近半正定矩阵"投影(如Higham算法)。
随机过程与时间序列
Q10:什么是平稳性(Stationarity)?为什么要关心它?
标准答案:
- 严平稳:联合分布不随时间平移改变
- 宽平稳(弱平稳):均值和自协方差函数不随时间变化
为什么关心:几乎所有时间序列建模方法(ARMA、协整分析等)都假设平稳性。对非平稳序列直接建模会产生伪回归(Spurious Regression),R²虚高但没有真实关系。
检验方法:ADF检验、PP检验、KPSS检验(注意KPSS的零假设是平稳)。
处理方法:差分(I(1)序列差分一次变平稳)、去趋势、对数变换。
Q11:ARIMA 和 GARCH 模型的区别与联系?
标准答案:
- ARIMA(p,d,q):建模条件均值。描述收益率本身的自回归和移动平均结构。
- GARCH(p,q):建模条件方差。描述波动率的聚集效应(volatility clustering)。
联系:通常组合使用,ARIMA建模均值方程,GARCH建模残差的方差方程。完整模型:
$$r_t = \mu_t(\text{ARIMA}) + \epsilon_t, \quad \epsilon_t = \sigma_t z_t, \quad \sigma_t^2 = \omega + \alpha \epsilon_{t-1}^2 + \beta \sigma_{t-1}^2$$
量化应用:GARCH族模型广泛用于波动率预测、VaR计算、期权隐含波动率建模。常用扩展包括EGARCH(捕捉杠杆效应)、GJR-GARCH等。
Q12:什么是协整(Cointegration)?和相关性有什么区别?
标准答案:
- 相关性:衡量两个变量线性关联的强度,是静态的
- 协整:两个非平稳序列的某个线性组合是平稳的,是动态的长期均衡关系
经典例子:醉汉和他的狗——各自随机游走(非平稳),但距离围绕某个均值波动(协整)。
量化应用:配对交易(Pairs Trading)的理论基础。找到协整关系后:
- 构建价差 $S_t = Y_t - \beta X_t$
- 当价差偏离均值时建仓,回归时平仓
- 常用Engle-Granger两步法或Johansen检验判断协整关系
注意:高相关不代表协整,协整也不要求高相关。
随机微积分基础
Q13:什么是布朗运动?Itô引理是什么?
标准答案:
布朗运动(维纳过程) $W_t$:
- $W_0 = 0$
- 增量独立且服从 $W_{t+s} - W_t \sim N(0, s)$
- 路径连续但处处不可微
Itô引理:随机微积分的"链式法则"。若 $dX_t = \mu , dt + \sigma , dW_t$,则对 $f(X_t, t)$:
$$df = \left(\frac{\partial f}{\partial t} + \mu \frac{\partial f}{\partial x} + \frac{1}{2}\sigma^2 \frac{\partial^2 f}{\partial x^2}\right)dt + \sigma \frac{\partial f}{\partial x} dW_t$$
比普通链式法则多了 $\frac{1}{2}\sigma^2 f’'$ 项,因为 $(dW_t)^2 = dt$。
量化应用:推导Black-Scholes公式、理解对冲比率(Delta)、推导各种衍生品定价公式。
Q14:几何布朗运动(GBM)的假设和局限是什么?
标准答案:
GBM模型:
$$dS_t = \mu S_t , dt + \sigma S_t , dW_t$$
解为:
$$S_t = S_0 \exp\left[\left(\mu - \frac{\sigma^2}{2}\right)t + \sigma W_t\right]$$
假设:
- 对数收益率独立同分布且服从正态
- 波动率恒定
- 无跳跃
局限:
- 实际中波动率不恒定(波动率微笑/偏斜)
- 收益率有厚尾(极端事件被低估)
- 存在跳跃(如财报发布、政策突变)
- 收益率存在自相关和波动率聚集
改进模型:随机波动率模型(Heston)、跳跃扩散模型(Merton)、局部波动率模型(Dupire)。
编程(Python / C++)
Python基础与数据处理
Q15:Python中 list、tuple、dict、set 的区别与适用场景?
标准答案:
| 类型 |
可变性 |
有序性 |
查找复杂度 |
量化场景 |
| list |
可变 |
有序 |
O(n) |
时间序列存储、策略信号列表 |
| tuple |
不可变 |
有序 |
O(n) |
作为dict的key(如 (date, ticker))、函数多返回值 |
| dict |
可变 |
有序(3.7+) |
O(1) |
ticker→price映射、参数配置 |
| set |
可变 |
无序 |
O(1) |
股票池去重、集合运算(交集并集求共同持仓) |
面试高频追问:dict的底层实现是哈希表,冲突解决用开放寻址法(CPython);set也是哈希表。
Q16:深拷贝和浅拷贝的区别?在量化中踩坑的例子?
标准答案:
- 浅拷贝(
copy.copy() 或 list.copy()):创建新对象,但内部元素仍引用原对象
- 深拷贝(
copy.deepcopy()):递归复制所有层级的对象
量化踩坑:
# 危险:portfolio_b 和 portfolio_a 共享内部列表
portfolio_a = {'holdings': [{'ticker': 'AAPL', 'weight': 0.5}]}
portfolio_b = portfolio_a.copy() # 浅拷贝
portfolio_b['holdings'][0]['weight'] = 0.3 # portfolio_a 也被修改了!
回测中修改了一个策略的持仓,另一个策略的持仓也被污染——这类bug极其隐蔽。
Q17:Pandas 中 apply、map、vectorized operations 的性能差异?
标准答案:
性能排序(快→慢):NumPy向量化 > Pandas内置方法 > apply > 纯Python循环
# 最快:向量化
df['ret'] = df['close'].pct_change()
# 较快:内置方法
df['log_ret'] = np.log(df['close'] / df['close'].shift(1))
# 慢:apply(每行调用一次Python函数)
df['signal'] = df.apply(lambda row: my_func(row['a'], row['b']), axis=1)
# 最慢:iterrows
for idx, row in df.iterrows(): ...
原则:能向量化就不用apply,能用内置方法就不自己写。处理大型tick数据时,性能差异可达100倍以上。
进阶:对无法向量化的复杂逻辑,考虑用 numba.jit 加速或用 polars 替代Pandas。
Q18:Python GIL是什么?如何在量化中实现真正的并行?
标准答案:
GIL(全局解释器锁)使得CPython中同一时刻只有一个线程执行Python字节码。
影响:CPU密集型任务(如大规模因子计算)无法通过多线程加速。
解决方案:
| 方案 |
适用场景 |
工具 |
| 多进程 |
CPU密集型因子计算 |
multiprocessing, joblib, concurrent.futures.ProcessPoolExecutor |
| 多线程 |
IO密集型(数据下载、API请求) |
threading, asyncio |
| 向量化/C扩展 |
数值计算 |
NumPy, Numba, Cython |
| 分布式计算 |
超大规模回测 |
Dask, Ray, Spark |
Q19:如何避免Pandas中的 “SettingWithCopyWarning”?
标准答案:
这个警告出现在对DataFrame切片的赋值操作中,因为切片可能返回视图(view)而非副本(copy),赋值行为不确定。
# 危险写法:链式索引
df[df['sector'] == 'tech']['weight'] = 0.5 # 可能无效
# 正确写法1:.loc
df.loc[df['sector'] == 'tech', 'weight'] = 0.5
# 正确写法2:显式copy
subset = df[df['sector'] == 'tech'].copy()
subset['weight'] = 0.5
Python进阶
Q20:装饰器(Decorator)的原理?在量化系统中的实际应用?
标准答案:
装饰器本质上是一个接收函数并返回新函数的高阶函数,语法糖 @decorator 等价于 func = decorator(func)。
量化中的实际应用:
import time
import functools
# 1. 计时器:监控因子计算耗时
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__} took {elapsed:.4f}s")
return result
return wrapper
# 2. 缓存:避免重复计算(如日频因子值)
from functools import lru_cache
@lru_cache(maxsize=1024)
def get_factor_exposure(ticker, date):
...
# 3. 重试机制:应对数据源不稳定
def retry(max_retries=3, delay=1):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_retries - 1:
raise
time.sleep(delay * (attempt + 1))
return wrapper
return decorator
Q21:Python中的生成器(Generator)是什么?在量化中的应用?
标准答案:
生成器是使用 yield 关键字的函数,它惰性地产生值,不会一次性将所有结果加载到内存。
量化应用:处理大规模tick数据时避免内存溢出。
def read_ticks(filepath):
"""逐行读取数亿行tick数据,内存占用恒定"""
with open(filepath) as f:
header = f.readline().strip().split(',')
for line in f:
values = line.strip().split(',')
yield dict(zip(header, values))
# 流式处理,内存友好
for tick in read_ticks('huge_tick_data.csv'):
process(tick)
也常用于滚动窗口计算、事件驱动回测引擎的信号生成等。
C++ 基础(QR 延伸阅读)
Q22:C++ 中指针和引用的区别?
标准答案:
| 特性 |
指针 |
引用 |
| 可否为空 |
可以为nullptr |
不可以,必须绑定对象 |
| 可否重新绑定 |
可以指向其他对象 |
不可以,绑定后不变 |
| 语法 |
需要 * 解引用 |
直接使用,语法透明 |
| 内存 |
占用空间(存地址) |
通常被编译器优化为别名 |
量化场景:高频交易系统中传递大型订单簿对象时用 const & 避免拷贝开销;智能指针(shared_ptr, unique_ptr)管理行情数据的生命周期。
Q23:C++ 中的虚函数(virtual function)和多态是什么?
标准答案:
虚函数允许通过基类指针/引用调用派生类的重写方法,实现运行时多态。底层通过虚函数表(vtable)实现。
class Strategy {
public:
virtual void on_market_data(const MarketData& md) = 0; // 纯虚函数
virtual ~Strategy() = default; // 虚析构函数(重要!)
};
class MomentumStrategy : public Strategy {
public:
void on_market_data(const MarketData& md) override {
// 动量策略的具体实现
}
};
面试追问:为什么基类析构函数要声明为virtual?——如果不声明,通过基类指针delete派生类对象时只调用基类析构函数,派生类资源不会释放,造成内存泄漏。
Q24:什么是 move 语义和右值引用?在高频系统中的意义?
标准答案:
C++11引入右值引用(&&)和 std::move,允许"窃取"临时对象的资源而非拷贝。
// 拷贝:O(n) —— 分配新内存,逐元素复制
std::vector<Order> orders2 = orders1;
// 移动:O(1) —— 直接接管 orders1 的内存
std::vector<Order> orders3 = std::move(orders1);
// orders1 此后处于"有效但未定义"状态
高频意义:在微秒级延迟的交易系统中,一次不必要的深拷贝可能就是几微秒的延迟。移动语义在订单传递、行情数据转发等热路径上至关重要。
Q25:C++ STL 容器的选择原则?
标准答案:
| 容器 |
底层结构 |
查找 |
插入/删除 |
量化场景 |
vector |
连续数组 |
O(n) |
尾部O(1) |
时间序列、K线存储 |
deque |
分段连续 |
O(n) |
头尾O(1) |
滑动窗口 |
map/set |
红黑树 |
O(log n) |
O(log n) |
有序订单簿 |
unordered_map/set |
哈希表 |
O(1)均摊 |
O(1)均摊 |
ticker→策略映射 |
priority_queue |
堆 |
取极值O(1) |
插入O(log n) |
事件驱动引擎的事件队列 |
高频考虑:vector 因内存连续、缓存友好,在遍历性能上远优于链表。高频系统中优先使用 vector + 排序,而非 map。
Q26:什么是模板(Template)元编程?在量化中有什么用?
标准答案:
模板允许在编译期生成特化代码,实现零开销抽象。
// 编译期计算阶乘
template<int N>
struct Factorial {
static constexpr int value = N * Factorial<N-1>::value;
};
template<>
struct Factorial<0> {
static constexpr int value = 1;
};
量化应用:
- 表达式模板(Expression Templates):避免临时对象,实现高效矩阵运算(Eigen库的核心技术)
- 策略模式的编译期实现:用模板参数选择不同的执行逻辑,避免虚函数的间接调用开销
- CRTP(Curiously Recurring Template Pattern):静态多态,高频系统中替代虚函数
NumPy / 数值计算
Q27:NumPy 的广播(Broadcasting)机制是什么?
标准答案:
广播允许不同形状的数组进行运算。规则:
- 从最后一个维度开始对齐
- 每个维度要么相同,要么其中一个为1
- 维度为1的那个轴会被"广播"(逻辑复制)
# 对每只股票的收益率减去其均值(截面去均值)
returns = np.random.randn(252, 500) # (252天, 500只股票)
mean_ret = returns.mean(axis=0) # (500,)
demeaned = returns - mean_ret # 广播:(252, 500) - (500,) → (252, 500)
理解广播是写出高效NumPy代码的关键,避免不必要的循环和内存分配。
Q28:如何用NumPy高效实现滚动窗口计算?
标准答案:
# 方法1:stride_tricks(零拷贝,最高效)
from numpy.lib.stride_tricks import sliding_window_view
windows = sliding_window_view(prices, window_shape=20) # (n-19, 20)
rolling_mean = windows.mean(axis=1)
# 方法2:cumsum技巧(O(n),适合求和/均值)
cumsum = np.cumsum(np.insert(prices, 0, 0))
rolling_sum = cumsum[20:] - cumsum[:-20]
rolling_mean = rolling_sum / 20
# 方法3:Pandas(最方便,但慢于纯NumPy)
pd.Series(prices).rolling(20).mean()
在大规模因子计算中,方法1和2比Pandas快3-10倍。
因子与 Alpha 策略
因子投资基础
Q29:什么是因子(Factor)?Alpha 和 Beta 的区别?
标准答案:
因子:能够系统性解释资产收益率截面差异的变量。
Alpha vs Beta:
- Beta(系统性风险暴露):承担市场、规模、价值等公共因子风险获得的补偿,人人可以获取
- Alpha(超额收益):在控制所有已知因子暴露后剩余的收益,来自信息优势或更优的执行
$$r_i - r_f = \alpha_i + \beta_{i,MKT} \cdot (r_{MKT} - r_f) + \beta_{i,SMB} \cdot SMB + \beta_{i,HML} \cdot HML + \epsilon_i$$
如果 $\alpha_i$ 显著大于零,说明存在无法被已知因子解释的超额收益。
核心洞察:今天的Alpha可能是明天的Beta——当一个信号被足够多的人知晓和使用后,它就变成了一个定价因子。
Q30:解释 Fama-French 三因子和五因子模型
标准答案:
三因子模型(1993):
- MKT(市场因子):市场组合超额收益
- SMB(Small Minus Big):小盘股超额收益
- HML(High Minus Low):高B/M(价值股)超额收益
五因子模型(2015)新增:
- RMW(Robust Minus Weak):高盈利vs低盈利
- CMA(Conservative Minus Aggressive):低投资vs高投资
核心贡献:建立了因子投资的分析框架。任何策略的收益都应该用这些因子回归分解——如果Alpha不显著,说明你只是在承担已知风险。
争议:HML在五因子模型中可能是冗余的(被RMW和CMA吸收);动量因子(UMD)未被包含但实证上很强。
Q31:常见的量价因子有哪些?如何构建?
标准答案:
| 因子类别 |
代表因子 |
构建逻辑 |
| 动量 |
12-1月动量 |
过去12个月累计收益(跳过最近1个月) |
| 反转 |
短期反转 |
过去1个月/1周收益取反 |
| 波动率 |
特质波动率 |
回归残差的标准差(IVOL) |
| 流动性 |
Amihud非流动性 |
$|r| / \text{Volume}$ 的均值 |
| 换手率 |
平均换手率 |
日均成交量 / 流通股本 |
| 量价背离 |
价升量缩 |
价格与成交量趋势方向不一致的程度 |
构建流程:
- 原始值计算 → 2. 截面标准化(z-score或排序) → 3. 异常值处理(MAD/Winsorize) → 4. 行业/市值中性化 → 5. 缺失值填充
标准答案:
-
IC:因子值与下期收益率的截面Rank相关系数(Spearman)。衡量因子单期选股能力。
- IC > 0.03 就算不错了
- 更稳健的变体:RankIC、quantile-spread
-
ICIR:IC 均值除以 IC 标准差,衡量因子的稳定性:
$$ICIR = \frac{\overline{IC}}{\sigma_{IC}}$$
-
IR(策略层面):年化超额收益除以年化跟踪误差,衡量策略承担主动风险的效率:
$$IR = \frac{\text{年化超额收益}}{\text{年化跟踪误差}}$$
基本定律(Fundamental Law of Active Management):
$$IR \approx IC \times \sqrt{BR}$$
其中 $BR$(Breadth)是独立决策次数。含义:微弱的IC也可以通过大量独立决策积累出好的IR。
Q33:因子的多重共线性问题如何处理?
标准答案:
当多个因子高度相关时(如EP和BP都是价值因子),回归系数不稳定,单因子测试有效但组合后失效。
处理方法:
- 正交化:对因子做Gram-Schmidt正交化或回归取残差
- PCA降维:提取主成分作为合成因子
- 因子分组:同类因子等权合成为一个复合因子
- 弹性网络(Elastic Net):L1+L2正则化自动处理共线性
- VIF检验:方差膨胀因子 > 10 视为严重共线性
Q34:什么是因子拥挤(Factor Crowding)?如何检测和应对?
标准答案:
因子拥挤:过多资金追逐同一个因子策略,导致因子估值过高、预期收益下降、崩盘风险上升。
检测信号:
- 因子多空组合的估值价差达到历史极端
- 短边借股成本飙升(做空拥挤)
- 同类策略的相关性上升
- 因子回撤加深且恢复变慢
历史案例:2007年8月量化危机——大量统计套利基金同时去杠杆,价值和动量因子在几天内回撤超过20%。
应对:
- 监控因子估值水平和拥挤度指标
- 分散因子来源(基本面+量价+另类数据)
- 动态调整因子暴露
- 保持流动性缓冲
组合优化
Q35:均值-方差优化(MVO)的原理和问题?
标准答案:
原理(Markowitz, 1952):
$$\min_w \frac{1}{2} w^T \Sigma w \quad \text{s.t.} \quad w^T \mu = \mu_{\text{target}}, \quad \mathbf{1}^T w = 1$$
求解得到有效前沿上的最优组合。
实践中的问题:
- 对输入极度敏感:期望收益率微小变化会导致权重剧烈变动(“误差最大化器”)
- 估计风险:期望收益率极难准确估计,协方差矩阵含噪
- 集中持仓:最优解常常极度集中在少数资产上
- 忽略交易成本:理论最优组合频繁调仓不现实
改进方法:
-
Black-Litterman模型(融入主观观点)
-
加入正则化约束(如持仓上下限、换手约束)
-
风险平价(Risk Parity):权重与波动率近似成反比
$$w_i \propto \frac{1}{\sigma_i}$$
-
最小方差组合(不需要估计期望收益率)
-
收缩估计(Ledoit-Wolf)改进协方差矩阵输入
Q36:什么是风险平价(Risk Parity)?和等权有什么区别?
标准答案:
风险平价:使每个资产对组合总风险的贡献相等。
资产 i 的风险贡献:
$$RC_i = w_i \cdot (\Sigma w)_i$$
风险平价要求:
$$RC_1 = RC_2 = \cdots = RC_N = \frac{w^T \Sigma w}{N}$$
vs 等权:等权是 $w_i = 1/N$(权重相等),风险平价是风险贡献相等。在波动率差异大的多资产组合中,等权会让高波动资产主导风险。
典型应用:Bridgewater的All Weather策略。股债配比中,股票波动率远高于债券,等权配比下股票贡献90%+的风险;风险平价下需要大量增配债券(通常加杠杆),使风险贡献均衡。
回测与策略评估
Q37:回测中常见的偏差(Bias)有哪些?
标准答案:
| 偏差 |
描述 |
危害 |
| 前视偏差(Look-ahead Bias) |
使用了回测时刻不可得的未来信息 |
收益虚高,致命 |
| 幸存者偏差(Survivorship Bias) |
只用了存续至今的股票/基金数据 |
高估历史收益 |
| 过拟合偏差 |
参数过度拟合历史数据 |
样本外表现崩塌 |
| 交易成本忽略 |
不考虑滑点、手续费、冲击成本 |
盈利被吃掉 |
| 时间段选择偏差 |
选择有利的回测区间 |
不具代表性 |
如何减轻:
- 严格使用 point-in-time 数据库
- 在回测框架中内置时间戳检查
- 分样本内/样本外/前向验证
- 纸交易(Paper Trading)验证
Q38:常用的策略评估指标有哪些?各自的局限?
标准答案:
| 指标 |
公式/含义 |
局限 |
| 年化收益率 |
$(1+R_{\text{total}})^{252/T} - 1$ |
不反映风险 |
| 夏普比率(Sharpe) |
$\frac{R_p - R_f}{\sigma_p}$ |
假设正态分布,忽略尾部风险 |
| 索提诺比率(Sortino) |
用下行偏差替代标准差 |
更关注下行风险,但对下行的定义依赖阈值 |
| 最大回撤(Max DD) |
峰值到谷底的最大跌幅 |
只描述单次最坏情况 |
| Calmar比率 |
年化收益 / 最大回撤 |
对单一极端事件敏感 |
| 信息比率(IR) |
超额收益 / 跟踪误差 |
依赖于基准选择 |
进阶指标:
Q39:什么是过拟合?如何在策略开发中避免?
标准答案:
过拟合:模型/策略在历史数据上表现优异,但在新数据上表现大幅衰减。本质上是拟合了噪声而非信号。
判断信号:
- 样本内夏普比率远高于样本外
- 策略逻辑过于复杂(大量参数、特殊规则)
- 对参数微调极度敏感
避免方法:
- 数据层面:训练集/验证集/测试集严格分离;使用 Walk-Forward 验证
- 模型层面:限制参数数量;用简单模型作为基线
- 统计层面:对多重测试做校正(Deflated Sharpe Ratio)
- 经济学层面:策略逻辑必须有合理的经济学解释
- 稳健性检验:更换时间窗口、市场、参数范围看策略是否稳定
Marcos López de Prado 的提醒:回测更适合承担验证职责,研究本身应先来自假设与机制。
Q40:什么是交易成本模型?如何估计市场冲击成本?
标准答案:
交易成本构成:
- 显性成本:佣金、印花税、交易所费用
- 隐性成本:买卖价差(bid-ask spread)、市场冲击(market impact)、时机成本
市场冲击模型:
Almgren-Chriss模型(经典):
$$\text{Impact} = \sigma \cdot \gamma \cdot \left(\frac{V}{ADV}\right)^{\delta}$$
其中 V 是订单量,ADV 是日均成交量,γ 和 δ 是经验参数。
平方根模型(业界常用简化版):
$$\text{Impact} \approx \sigma \cdot \sqrt{\frac{V}{ADV}}$$
重要性:高换手策略(如短期反转)的收益可能被冲击成本完全吃掉。策略开发时必须将冲击成本纳入回测。
机器学习 / 深度学
README 内容过长,已截取部分内容。完整内容请前往 GitHub 仓库查看。
评论