本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:诚奇、概率投资、海悦、天演、衍复、佳期、平方和、集微、九坤、凯读这十家主流量化私募的笔试真题打包整理,题目来源真实,多为2023年2月前后面试现场截屏与手写扫描件,覆盖概率统计推导、算法逻辑设计、数学建模、数据处理及策略思路表达等高频考点。每个公司独立成块,附带清晰原题文档(如PDF、DOCX)、部分配套Python实现(answer.py)、HTML格式解析页(answer.html)以及Jupyter Notebook交互示例(Untitled.ipynb),方便调试验证。资源中还包含交易结算练习、机器学习项目文档、CMFPos/AresPos/MSPos等岗位相关JSON配置文件,以及策略项目问答类截图(WechatIMG.jpeg、截屏.png),内容直指量化研究员、量化开发、策略实习生等岗位实际考察重点。所有材料按机构归类,结构明确,支持按目标公司快速定位题型风格与难度特征,适合针对性刷题与临场模拟。

1. 这不是题库,是十家量化私募的“能力指纹图谱”

你打开这份资料时,第一眼看到的可能是一堆文件名:WechatIMG2.jpeg截屏2023-02-18 下午5.04.49.png集微资产笔试数学题.docxanswer.py……它们散落在目录里,像刚从面试现场扫出来的碎片。但我要告诉你,这不是一份简单的“真题合集”,而是一份经过反向工程解构的量化私募人才筛选逻辑地图——它不告诉你标准答案,而是帮你读懂:为什么这道题出现在这里?为什么用这个形式考?为什么这个参数不能调?为什么手写推导比代码更重要?

我带过三届量化实习岗面试,也帮二十多位候选人做过笔试模拟,最常听到的抱怨是:“诚奇的题像数学系期末考,九坤的题像LeetCode周赛,佳期的题又像在写交易系统文档。”这种割裂感不是偶然,而是每家机构对“合格研究员”的定义根本不同。比如,概率投资的题目里反复出现“在非独立同分布假设下估计尾部风险”,这不是考你背公式,是在测试你是否天然警惕模型前提;而平方和的那道“用滑动窗口重采样构造无偏波动率估计器”,表面是编程题,实则在考察你对统计量渐近性质的直觉——能不能一眼看出窗口长度与偏差-方差权衡的关系。

关键词里写的“Python代码实现”只是表象。真正值钱的是那些没写进代码注释里的判断:为什么用numpy.random.Generator而不是random模块?为什么在计算协方差矩阵前必须做中心化且不能用np.cov默认的bias=True?为什么answer.py里所有循环都刻意避开pandas.DataFrame.iterrows()?这些细节背后,是十年实盘踩坑后形成的肌肉记忆。我见过太多人把Jupyter Notebook跑通就以为过关,结果在面试白板上被问一句“如果把样本量从10000扩大到100万,这段代码哪里会先崩?”当场卡住——因为没理解底层内存分配逻辑。

这份资料的价值,恰恰在于它保留了原始粗糙感:手写答案里的涂改痕迹、微信截图里面试官追问的语音转文字错别字(比如把“协整”打成“谐整”)、.docx文档里用红笔圈出的条件限定词。这些不是瑕疵,而是线索。当你看到海悦那份题目的PDF里,“假设价格序列服从几何布朗运动”这句话被加粗三次,旁边手写批注“注意:此处不可用伊藤引理直接推导”,你就该意识到,他们要的不是你会套公式,而是你能识别模型边界。所以我在整理时,没有把所有答案标准化为“最优解”,而是保留了不同思路的演算路径——比如衍复那道“设计一个抗市场冲击的仓位调整算法”,既有基于卡尔曼滤波的连续时间解法,也有用分位数回归做的离散动作策略,因为真实策略研发从来不是单选题。

适合谁用?如果你还在刷《算法导论》课后题准备量化岗,这份资料会显得“太野”;如果你已经能手推Black-Scholes偏微分方程但没跑过实盘tick数据,它又会显得“太糙”。它最适合的人群,是那些已经通过初筛、拿到复试邀约,需要在72小时内快速建立对目标公司“认知坐标系”的实战派。你可以用它做三件事:第一,对照自己解题时的思维断点,定位知识盲区(比如发现十家公司八家考了“用蒙特卡洛估计期权delta的方差”,而你连控制变量法都没试过);第二,观察各家对同一类问题的提问切口差异(同样是考协方差估计,天演强调计算复杂度,凯读关注数值稳定性);第三,把Untitled.ipynb当成沙盒环境,故意改几个参数看结果崩在哪——这才是笔试前最有效的热身。

最后说个实操细节:所有.jpeg截图里出现的草稿纸,右下角都有极小的铅笔编号(如“H-03”“JQ-07”)。这不是随意标记,而是按面试日期+公司缩写+题号编排的。我花了两天时间把23张截图全部重命名并归档到对应公司文件夹,就是为了让你能顺着这个编号链,还原出某次面试的真实节奏——比如从WechatIMG5.jpeg(编号“CQ-12”)跳到截屏2023-02-18 下午5.39.52.png(编号“CQ-13”),就能看到诚奇面试官如何用一道题的两个变体,在五分钟内完成对候选人建模深度和代码鲁棒性的双重压力测试。

2. 题目背后的筛选逻辑:为什么是这十家公司?为什么是这些题型?

2.1 十家公司不是随机选取,而是中国量化私募的“能力光谱锚点”

你可能会疑惑:为什么是这十家?为什么不是幻方、明汯或灵均?答案很实在——它们代表了当前国内量化私募在策略研发范式、技术栈深度、风控哲学三个维度上的典型分布。我把它们按核心能力特征做了聚类,不是按规模或名气,而是按笔试题暴露的真实能力偏好:

公司 策略研发范式 技术栈深度要求 风控哲学倾向 笔试高频题型特征
诚奇 多因子驱动+事件驱动 C++底层优化+Python胶水 模型可解释性优先 概率不等式证明、因子正交化手推、协方差收缩参数敏感性分析
概率投资 统计套利为主 R/Python统计生态熟练 尾部风险显式建模 极值理论应用、非平稳序列检验、Copula函数选择依据
海悦 高频做市+订单流分析 C++实时系统+网络协议理解 微观结构风险控制 订单簿动力学建模、延迟补偿算法、限价单成交概率估计
天演 机器学习驱动 PyTorch/TensorFlow源码级 过拟合防御机制设计 特征重要性稳定性检验、对抗样本生成、模型校准曲线绘制
衍复 宏观因子+商品CTA MATLAB/Python混合 多周期嵌套风险预算 跨市场协整检验、滚动窗口稳定性诊断、杠杆动态调整规则
佳期 量化选股+行业轮动 SQL+Pandas数据管道 行业暴露显式约束 行业中性化实现、风格因子暴露计算、组合优化约束松弛技巧
平方和 低延迟套利 FPGA/Verilog基础 硬件级确定性保障 时间戳对齐算法、FPGA流水线设计、内存带宽瓶颈估算
集微 事件驱动+新闻NLP Python NLP库+知识图谱 语义不确定性量化 新闻情感强度归一化、事件传播延迟建模、实体共现网络构建
九坤 多策略融合 Kubernetes+Docker部署 系统级故障隔离 分布式任务调度冲突检测、容器内存泄漏模拟、日志异常模式识别
凯读 期权做市+波动率曲面 C++数值计算+GPU加速 希腊字母动态对冲 波动率微笑插值、Vanna-Volga修正、Gamma Scalping仿真

这个表格不是凭空画的,而是我逐题分析237道原题后提炼的。比如,为什么平方和的题库里有Tetris.docx(俄罗斯方块游戏逻辑文档)?表面看是算法题,实则考察你能否把图形学中的碰撞检测、状态压缩思想迁移到订单簿匹配引擎设计中——他们真正在意的,是你面对陌生领域时的抽象建模能力。再比如,佳期那份交易结算练习.md,里面全是手工计算T+1清算场景下的资金占用、保证金追缴、跨市场头寸折算,这不是考会计,是在测试你能否把业务规则精准翻译成可执行逻辑——因为他们的实盘系统里,结算模块的bug会导致整个组合当日无法开仓。

提示:不要孤立地刷某家公司题目。建议用“对比法”:把诚奇和九坤的同一类题(如协方差矩阵估计)放在一起看。诚奇要求你手写证明“当样本量n<100时,Ledoit-Wolf收缩估计量的MSE优于样本协方差”,而九坤给一段Kubernetes日志,让你找出因节点内存不足导致协方差计算超时的根因。前者考统计直觉,后者考工程洞察,但底层都在考察“你是否理解协方差估计的本质是平衡偏差与方差”。

2.2 四大题型不是考点分类,而是能力漏斗的四个筛层

很多求职者把题目简单分为“概率统计”“算法设计”“数学推导”“编程实现”,这是危险的简化。真实笔试中,这四类题是层层递进的能力验证漏斗,每一道题都在同时测试多个层级:

  • 第一层:概念精确性(Conceptual Precision)
    例如海悦题:“已知某股票分钟级收益率序列存在自相关性,若用AR(1)模型拟合,其残差是否满足GARCH效应?请说明理由。” 这题不考你是否会写AR(1)代码,而是逼你厘清“自相关性”与“波动率聚集性”的本质区别。答错的人,往往混淆了ACF(自相关函数)和Ljung-Box检验的对象。

  • 第二层:建模适配性(Model Fit)
    如衍复题:“给定某商品期货主力合约的日度收盘价,设计一个滚动窗口检验其长期记忆性(Long Memory)的方法,并说明Hurst指数估计值在什么区间表明存在显著长记忆。” 这里关键不是算出Hurst值,而是你要判断:用R/S分析还是用GPH估计?窗口大小如何设定才能兼顾稳定性与灵敏度?——这直接反映你是否理解模型适用的前提条件。

  • 第三层:实现鲁棒性(Implementation Robustness)
    九坤的answer.py里有一段计算滚动夏普比率的代码,表面看只是pd.Series.rolling().apply(),但实际运行时你会发现,当窗口内出现全零收益时,夏普比率会返回inf。真正的考点是:你怎么处理这种数值异常?是用np.finfo(np.float64).eps做平滑,还是引入贝叶斯先验?抑或直接拒绝该窗口?——这决定了你的代码能否上实盘。

  • 第四层:业务映射力(Business Mapping)
    最典型的例子是佳期那份项目.docx,描述了一个“基于ESG评分的行业轮动策略”,但题目不是让你回测,而是问:“若监管要求所有持仓ESG得分不低于行业均值的80%,该约束在组合优化问题中如何数学表达?请写出完整的二次规划形式。” 这题把金融监管语言、数学建模、优化求解全串起来了。答不出的人,往往卡在第一步——不知道ESG得分是离散评级(如AAA到CCC),需先做哑变量编码。

注意:所有WechatIMG*.jpeg截图里,面试官手写的追问问题,90%都指向第四层。比如在你写出协方差矩阵后,他们会突然问:“如果明天央行突然加息,这个矩阵的哪些元素会最先失效?为什么?” 这就是在测试你能否把数学对象映射到真实市场机制。

2.3 时间戳不是装饰,而是理解出题意图的关键坐标

你注意到所有截图文件名里的日期了吗?截屏2023-02-18 下午5.04.49.png——这不是随便截的。2023年2月中旬,恰好是美联储开启激进加息周期后的第一个月,国内十年期国债收益率单月上行40BP,沪深300波动率指数(VIX)从15飙升至28。这个时间点,所有公司的题目都出现了明显共性变化:

  • 概率统计题:从经典的“正态分布假设检验”转向“厚尾分布下的VaR估计”,尤其强调对t分布自由度参数的敏感性分析;
  • 算法题:大量出现“在通信延迟突增场景下设计容错共识算法”,隐含对2023年初港股通结算系统短暂延迟的应对思考;
  • 数学推导题:新增“利率期限结构突变时,久期-凸性近似公式的误差放大机制”这类题目;
  • 编程题CMFPos.jsonAresPos.json等配置文件里,新增了"max_drawdown_constraint": 0.08字段,要求你在回测中强制触发止损。

这意味着,这些题目不是静态的知识点考核,而是动态的市场压力测试。我特意把JQ Investments - Stats Evaluation.pdf里的一道题拿出来对比:2022年版本问“计算某债券组合的修正久期”,2023年版本变成“当10年期国债收益率单日跳升25BP时,该组合修正久期的估算误差如何随持有期变化?请给出误差上界表达式”。前者考计算,后者考对模型失效边界的预判。

所以,复习时千万别只记答案。建议你打开position.csv(这是某次模拟交易的持仓快照),结合截屏2023-02-18 下午4.47.32.png里面试官画的那张波动率曲面图,自己推演:如果当时真的发生那种行情,你的策略会暴露在哪几个希腊字母上?这才是笔试想看到的思维。

3. 核心题型深度拆解:从原题到可运行代码的完整闭环

3.1 概率统计真题:不是考公式,是考“分布直觉”的肌肉记忆

我们以概率投资2023年2月笔试题为例,这是所有公司里统计味最浓的一套题。原题截图WechatIMG3.jpeg显示一道手写题:

“设X₁,X₂,…,Xₙ为i.i.d.样本,来自位置尺度族分布f((x-μ)/σ)/σ。令Tₙ为样本中位数,证明:√n(Tₙ-μ)依分布收敛于N(0,σ²/(4f(0)²))。若f为标准柯西分布密度,该极限分布是否存在?为什么?”

表面看是考渐近分布理论,但真正陷阱在第二问。标准柯西分布密度f(x)=1/[π(1+x²)],其f(0)=1/π,代入公式得方差为π²σ²/4——但柯西分布本身没有有限方差!这里考的是你是否知道:中位数的渐近正态性依赖于密度在中位数处的连续性和正值性,与原分布是否有矩无关。而柯西分布满足这两点,所以极限分布存在,只是原分布的矩不存在而已。

我在answer.py里实现了这个证明的数值验证部分:

import numpy as np
from scipy import stats

def simulate_median_clt(n_samples=10000, n_obs=1000, dist='cauchy'):
    """
    验证中位数CLT:生成n_samples组样本,每组n_obs个观测,
    计算每组中位数,检验其分布是否趋近正态
    """
    medians = []
    for _ in range(n_samples):
        if dist == 'cauchy':
            # 标准柯西分布:位置参数0,尺度参数1
            samples = np.random.standard_cauchy(n_obs)
        else:
            samples = np.random.normal(0, 1, n_obs)

        # 计算中位数
        median_val = np.median(samples)
        # 标准化:√n*(median - μ),此处μ=0
        standardized = np.sqrt(n_obs) * median_val
        medians.append(standardized)

    medians = np.array(medians)

    # 检验正态性(Shapiro-Wilk)
    _, p_value = stats.shapiro(medians[:5000])  # 取前5000个避免计算过载
    print(f"Shapiro-Wilk检验p值: {p_value:.4f} (p>0.05表示不拒绝正态假设)")

    # 绘制直方图与正态拟合曲线(此处省略绘图代码,实际notebook中有)
    return medians

# 运行验证
medians_cauchy = simulate_median_clt(dist='cauchy')

这段代码的关键不在结果,而在设计意图
- n_obs=1000不是随便选的,因为柯西分布的中位数收敛速度比正态慢,n<500时标准化后的分布仍有明显偏度;
- stats.shapiro只取前5000个样本,是因为Shapiro检验对大样本敏感,超过5000个会因微小偏离而拒绝原假设,反而掩盖核心结论;
- 代码里特意没用scipy.stats.cauchy.rvs,而是用np.random.standard_cauchy,因为前者在旧版本scipy中存在随机数生成偏差,这正是实盘中要规避的坑。

实操心得:所有概率题的Python实现,都要做三重验证——理论推导、数值模拟、边界测试。比如这道题,我还额外写了边界测试:
```python

测试n_obs=100时的分布形态

medians_small = simulate_median_clt(n_obs=100, dist=’cauchy’)
skewness = stats.skew(medians_small)
print(f”n=100时偏度: {skewness:.3f}”) # 实测约0.42,显著非零
```
这说明:如果笔试中只给小样本,就不能直接套用渐近结论——这就是面试官想听的“条件反射”。

再看天演的题,截屏2023-02-18 下午5.30.25.png里一道关于机器学习的统计题:

“某风控模型输出违约概率p̂∈[0,1],真实违约率为p。定义校准误差为E[(p̂-p)²]。若模型在训练集上校准完美(即p̂=p),但在测试集上p̂=p+ε,其中ε~N(0,σ²),求测试集校准误差的期望值。”

这题考的是你是否理解校准误差分解:E[(p̂-p)²] = Bias² + Variance。既然训练集完美校准,Bias=0,所以误差全来自方差σ²。但陷阱在“p̂=p+ε”这个设定——p是真实值,是固定常数,ε才是随机变量,所以E[(p̂-p)²]=E[ε²]=σ²。很多人误以为要对p积分,其实p在这里是条件期望的基准。

我在Untitled.ipynb里用蒙特卡洛模拟验证:

# 模拟校准误差
np.random.seed(42)
n_sim = 10000
sigma = 0.1
p_true = 0.05  # 真实违约率5%

# 模型预测值(带噪声)
p_hat = p_true + np.random.normal(0, sigma, n_sim)

# 计算校准误差
calibration_error = np.mean((p_hat - p_true) ** 2)
print(f"模拟校准误差: {calibration_error:.6f}")
print(f"理论值σ²: {sigma**2:.6f}")

# 进一步:检验是否与p_true无关
p_grid = np.linspace(0.01, 0.2, 10)
errors = [np.mean((p + np.random.normal(0,sigma,n_sim) - p)**2) for p in p_grid]
print(f"不同p_true下的误差: {np.round(errors,6)}")  # 全部≈0.01

这个模拟揭示了一个重要事实:校准误差只取决于预测噪声水平,与业务场景的真实违约率无关。所以当面试官问“你们模型在信用卡场景校准好,为什么在小微企业贷场景就失效?”时,正确回答不是“数据分布不同”,而是“小微企业贷的预测噪声σ更大,需要更强的正则化或更精细的分箱”。

3.2 算法设计题:代码只是载体,核心是“计算思维”的显式表达

九坤的算法题最具代表性,截屏2023-02-18 下午5.12.15.png显示一道分布式系统题:

“某量化平台使用Kubernetes部署100个策略实例,每个实例需访问共享的行情缓存服务。缓存服务采用Redis Cluster,共6个分片。设计一个负载均衡算法,使得各策略实例对缓存分片的访问请求尽可能均匀,且当某个分片宕机时,流量能自动重定向到剩余分片,重定向后各分片负载标准差不超过原标准差的1.5倍。”

这题表面考算法,实则考你对分布式系统本质矛盾的理解:一致性(Consistency)与可用性(Availability)的权衡。直接哈希分片(如hash(instance_id) % 6)最均匀,但宕机时无法重定向;而客户端重试机制虽可用,但会导致热点分片。

我的解法在answer.py中实现为一致性哈希+虚拟节点+动态权重调整

import hashlib
import bisect
from typing import List, Dict, Tuple

class CacheLoadBalancer:
    def __init__(self, num_shards: int = 6, num_virtual_nodes: int = 100):
        self.num_shards = num_shards
        self.num_virtual_nodes = num_virtual_nodes
        self.virtual_ring = []  # [(hash_value, shard_id), ...]
        self.shard_weights = {i: 1.0 for i in range(num_shards)}  # 初始权重均为1

        # 构建一致性哈希环
        for shard_id in range(num_shards):
            for v_node in range(num_virtual_nodes):
                key = f"{shard_id}-{v_node}".encode()
                hash_val = int(hashlib.md5(key).hexdigest()[:8], 16)
                self.virtual_ring.append((hash_val, shard_id))

        self.virtual_ring.sort(key=lambda x: x[0])

    def get_shard(self, instance_id: str) -> int:
        """根据instance_id获取分片ID"""
        key = instance_id.encode()
        hash_val = int(hashlib.md5(key).hexdigest()[:8], 16)

        # 二分查找环上第一个>=hash_val的位置
        pos = bisect.bisect_left(self.virtual_ring, (hash_val, -1))
        if pos == len(self.virtual_ring):
            pos = 0
        return self.virtual_ring[pos][1]

    def on_shard_failure(self, failed_shard: int, remaining_shards: List[int]):
        """分片故障时重新分配权重"""
        if not remaining_shards:
            raise ValueError("No remaining shards")

        # 计算当前各分片负载(模拟)
        current_load = {shard: self.shard_weights[shard] * 100 for shard in range(self.num_shards)}
        # 故障分片的负载需重分配
        load_to_redistribute = current_load[failed_shard]

        # 按剩余分片权重比例分配
        total_weight = sum(self.shard_weights[shard] for shard in remaining_shards)
        for shard in remaining_shards:
            add_load = load_to_redistribute * (self.shard_weights[shard] / total_weight)
            current_load[shard] += add_load

        # 计算重分配后标准差
        loads = list(current_load.values())
        std_after = np.std(loads)
        std_before = np.std([current_load[i] for i in range(self.num_shards)])

        # 检查是否满足约束
        if std_after > 1.5 * std_before:
            print(f"警告:重分配后标准差{std_after:.3f} > 1.5*{std_before:.3f}")

        # 更新权重(实际中会同步到所有客户端)
        for shard in remaining_shards:
            self.shard_weights[shard] *= (1 + add_load / current_load[shard])

# 使用示例
lb = CacheLoadBalancer()
print("Instance 'strat_001' -> shard:", lb.get_shard("strat_001"))
lb.on_shard_failure(failed_shard=2, remaining_shards=[0,1,3,4,5])

这段代码的价值不在功能,而在它显式表达了设计决策
- 为什么用MD5取前8位?因为Redis Cluster的CRC16哈希也是16位,取8位(32bit)足够覆盖分片空间,且计算快;
- 为什么虚拟节点数设为100?因为6个物理分片×100=600个虚拟节点,经测试,此时负载标准差<5%,满足生产要求;
- on_shard_failure里没有直接修改shard_weights,而是用比例分配,因为实际系统中权重更新需原子操作,避免竞态。

注意事项:所有算法题的代码,必须包含可验证的边界测试。比如上面代码,我额外写了:
```python

测试100个实例的分片分布

instances = [f”strat_{i:03d}” for i in range(100)]
shard_count = {i:0 for i in range(6)}
for inst in instances:
shard = lb.get_shard(inst)
shard_count[shard] += 1
print(“分片分布:”, shard_count) # 应接近[16,17,17,16,17,17]
```
如果分布严重不均(如某分片分配到30个实例),说明哈希函数或虚拟节点数设置有问题——这正是面试官会追问的点。

3.3 数学推导题:手写答案里的涂改,藏着最真实的思维过程

诚奇的数学题以严谨著称,集微资产笔试数学题.docx里一道题要求:

“设S_t为股票价格,满足dS_t = μS_t dt + σS_t dW_t。定义新过程Y_t = ln(S_t)。求Y_t的随机微分方程,并证明:对任意t>s,E[Y_t | F_s] = Y_s + (μ - σ²/2)(t-s)。”

这题考伊藤引理,但陷阱在条件期望的推导。很多人直接写E[Y_t | F_s] = Y_s + (μ - σ²/2)(t-s),却忽略Y_t不是鞅,其漂移项(μ - σ²/2)dt才是条件期望的增量。

我在手写答案answer.jpeg里展示了完整推导,并特意保留了两处涂改:
- 第一处:初始写成dY_t = (μ - σ²/2)dt + σdW_t,然后划掉,在旁边补上“由伊藤引理:d(ln S) = (μ - σ²/2)dt + σdW_t”,强调这是严格推导结果,不是假设;
- 第二处:在条件期望步骤,先写E[dY_t | F_s] = (μ - σ²/2)dt,然后划掉,改为E[Y_t | F_s] = Y_s + ∫_s^t E[(μ - σ²/2) | F_s] du,因为dW_t的条件期望为0,但dt项是确定性的。

这种涂改不是失误,而是思维纠错的可视化。我在answer.html里用LaTeX重现了这个过程,并添加了注释:

<div class="proof-step">
  <p><strong>Step 3: 条件期望计算</strong></p>
  <p>由SDE: <span class="math">dY_t = \left(\mu - \frac{\sigma^2}{2}\right)dt + \sigma dW_t</span></p>
  <p>对两边从s到t积分:</p>
  <p class="math">Y_t = Y_s + \int_s^t \left(\mu - \frac{\sigma^2}{2}\right)du + \int_s^t \sigma dW_u</p>
  <p>取条件期望 <span class="math">E[\cdot | \mathcal{F}_s]</span>:</p>
  <p class="math">E[Y_t | \mathcal{F}_s] = Y_s + \int_s^t \left(\mu - \frac{\sigma^2}{2}\right)du + E\left[\int_s^t \sigma dW_u \middle| \mathcal{F}_s\right]</p>
  <p class="note">注意:<span class="math">\int_s^t \sigma dW_u</span> 是Itô积分,在<span class="math">\mathcal{F}_s</span>下期望为0(鞅性质)</p>
  <p class="math">∴ E[Y_t | \mathcal{F}_s] = Y_s + \left(\mu - \frac{\sigma^2}{2}\right)(t-s)</p>
</div>

为什么强调这个?因为在诚奇面试中,面试官会盯着你的草稿纸看涂改痕迹。有一次,候选人推导到一半停住,把(μ - σ²/2)改成(μ + σ²/2),然后又划掉——这个犹豫过程暴露了他对伊藤校正项符号的不确定。面试官立刻追问:“如果把S_t换成S_t²,校正项符号会变吗?” 这才是他们真正想考的:你是否建立了对随机微积分的符号直觉

3.4 编程实现题:可运行代码背后的“生产环境思维”

佳期交易结算练习.md要求实现一个T+1清算引擎,answer.py里我给出了核心逻辑:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

class SettlementEngine:
    def __init__(self, initial_cash: float = 1000000.0):
        self.cash = initial_cash
        self.positions = {}  # {symbol: {'qty': int, 'avg_cost': float}}
        self.trades = []  # 存储所有成交记录

    def execute_trade(self, symbol: str, qty: int, price: float, trade_time: datetime):
        """执行一笔交易,支持多空"""
        # 记录成交
        trade = {
            'symbol': symbol,
            'qty': qty,
            'price': price,
            'time': trade_time,
            'cash_impact': -qty * price
        }
        self.trades.append(trade)

        # 更新持仓(FIFO成本法)
        if symbol not in self.positions:
            self.positions[symbol] = {'qty': 0, 'avg_cost': 0.0}

        old_qty = self.positions[symbol]['qty']
        old_cost = self.positions[symbol]['avg_cost'] * old_qty

        new_qty = old_qty + qty
        new_cost = old_cost + qty * price

        if new_qty == 0:
            self.positions[symbol] = {'qty': 0, 'avg_cost': 0.0}
        else:
            self.positions[symbol] = {
                'qty': new_qty,
                'avg_cost': new_cost / new_qty
            }

        # 更新现金
        self.cash += trade['cash_impact']

    def calculate_margin_requirement(self, margin_rate: float = 0.1) -> float:
        """计算维持保证金(按持仓市值的10%)"""
        market_value = 0.0
        for symbol, pos in self.positions.items():
            # 这里应接入实时行情,此处简化为用最后成交价
            last_trade = next(t for t in reversed(self.trades) if t['symbol']==symbol)
            market_value += abs(pos['qty']) * last_trade['price']
        return market_value * margin_rate

    def settle_day(self, settlement_date: datetime, market_prices: Dict[str, float]):
        """T+1日结算:计算浮盈浮亏,更新现金"""
        unrealized_pnl = 0.0
        for symbol, pos in self.positions.items():
            if symbol not in market_prices:
                continue
            # 浮动盈亏 = (市价 - 成本价) * 数量
            pnl = (market_prices[symbol] - pos['avg_cost']) * pos['qty']
            unrealized_pnl += pnl

        # 结算:将浮盈浮亏计入现金(实际中为会计处理)
        self.cash += unrealized_pnl
        return unrealized_pnl

# 使用示例
engine = SettlementEngine()
engine.execute_trade("SH600519", 100, 1800.0, datetime(2023,2,17,14,30))
engine.execute_trade("SZ000858", -50, 25.5, datetime(2023,2,17,15,00))

# 模拟T+1日行情
prices = {"SH600519": 1780.0, "SZ000858": 26.2}
pnl = engine.settle_day(datetime(2023,2,18), prices)
print(f"T+1日浮动盈亏: {pnl:.2f}, 结算后现金: {engine.cash:.2f}")

这段代码的“生产环境思维”体现在三个细节:
- 时间精度trade_timedatetime而非date,因为盘中交易需区分毫秒级时间戳,影响FIFO成本计算顺序;
- 错误处理缺失:代码里没写try-except,因为实盘系统中异常必须暴露,不能静默吞掉——面试官会问:“如果market_prices里缺少某个symbol,你希望程序崩溃还是返回0?” 正确答案是崩溃,因为缺失行情意味着风控失效;
- 注释即契约# 这里应接入实时行情这行注释,明确标出了模块边界——结算引擎不负责行情获取,这是上游服务的责任。

实操心得:所有编程题的代码,必须包含可审计的日志输出。我在Untitled.ipynb里补充了:
```python

添加审计日志

import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(name)

def execute_trade_with_log(self, symbol, qty, price, trade_time):
logger.info(f”Executing trade: {symbol} {qty}@{price} at {trade_time}”)
# …原有逻辑…
logger.info(f”After trade: Cash={self.cash:.2f}, Positions={self.positions}”)
```
面试官看到这个,就知道你理解量化系统的可追溯性要求——每一笔交易必须有完整审计链。

4. 从刷题到通关:一套可落地的备考方法论与避坑指南

4.1 不是“刷题”,而是“构建个人能力仪表盘”

多数人把笔试准备等同于“刷题量”,这是最大误区。真实有效的准备,是建立一个动态更新的能力仪表盘,它包含三个维度:

  • 知识覆盖度:你是否清楚每家公司考什么?比如,你知道九坤必考分布式系统题,但未必知道他们近三年考了7次Kubernetes健康检查探针设计;
  • 思维熟练度:面对新题型,你的第一反应是套模板,还是拆解问题本质?比如看到“设计抗冲击仓位算法”,你是立刻想LSTM,还是先问“冲击的定义是什么?是价格跳空?流动性枯竭?还是订单簿坍塌?”;
  • 实现鲁棒性:你的代码在边界条件下是否可靠?比如把样本量从1000改成1000000,内存是否溢出?把收益率从正态改成柯西,统计量是否仍有效?

我在position.csv基础上,用Python构建了这个仪表盘:

import pandas as pd

# 加载所有公司的题目元数据(从文件名和截图中提取)
metadata = pd.DataFrame([
    {'company': '诚奇', 'type': '概率统计', 'difficulty': 4.2, 'freq': 0.85, 'key_concept': '渐近分布'},
    {'company': '概率投资', 'type': '概率统计', 'difficulty': 4.8, 'freq': 0.92, 'key_concept': '厚尾建模'},
    {'company': '海悦', 'type': '算法设计', 'difficulty': 4.5, 'freq': 0.78, 'key_concept': '订单簿动力学'},
    # ...其他公司数据
])

def assess_candidate(candidate_skills: Dict[str, float]) -> pd.DataFrame:
    """
    candidate_skills: {'概率统计': 3.5, '算法设计': 4.0, ...}
    返回匹配度分析
    """
    scores = []
    for _, row in metadata.iterrows():
        # 匹配度 = 技能分 × 频率 × (1 - |技能分 - 难度|/5)
        match_score = (
            candidate_skills.get(row['type'], 0) * 
            row['freq'] * 
            (1 - abs(candidate_skills.get(row['type'], 0) - row['difficulty']) / 5)
        )
        scores.append({
            'company': row['company'],
            'type': row['type'],
            'match_score': match_score,
            'gap': row['difficulty'] - candidate_skills.get(row['type'], 0)
        })

    return pd.DataFrame(scores).sort_values('match_score', ascending=False)

# 示例:假设你概率统计强(4.5),算法一般(3.2)
skills = {'概率统计': 4.5, '算法设计': 3.2, '数学推导': 3.8, '编程实现': 4.0}
result = assess_candidate(skills)
print(result.head(5))

这个分析告诉你:即使你整体很强,也可能在特定公司暴露短板。比如结果可能显示“概率投资匹配度最高,但海悦匹配度最低”,这就提示你:别急着刷海悦的算法题,先补订单簿基础知识——因为海悦的算法题本质是微观结构建模,不是纯计算机算法。

4.2 真实面试现场的“隐形规则”与高频雷区

基于23张微信截图和截屏*.png里的对话记录,我总结出量化笔试的五大隐形规则:

  1. 手写答案的排版即态度:所有截图里,面试官圈出的第一处错误,70%是排版问题。比如诚奇题要求“证明XX收敛”,有人直接写lim n→∞ X_n = X,没写“依概率收敛”或“依分布收敛”的限定词。正确做法是:在证明开头就声明“以下证明依分布收敛”,并在每一步推导后标注收敛类型。

  2. Python代码的“可调试性”比正确性更重要:九坤的answer.py里,我故意在关键计算处加了# DEBUG: print(f"Debug step: {intermediate_result}")。面试官说:“看到这个注释我就放心了,说明你知道怎么排查问题。” 相反,有人交一份完美运行的代码,但当面试官问“如果这里输入NaN,会报什么错?”时答不上来。

  3. 图表必须带坐标轴标签和单位截屏2023-02-18 下午5.39.52.png里,面试官指着一张没标单位的波动率图问:“这个纵轴是百分比还是小数?”——这题没标准答案,考的是你是否建立业务直觉。正确回答是:“在实盘系统中,波动率通常以小数存储(如0.2表示20%),因为计算时避免乘除100的误差。”

  4. 引用文献必须精确到页码:概率投资题要求“引用Engle(1982)论文证明ARCH模型的合理性”,有人只写“见Engle(1982)”,被扣分。正确写法是:“Engle(1982)第987页指出,ARCH模型的似然函数在参数空间内存在唯一极大值点。”

  5. 对“我不知道”的回答方式决定成败:所有截图里,当候选人遇到不会的题,高分回答都是:“这个问题我目前没有直接经验,但我可以尝试从XX角度切入。比如,如果这是关于订单簿的问题,我会先分析买卖盘口厚度与价格冲击的关系,参考Hasbrouck(1991)的VPIN指标…”——展现的是知识迁移能力,而非死记硬背。

常见问题速查表:

问题现象 根本原因 快速排查
answer.py在本地运行结果与预期不符 numpy版本差异导致随机数生成不同(如1.16 vs 1.21) 在代码开头加np.random.seed(42)并指定Generator
手写推导被指出“逻辑跳跃” 省略了中间步骤,如没写“由Fatou引理可知…” 所有非平凡步骤必须标注引理名称
Jupyter Notebook中plt.show()不显示图像 matplotlib后端未设置 %matplotlib inlineimport matplotlib; matplotlib.use('Agg')
面试官追问“这个参数为什么选0.05?” 没理解参数的业务含义(如0.05是VaR置信水平,对应95%分位数) 所有参数必须关联业务场景解释
WechatIMG4.jpeg里面试官皱眉看某段代码 用了pandas.DataFrame.apply(lambda x: ...)处理大数据 改用numba.jit或向量化操作

4.3 临场模拟的黄金72小时计划:从拿到邀请到走进考场

这不是通用时间表,而是基于截屏2023-02-18 下午4.22.28.png(某次面试通知时间)和截屏2023-02-18 下午5.07.52.png(实际考试时间)之间的时间差制定的实战计划:

第1天(收到邀请当天):建立靶向认知
- 上午:用grep -r "协方差" *.docx *.pdf搜索所有公司文档,统计各公司考协方差相关题的频率和形式;
- 下午:打开Untitled.ipynb,运行所有公司的answer.py,记录哪个公司的代码运行最慢(通常是天演的PyTorch模型加载);
- 晚上:针对最慢的那个公司,重写其核心算法为纯NumPy实现,对比性能提升。

第2天(考前一日):压力测试与降维
- 上午:把position.csv里的持仓数据,强行注入极端值(如某只股票价格设为0),运行所有结算代码,看哪里崩溃;
- 下午:手写一道题的三种解法(如用蒙特卡洛、解析解、近似公式),比较优劣;
- 晚上:只看answer.jpeg里的涂改痕迹,模仿其思维纠错过程,重做一遍。

第3天(考试当日):状态校准
- 上午:用WechatIMG5.jpeg里的草稿纸格式,手写一页推导,重点练排版和术语标注;
- 中午:运行一次simulate_median_clt,确认环境无异常;
- 考前1小时:默写三家公司最常考的三个公式及其适用条件(如“Ledoit-Wolf收缩适用于n<p场景”)。

这个计划的核心是:把不确定性转化为可执行动作。比如“运行最慢的代码”这个动作,直接暴露了你的环境瓶颈;“注入极端值”这个动作,提前发现了你的代码鲁棒性缺陷。所有动作都有明确产出物,而非模糊的“复习”。

4.4 一份被忽略的宝藏:密码.docx机器学习项目文档.pdf的深层价值

很多人直接跳过密码.docx机器学习项目文档.pdf,认为是干扰项。但截屏2023-02-18 下午4.47.32.png里,面试官指着密码.docx说:“这个加密方案,如果用在行情传输中,会带来什么延迟?”——这题考的不是密码学,而是系统级权衡思维

密码.docx内容实为AES-256-CBC加密流程文档,但关键在附录的性能测试表:

密钥长度 数据块大小 加密耗时(ms) 解密耗时(ms) 内存占用(MB)
128-bit 1KB 0.023 0.021 0.15
256-bit 1KB 0.038 0.035 0.15
256-bit 1MB 12.4 11.8 12.6

这个表揭示了真实约束:在高频交易中,1MB行情包的加密延迟12ms已不可接受(交易所平均撮合延迟<100μs),所以必须用硬件加速或轻量级加密。这就是为什么平方和的题库里有Tetris.docx——他们在测试你能否把图形学中的状态压缩思想,迁移到加密算法优化中。

机器学习项目文档.pdf更是宝藏。它描述了一个“用LSTM预测股指期货日内波动率”的项目,但没写模型结构,只给了评估指标:

指标 训练集 测试集 说明
RMSE 0.012 0.048 测试集误差是训练集的4倍
MAE 0.009 0.035 同上
0.92 0.65 显著下降

这个数据在说:模型过拟合了。但面试官不会直接问“怎么解决过拟合”,而是问:“如果这是你的实盘模型,你会先检查哪三个地方?” 正确答案是:
1. 检查特征工程:是否用了未来信息(如用当日收盘价构造特征);
2. 检查时间序列分割:是否用TimeSeriesSplit而非随机分割;
3. 检查损失函数:是否用MAE而非MSE,避免异常值主导训练。

最后分享一个小技巧:所有.jpeg截图里,面试官的微信头像都不同。我统计发现,用卡通头像的面试官(如WechatIMG2.jpeg)更关注思维过程,用风景照的(如WechatIMG4.jpeg)更关注结果精度。这不是玄学,而是性格投射——你可以据此微调答题策略:对前者,多展示推导草稿;对后者,确保最终答案数字精确到小数点后四位。

5. 写在最后:当代码跑通那一刻,真正的考验才开始

我删掉了最初写的几百字结尾——那些“祝你成功”“前程似锦”的套话。因为在这个行当里,没有轻松的成功。你此刻看到的answer.py,是我重写了17遍的产物;answer.jpeg里的涂改,是我在凌晨三点推翻前三次推导的痕迹;Untitled.ipynb里每一个单元格的注释,都对应着某次面试中被追问到哑口无言的瞬间。

这份资料最珍贵的部分,不是那些题目和答案,而是它坦诚地展示了专业能力的成长轨迹:从第一次看到伊藤引理时的困惑,到能随手写出其在跳跃扩散过程中的修正形式;从把pandas当Excel用,到理解DataFrame底层内存布局对缓存命中率的影响;从机械套用CAPM,到能说出“在中国A股市场,CAPM的β系数在牛市初期失效,因为散户情绪导致系统性风险溢价非线性上升”。

所以,当你运行answer.py看到print("Test passed!")时,请不要松一口气。真正的考验在下一秒:面试官合上电脑,抬头问你:“如果现在把样本量扩大一百倍,这段代码的瓶颈会在哪里?你会怎么优化?”——这个问题的答案,不在任何文档里,而在你过去每一次为搞懂一个内存泄漏而熬的夜,在你为验证一个统计假设而写的第十次蒙特卡洛模拟,在你为读懂一行晦涩的论文推导而查的第五本参考书里。

最后,打开密码.docx,找到最后一页的空白处,用铅笔写下你的名字和今天日期。这不是签名,而是你向自己立下的契约:从今天起,不再为笔试而学,而是为成为一个能在真实市场中活下来、跑赢时间的量化从业者而学。毕竟,市场从不关心你刷了多少题,它只认一件事:当黑天鹅起飞时,你的模型,有没有翅膀。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:诚奇、概率投资、海悦、天演、衍复、佳期、平方和、集微、九坤、凯读这十家主流量化私募的笔试真题打包整理,题目来源真实,多为2023年2月前后面试现场截屏与手写扫描件,覆盖概率统计推导、算法逻辑设计、数学建模、数据处理及策略思路表达等高频考点。每个公司独立成块,附带清晰原题文档(如PDF、DOCX)、部分配套Python实现(answer.py)、HTML格式解析页(answer.html)以及Jupyter Notebook交互示例(Untitled.ipynb),方便调试验证。资源中还包含交易结算练习、机器学习项目文档、CMFPos/AresPos/MSPos等岗位相关JSON配置文件,以及策略项目问答类截图(WechatIMG.jpeg、截屏.png),内容直指量化研究员、量化开发、策略实习生等岗位实际考察重点。所有材料按机构归类,结构明确,支持按目标公司快速定位题型风格与难度特征,适合针对性刷题与临场模拟。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

更多推荐