<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>编程与工程基础 on 云栖</title><link>http://airyv.com/quant/02-coding/</link><description>Recent content in 编程与工程基础 on 云栖</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="http://airyv.com/quant/02-coding/index.xml" rel="self" type="application/rss+xml"/><item><title>Python 量化栈：NumPy、Pandas 与向量化思维</title><link>http://airyv.com/quant/python-quant-stack/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://airyv.com/quant/python-quant-stack/</guid><description>&lt;p&gt;Python 成为量化第一语言不是因为它快（它很慢），而是因为它&lt;strong&gt;把「想法到验证」的距离压到最短&lt;/strong&gt;。本篇不讲语法，讲三件真正影响研究质量的事：向量化思维、Pandas 的对齐陷阱、以及复现纪律。所有例子都来自交易场景。&lt;/p&gt;
&lt;h2 id="numpy向量化是思维方式的转变"&gt;NumPy：向量化是思维方式的转变
&lt;/h2&gt;&lt;p&gt;新手写双均线策略：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 逐日循环：慢、啰嗦、容易在边界犯错&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ma5&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ma20&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;ma5&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ma20&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;signals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;向量化写法把「逐日判断」变成「整列运算」：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ma5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ma20&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;death_cross&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ma5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ma20&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ma5&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;ma20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 整列布尔&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;三重收益：&lt;strong&gt;速度&lt;/strong&gt;（底层 C 循环，百万行毫秒级，因子批量计算的前提）、&lt;strong&gt;正确性&lt;/strong&gt;（&lt;code&gt;shift(1)&lt;/code&gt; 强制你显式处理「用昨天信号交易今天」——逐日循环里这恰恰是最容易写错的地方）、&lt;strong&gt;可读性&lt;/strong&gt;（公式与代码同构）。性能优化路线：纯 Python → NumPy 向量化 → NumPy 广播/&lt;code&gt;einsum&lt;/code&gt; → Numba/Cython（只在 profile 证明瓶颈后用，见&lt;a
 class="link"
 href="#"&gt;&lt;span class="markdown-link-inner"&gt;向量化的边界&lt;/span&gt;&lt;/a&gt;
）。&lt;/p&gt;
&lt;h2 id="pandas强大之处与三大陷阱"&gt;Pandas：强大之处与三大陷阱
&lt;/h2&gt;&lt;p&gt;Pandas 的 DataFrame 是量化数据的默认形态（T 行 × N 列，见&lt;a
 class="link"
 href="http://airyv.com/quant/linear-algebra-quant/"&gt;&lt;span class="markdown-link-inner"&gt;线性代数&lt;/span&gt;&lt;/a&gt;
的收益矩阵）。但它有三个让回测悄悄变错的陷阱：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;陷阱一：索引对齐的静默 NaN。&lt;/strong&gt; 两只股票停牌日不同，&lt;code&gt;df1 + df2&lt;/code&gt; 会按索引对齐，缺失处产生 NaN；随后 &lt;code&gt;fillna(0)&lt;/code&gt; 把「没交易」填成「收益 0」——&lt;strong&gt;把停牌处理成免费平仓&lt;/strong&gt;，回测收益虚高。守则：算完先看 &lt;code&gt;df.isna().sum()&lt;/code&gt;；明确每列的业务含义（停牌是「沿用昨日价」还是「不可交易」）再决定填充策略。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;陷阱二：&lt;code&gt;ffill&lt;/code&gt; 与前视。&lt;/strong&gt; 用财报数据 &lt;code&gt;ffill()&lt;/code&gt; 向前填充本身没错，错的是&lt;strong&gt;对齐错了时间戳&lt;/strong&gt;：Q1 财报（4 月 30 日公布）的数据从 3 月 31 日就开始用，就是前视偏差。守则：财报数据一律以&lt;strong&gt;公告日&lt;/strong&gt;重新索引后再 ffill（见&lt;a
 class="link"
 href="http://airyv.com/quant/data-cleaning/"&gt;&lt;span class="markdown-link-inner"&gt;PIT 数据库&lt;/span&gt;&lt;/a&gt;
）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;陷阱三：inplace 与链式赋值。&lt;/strong&gt; &lt;code&gt;df[df.a&amp;gt;0]['b'] = 1&lt;/code&gt; 静默失败；&lt;code&gt;inplace=True&lt;/code&gt; 在新版本已被弃用。守则：显式赋值 &lt;code&gt;df.loc[mask, 'b'] = 1&lt;/code&gt;，研究代码避免 inplace。&lt;/p&gt;
&lt;p&gt;SciPy 的日常角色：&lt;code&gt;scipy.stats&lt;/code&gt;（t 检验、正态性检验）、&lt;code&gt;scipy.optimize&lt;/code&gt;（组合优化的 SLSQP、GARCH 的 MLE）、&lt;code&gt;scipy.linalg&lt;/code&gt;（Cholesky 分解做相关采样）。它们是&lt;a
 class="link"
 href="http://airyv.com/quant/statistical-inference/"&gt;&lt;span class="markdown-link-inner"&gt;统计推断&lt;/span&gt;&lt;/a&gt;
与&lt;a
 class="link"
 href="http://airyv.com/quant/optimization-quant/"&gt;&lt;span class="markdown-link-inner"&gt;优化&lt;/span&gt;&lt;/a&gt;
两章的工程对应物。&lt;/p&gt;
&lt;h2 id="可视化为判断服务不为好看服务"&gt;可视化：为判断服务，不为好看服务
&lt;/h2&gt;&lt;p&gt;量化图表的四条纪律：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;累计净值永远配对数轴 + 画基准&lt;/strong&gt;——线性轴让 2015 年的 3 倍吞掉后面所有细节；无基准的净值曲线没有信息量；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;回撤曲线与净值同框&lt;/strong&gt;——收益的样子骗人，回撤的形状诚实（水下曲线）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;因子检验画分组净值而不是只报 IC&lt;/strong&gt;——单调性是肉眼可见的（见&lt;a
 class="link"
 href="http://airyv.com/quant/factor-testing/"&gt;&lt;span class="markdown-link-inner"&gt;因子检验&lt;/span&gt;&lt;/a&gt;
）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分布图画对数收益并标注 ±3σ 与极值点&lt;/strong&gt;——肥尾一眼可见（见&lt;a
 class="link"
 href="http://airyv.com/quant/probability-basics/"&gt;&lt;span class="markdown-link-inner"&gt;概率论基础&lt;/span&gt;&lt;/a&gt;
）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;工具选择：研究期 Matplotlib（快、可控、出报告图），交互探索 Plotly（缩放排查单日异常）。Matplotlib 的中文字体（&lt;code&gt;plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']&lt;/code&gt;）与负号显示（&lt;code&gt;axes.unicode_minus = False&lt;/code&gt;）是 Windows 环境必配的两行。&lt;/p&gt;
&lt;h2 id="jupyter-与研究复现"&gt;Jupyter 与研究复现
&lt;/h2&gt;&lt;p&gt;Notebook 适合&lt;strong&gt;探索&lt;/strong&gt;（分步验证数据、即时画图），但「cell 乱序执行」会制造不可复现的研究：&lt;code&gt;df&lt;/code&gt; 在第 3 格被改、第 7 格重跑时结果全变而你不自知。复现纪律四条：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;探索用 Notebook，成形即落盘&lt;/strong&gt;：任何通过初检的因子，立刻把逻辑重写成 &lt;code&gt;.py&lt;/code&gt; 模块 + 单元测试（见&lt;a
 class="link"
 href="http://airyv.com/quant/code-quality/"&gt;&lt;span class="markdown-link-inner"&gt;代码质量&lt;/span&gt;&lt;/a&gt;
），Notebook 只留调用；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;顶部固定环境&lt;/strong&gt;：&lt;code&gt;%load_ext autoreload&lt;/code&gt;、随机种子、数据版本号写在第一个 cell；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restart &amp;amp; Run All 是提交标准&lt;/strong&gt;：一个 notebook 若不能一键从头跑通，就等于没写完；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据快照&lt;/strong&gt;：因子计算前记录数据表的行数、日期范围、来源版本——三个月后复现不出的「夏普 2.3」等于不存在（见&lt;a
 class="link"
 href="http://airyv.com/quant/factor-storage-quality/"&gt;&lt;span class="markdown-link-inner"&gt;因子存储与版本管理&lt;/span&gt;&lt;/a&gt;
）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;关联阅读&lt;/strong&gt;：&lt;a
 class="link"
 href="http://airyv.com/quant/git-collaboration/"&gt;&lt;span class="markdown-link-inner"&gt;Git 与协作&lt;/span&gt;&lt;/a&gt;
 管住代码版本；&lt;a
 class="link"
 href="http://airyv.com/quant/quant-frameworks/"&gt;&lt;span class="markdown-link-inner"&gt;回测框架概览&lt;/span&gt;&lt;/a&gt;
 评测现成轮子；&lt;a
 class="link"
 href="http://airyv.com/quant/scheduling-databases/"&gt;&lt;span class="markdown-link-inner"&gt;任务调度&lt;/span&gt;&lt;/a&gt;
 把 Notebook 研究变成每日自动运行的流水线。&lt;/p&gt;</description></item><item><title>其他语言生态：C++、Rust、Go、R 与 MATLAB（选读）</title><link>http://airyv.com/quant/other-languages/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://airyv.com/quant/other-languages/</guid><description>&lt;p&gt;「量化用什么语言」是个伪问题——成熟机构从来是多语言栈：研究在 Python，生产在 C++/Rust，统计在 R，历史遗留仍在 MATLAB。本篇给一张选型地图：&lt;strong&gt;每种语言回答什么交易问题&lt;/strong&gt;，以及「换语言」的真实成本。&lt;/p&gt;
&lt;h2 id="c延迟敏感场景的统治者"&gt;C++：延迟敏感场景的统治者
&lt;/h2&gt;&lt;p&gt;微秒级延迟的战场——高频做市、期货高频套利、行情解析——至今仍是 C++ 的领地。先看一段行情链路的延迟预算，就知道优化发生在哪里：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;链路段&lt;/th&gt;
 &lt;th&gt;典型延迟&lt;/th&gt;
 &lt;th&gt;由什么决定&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;交易所撮合 → 机房内你的网卡&lt;/td&gt;
 &lt;td&gt;1–5 μs&lt;/td&gt;
 &lt;td&gt;物理距离（托管是入场券）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;行情解析（UDP → 结构化 tick）&lt;/td&gt;
 &lt;td&gt;0.3–2 μs&lt;/td&gt;
 &lt;td&gt;内核旁路 + C++/FPGA&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;策略计算（做市报价更新）&lt;/td&gt;
 &lt;td&gt;0.5–5 μs&lt;/td&gt;
 &lt;td&gt;算法与数据结构（无堆分配、无系统调用）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;订单编码 + 发出&lt;/td&gt;
 &lt;td&gt;0.3–1 μs&lt;/td&gt;
 &lt;td&gt;预序列化模板 + FPGA 更快&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;你的服务器 → 交易所撮合&lt;/td&gt;
 &lt;td&gt;1–5 μs&lt;/td&gt;
 &lt;td&gt;同物理距离&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;读懂这张表就懂了 C++ 的不可替代性&lt;/strong&gt;：全程预算 10 μs 的场景里，Python 一次对象分配（~100ns×百万次）、一次 GC 暂停（~ms 级）、一层解释器开销（Python 单次行情处理通常 10–100μs）都直接出局。这不是「优化 Python」能追平的量级差，是范式差。&lt;/p&gt;
&lt;p&gt;适合你的信号：策略的盈亏由「快 5 微秒」决定（排队位置、抢单），而不是由信号质量决定。判断口诀：&lt;strong&gt;收益来源是「信息优势×速度」才上 C++；收益来源是「统计规律」Python 足矣&lt;/strong&gt;——多因子选股把下单从 100ms 提到 5ms 毫无意义，做市商差 5 微秒就是生死（见&lt;a
 class="link"
 href="http://airyv.com/quant/hft-and-market-making/"&gt;&lt;span class="markdown-link-inner"&gt;高频交易概论&lt;/span&gt;&lt;/a&gt;
）。学习路径建议：先 Python 完整走通策略闭环，再按&lt;a
 class="link"
 href="http://airyv.com/quant/low-latency-basics/"&gt;&lt;span class="markdown-link-inner"&gt;低延迟基础&lt;/span&gt;&lt;/a&gt;
的清单逐项优化，C++ 是最后一步而非第一步。&lt;/p&gt;
&lt;h2 id="rust--go新一代基础设施的选项"&gt;Rust / Go：新一代基础设施的选项
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt; 在量化基础设施层（行情网关、回测引擎核心、风控网关）快速渗透：内存安全无 GC、性能对标 C++、现代工具链（cargo 依赖管理与测试体验远优于 CMake）。适合「要 C++ 的性能，不想要 C++ 的段错误」的团队——量化系统的特点是&lt;strong&gt;长时间无人值守运行&lt;/strong&gt;，C++ 的野指针在凌晨三点崩掉进程的代价，Rust 在编译期就拦下了。代价：学习曲线陡（借用检查）、金融领域成熟库少（&lt;em&gt;fixed income&lt;/em&gt; 定价、行情协议解析常要自己造）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt; 统治调度与 API 层：goroutine 模型天然适合「同时盯几百个行情连接 + 并发下单 + 心跳监控」——写一个多交易所行情聚合网关，Go 大约是 C++ 三分之一到五分之一的代码量。很多机构的&lt;strong&gt;交易监控系统、清结算对账服务&lt;/strong&gt;用 Go 写。&lt;/p&gt;
&lt;p&gt;对新人的建议：这两个语言是&lt;strong&gt;锦上添花&lt;/strong&gt;，不是入行门票。量化工程师岗位的核心竞争力仍是「把研究可靠地搬到生产」的系统能力，语言只是载体。&lt;/p&gt;
&lt;h2 id="r统计研究的行家"&gt;R：统计研究的行家
&lt;/h2&gt;&lt;p&gt;R 的优势集中在统计建模的原生性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;公式接口&lt;/strong&gt;：&lt;code&gt;lm(ret ~ mkt + smb + hml + mom)&lt;/code&gt; 一行完成回归与完整诊断（t 值、R²、残差图）——Python 的 statsmodels 能做到但啰嗦一倍；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;新方法的首发平台&lt;/strong&gt;：学术界新统计方法（新的 FDR 变体、面板回归修正、wild bootstrap）几乎总是先有 R 包，Python 社区跟进滞后半年到数年。复现一篇论文的方法时，先搜 R 包常能省一周；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据处理的 &lt;code&gt;data.table&lt;/code&gt;&lt;/strong&gt;：大表分组运算在某些场景快过 Pandas。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实务定位：&lt;strong&gt;Python 已覆盖 R 的 95% 用途&lt;/strong&gt;（statsmodels、linearmodels、arch）。值得专门学 R 的场景：需要用最新的计量方法而 Python 尚无成熟实现；或所在团队历史代码是 R。&lt;/p&gt;
&lt;h2 id="matlab曾经的标准如今的遗产"&gt;MATLAB：曾经的标准、如今的遗产
&lt;/h2&gt;&lt;p&gt;2010 年前的量化教材与欧洲机构大量使用 MATLAB（工具箱齐全、矩阵思维原生）。今天它主要作为&lt;strong&gt;遗产系统&lt;/strong&gt;存在：读经典教材（如一些老牌 MFE 课程讲义）、维护老系统时需要能读懂，新项目不建议入坑——闭源授权贵、生态迁移、部署麻烦三座大山。&lt;/p&gt;
&lt;h2 id="选型决策表"&gt;选型决策表
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;你的问题&lt;/th&gt;
 &lt;th&gt;推荐&lt;/th&gt;
 &lt;th&gt;理由&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;因子研究、回测原型&lt;/td&gt;
 &lt;td&gt;Python&lt;/td&gt;
 &lt;td&gt;生态与迭代速度&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;生产多因子日频交易&lt;/td&gt;
 &lt;td&gt;Python + 少量 C 扩展&lt;/td&gt;
 &lt;td&gt;延迟不敏感&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;高频做市 / 抢单类套利&lt;/td&gt;
 &lt;td&gt;C++ 或 Rust&lt;/td&gt;
 &lt;td&gt;微秒延迟决定盈亏&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;行情网关、监控系统&lt;/td&gt;
 &lt;td&gt;Go&lt;/td&gt;
 &lt;td&gt;高并发网络编程效率&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;学术级统计推断、方法复现&lt;/td&gt;
 &lt;td&gt;R&lt;/td&gt;
 &lt;td&gt;统计包最新最全&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;读懂 2010 年前的经典代码&lt;/td&gt;
 &lt;td&gt;MATLAB&lt;/td&gt;
 &lt;td&gt;遗产兼容&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一条贯穿的原则：&lt;strong&gt;语言是成本中心，不是竞争力本身&lt;/strong&gt;。同一家机构里，把 Python 研究流水线做得可靠、可复现的人，长期价值高于「用 Rust 重写了回测引擎但因子产出为零」的人——工程服务于研究，这根主轴不要倒置（见&lt;a
 class="link"
 href="http://airyv.com/quant/panorama/"&gt;&lt;span class="markdown-link-inner"&gt;量化全景图&lt;/span&gt;&lt;/a&gt;
）。判断自己是否在「为换语言而换语言」的试金石：新语言能把哪个&lt;strong&gt;研究产出指标&lt;/strong&gt;（因子尝试数/上线周期/事故率）改善多少？答不出数字，就先别动。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关联阅读&lt;/strong&gt;：&lt;a
 class="link"
 href="http://airyv.com/quant/python-quant-stack/"&gt;&lt;span class="markdown-link-inner"&gt;Python 量化栈&lt;/span&gt;&lt;/a&gt;
 是默认主线；&lt;a
 class="link"
 href="http://airyv.com/quant/low-latency-basics/"&gt;&lt;span class="markdown-link-inner"&gt;低延迟基础&lt;/span&gt;&lt;/a&gt;
 给出 C++/Rust 场景的度量清单；&lt;a
 class="link"
 href="http://airyv.com/quant/quant-system-architecture/"&gt;&lt;span class="markdown-link-inner"&gt;生产系统架构&lt;/span&gt;&lt;/a&gt;
 展示多语言如何在一个系统里分工。&lt;/p&gt;</description></item><item><title>版本控制与协作（Git）</title><link>http://airyv.com/quant/git-collaboration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://airyv.com/quant/git-collaboration/</guid><description>&lt;p&gt;量化代码的特殊性在于：&lt;strong&gt;三个月后你必须能精确复现某一天的信号&lt;/strong&gt;——监管问询、客户问询、或仅仅是「为什么当时的仓位和现在不一样」。Git 是这个能力的地基，但量化场景的 Git 用法与软件开发有几个关键差异。&lt;/p&gt;
&lt;h2 id="分支策略研究分支是用来敢于尝试的"&gt;分支策略：研究分支是用来「敢于尝试」的
&lt;/h2&gt;&lt;p&gt;个人研究者的常见做法是复制 &lt;code&gt;策略_v3_最终版_真最终版.py&lt;/code&gt;——三个月后没人知道哪个是活的。正确的最小工作流：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;main&lt;/code&gt; 分支永远保持「可直接实盘」状态：每次合并前必须通过回测复核（见&lt;a
 class="link"
 href="http://airyv.com/quant/strategy-deployment/"&gt;&lt;span class="markdown-link-inner"&gt;策略上线流程&lt;/span&gt;&lt;/a&gt;
）；&lt;/li&gt;
&lt;li&gt;每个研究假设开一个分支：&lt;code&gt;factor/reversal-20d&lt;/code&gt;、&lt;code&gt;fix/stop-loss-queue&lt;/code&gt;——实验失败就删分支，零成本。分支命名的约定本身就值回票价：&lt;code&gt;factor/&lt;/code&gt; 前缀的分支 = 未验证假设，&lt;code&gt;prod/&lt;/code&gt; 前缀 = 在跑策略，一眼分清「想法」与「资产」；&lt;/li&gt;
&lt;li&gt;合并（merge/PR）即「上线决策」：合并记录 = 上线记录，回滚 = &lt;code&gt;git revert&lt;/code&gt;。这与&lt;a
 class="link"
 href="http://airyv.com/quant/strategy-deployment/"&gt;&lt;span class="markdown-link-inner"&gt;灰度放量&lt;/span&gt;&lt;/a&gt;
衔接：分支可以合并了，资金百分比逐步放大；&lt;/li&gt;
&lt;li&gt;团队协作再加两条：PR 必须有第二人 review（QE 或另一位 QR，重点查前视与成本假设——代码评审在量化里的重心不是风格而是「这行会不会偷看未来」）；&lt;code&gt;main&lt;/code&gt; 打 tag 对应每个实盘版本（&lt;code&gt;prod-2026-09-15&lt;/code&gt;），实盘异常时第一动作是核对生产进程跑的是哪个 tag。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="commit写给三个月后的自己的研究日志"&gt;Commit：写给三个月后的自己的研究日志
&lt;/h2&gt;&lt;p&gt;「fix bug」「update」式的 commit 信息在量化里的成本极高。推荐的格式是**「动机 + 口径 + 结果」**：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;factor/momentum-60d: 剔除停牌超过20日的样本后重估IC
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 原因：长期停牌股的动量因子值冻结，IC被高估约15%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 口径：2020-2025，月频，行业市值中性，含双边成本
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 结果：RankIC 0.031→0.024，夏普 1.8→1.5，仍显著(t=2.9)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这条记录三个月后就是现成的&lt;a
 class="link"
 href="http://airyv.com/quant/alpha-research-process/"&gt;&lt;span class="markdown-link-inner"&gt;研究笔记&lt;/span&gt;&lt;/a&gt;
。&lt;strong&gt;回测结果写进 commit 的价值&lt;/strong&gt;：绩效数字会随数据更新漂移，把「当时看到什么」钉死在时间轴上，是诚实研究的一部分——三个月后数据更新导致 IC 变成 0.028，你能精确定位变化发生在哪次数据或代码变更。&lt;/p&gt;
&lt;h2 id="gitignore量化仓库的第一道安全门"&gt;&lt;code&gt;.gitignore&lt;/code&gt;：量化仓库的第一道安全门
&lt;/h2&gt;&lt;p&gt;必进 ignore 清单的东西比一般软件项目多：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;data/ # 原始行情数据（GB级，且可能有授权限制）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.h5 *.parquet # 因子中间产物
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;config/prod.yaml # 含交易账户、密钥的生产配置
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.ipynb_checkpoints/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;血泪教训两条：把几十 GB 的行情数据 push 进仓库拖垮所有人（git 对大二进制的历史是永久负担，即使后续删除，历史里还在）；把 API key（券商接口、数据商账号）提交进公开仓库——&lt;strong&gt;密钥一旦入网即视为泄露，必须作废重置&lt;/strong&gt;， gods and regulators 都帮不了你（见&lt;a
 class="link"
 href="http://airyv.com/quant/dr-and-security/"&gt;&lt;span class="markdown-link-inner"&gt;安全&lt;/span&gt;&lt;/a&gt;
）。配置管理用模板 + 本地覆盖：&lt;code&gt;config.example.yaml&lt;/code&gt; 进仓库，真实配置本地放并 ignore。&lt;/p&gt;
&lt;h2 id="notebook-与实验的版本化"&gt;Notebook 与实验的版本化
&lt;/h2&gt;&lt;p&gt;Jupyter Notebook 对 Git 不友好（diff 全是 JSON 噪声），三个实用妥协：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Notebook 只做探索，成形逻辑落 &lt;code&gt;.py&lt;/code&gt;（见&lt;a
 class="link"
 href="http://airyv.com/quant/python-quant-stack/"&gt;&lt;span class="markdown-link-inner"&gt;研究复现&lt;/span&gt;&lt;/a&gt;
），&lt;code&gt;.py&lt;/code&gt; 严格进 Git；&lt;/li&gt;
&lt;li&gt;确要进仓库的 Notebook，提交前清空输出（&lt;code&gt;nbstripout&lt;/code&gt; 工具自动化）；&lt;/li&gt;
&lt;li&gt;实验结果（指标表格、净值截图）不进 Git，进&lt;strong&gt;实验登记表&lt;/strong&gt;（一行一个实验：分支名、参数、绩效、结论）——Git 管代码，表格管结果，两者用分支名关联。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="数据版本git-之外的轻量方案"&gt;数据版本：Git 之外的轻量方案
&lt;/h2&gt;&lt;p&gt;数据本身不适合 Git（体积大、二进制、更新频繁），但&lt;strong&gt;数据版本号必须被 Git 记录&lt;/strong&gt;：因子计算脚本读取的每张表，在其旁边维护一个 &lt;code&gt;manifest.json&lt;/code&gt;（行数、日期范围、生成时间、来源脚本版本）；脚本启动时校验 manifest 与预期一致，不一致直接报错拒跑。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;table&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;daily_bar_hfq&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;rows&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5820344&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;date_range&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2014-01-02&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2026-09-17&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;built_at&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2026-09-17T17:12:04&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;source_commit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;a3f9c2d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;adj_factor_version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;20260917&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这就是&lt;a
 class="link"
 href="http://airyv.com/quant/factor-storage-quality/"&gt;&lt;span class="markdown-link-inner"&gt;因子存储与版本管理&lt;/span&gt;&lt;/a&gt;
的最小实现——没有它，「同一个策略上周和今天回测结果不一样」将永远无法归因。这句话值得展开：99% 的「回测结果对不上」最终归因于三者之一——数据变了（manifest 能抓）、代码变了（git 能抓）、参数变了（配置 diff 能抓）。三样都版本化，神秘感消失。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关联阅读&lt;/strong&gt;：&lt;a
 class="link"
 href="http://airyv.com/quant/code-quality/"&gt;&lt;span class="markdown-link-inner"&gt;代码质量&lt;/span&gt;&lt;/a&gt;
 接管合并前的质量门禁；&lt;a
 class="link"
 href="http://airyv.com/quant/factor-storage-quality/"&gt;&lt;span class="markdown-link-inner"&gt;因子存储与版本管理&lt;/span&gt;&lt;/a&gt;
 是数据层版本化的完整方案；&lt;a
 class="link"
 href="http://airyv.com/quant/quant-devops/"&gt;&lt;span class="markdown-link-inner"&gt;DevOps 与 CI/CD&lt;/span&gt;&lt;/a&gt;
 把本篇的手工流程自动化。&lt;/p&gt;</description></item><item><title>代码质量：规范、测试、类型注解与依赖管理</title><link>http://airyv.com/quant/code-quality/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://airyv.com/quant/code-quality/</guid><description>&lt;p&gt;研究代码的质量标准与业务软件不同：它允许探索期的凌乱，但&lt;strong&gt;任何要进入回测或实盘的逻辑必须达到生产质量&lt;/strong&gt;——因为一个 sign 错误、一个 off-by-one，亏损的是真金白银。本篇用同一个交易函数贯穿四个话题。&lt;/p&gt;
&lt;h2 id="一个函数的四重进化"&gt;一个函数的四重进化
&lt;/h2&gt;&lt;p&gt;需求：给定持仓与当日最高最低价，判断固定百分比止损是否触发。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# v0：研究 Notebook 里的顺手一写（有 3 个隐患）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pct&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# p 是什么价？成本价还是昨收？跌停怎么办？&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;隐患：参数含义无文档；跌停无法卖出的情形未处理；无法防止未来有人把 &lt;code&gt;low&lt;/code&gt; 传成收盘价。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# v1：类型注解 + 明确语义&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_stop_triggered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cost_price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day_low&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stop_pct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;当日最低价跌破成本价×(1-stop_pct) 时触发止损。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stop_pct&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;stop_pct 必须为正&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;day_low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cost_price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;stop_pct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# v2：单元测试（pytest）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pytest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_normal_trigger&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;is_stop_triggered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.49&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt; &lt;span class="c1"&gt;# 9.49 &amp;lt; 9.50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_boundary_exact&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;is_stop_triggered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt; &lt;span class="c1"&gt;# 恰好等于不触发&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_float_precision&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;is_stop_triggered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.499999999&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt; &lt;span class="c1"&gt;# 浮点边界&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_invalid_pct&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;is_stop_triggered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;9.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop_pct&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;测试用例从哪里来？从真实事故里来。&lt;/strong&gt; 「恰好等于不触发」这种边界，是无数实盘纠纷（触发价 vs 成交价）换来的。量化代码的测试金字塔：纯函数（信号计算、止损判断、仓位计算）全量单测；数据管道用「黄金样本」测试（一小份已知答案的历史数据，跑完比对输出）；回测引擎用端到端回归测试（改动前后对同一数据集的净值曲线 diff）。&lt;/p&gt;
&lt;h2 id="类型注解pandas-时代尤其实用"&gt;类型注解：Pandas 时代尤其实用
&lt;/h2&gt;&lt;p&gt;Python 的动态类型在量化里的代价极高：&lt;code&gt;pd.Series&lt;/code&gt; 与 &lt;code&gt;pd.DataFrame&lt;/code&gt; 传错（一个是列一个是表）、日期是 str 还是 Timestamp、收益率是小数还是百分数——这些错误运行时才爆，而且爆在三层调用之外。类型注解 + &lt;code&gt;mypy&lt;/code&gt;（或 pandas-stubs）能在 IDE 里当场标红：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Timestamp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_weights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;asof&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;top_n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;scores: index=日期, columns=股票代码 的因子分数表&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;渐进式采用即可：新代码全部注解，老代码改动时顺手补。团队收益巨大——&lt;strong&gt;类型就是最小的可执行文档&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="规范让-code-review-聚焦逻辑而不是格式"&gt;规范：让 code review 聚焦逻辑而不是格式
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;格式交给工具：&lt;code&gt;black&lt;/code&gt;（格式化）+ &lt;code&gt;ruff&lt;/code&gt;（lint，含 import 排序、未用变量）+ pre-commit 钩子，仓库里零配置争议；&lt;/li&gt;
&lt;li&gt;命名约束写进 README：收益率字段统一 &lt;code&gt;ret&lt;/code&gt; 后缀、因子表列名统一 &lt;code&gt;factor_xxx&lt;/code&gt;、日期列统一 &lt;code&gt;date&lt;/code&gt;（Timestamp 类型）——&lt;strong&gt;跨策略的字段口径一致&lt;/strong&gt;，是多人协作里最省钱的决定；&lt;/li&gt;
&lt;li&gt;函数纪律：单个函数不超过一屏；回测里禁止出现魔法数字（&lt;code&gt;0.001&lt;/code&gt; 必须命名 &lt;code&gt;COMMISSION_RATE&lt;/code&gt;）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;research 包结构&lt;/strong&gt;模板：&lt;code&gt;data/&lt;/code&gt;（加载与清洗）、&lt;code&gt;factors/&lt;/code&gt;（一因子一文件一测试）、&lt;code&gt;backtest/&lt;/code&gt;（引擎与成本模型）、&lt;code&gt;portfolio/&lt;/code&gt;（优化与权重）、&lt;code&gt;utils/&lt;/code&gt;——研究与回测共享同一份因子实现，杜绝「研究用 A 实现、回测用 B 实现」的分叉。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="依赖管理与虚拟环境"&gt;依赖管理与虚拟环境
&lt;/h2&gt;&lt;p&gt;「在我机器上能跑」在量化里的具体形态是：两年后重跑因子，numpy 新版改变了某个函数的默认行为，结果全变。对策：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;一项目一虚拟环境&lt;/strong&gt;（&lt;code&gt;python -m venv&lt;/code&gt; / conda / uv 任选），绝不往系统 Python 里装包；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;锁文件进仓库&lt;/strong&gt;：&lt;code&gt;pip freeze &amp;gt; requirements.lock&lt;/code&gt; 或用 &lt;code&gt;uv lock&lt;/code&gt; / &lt;code&gt;conda env export&lt;/code&gt;——精确到版本号的依赖是复现的必要条件；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;升级纪律&lt;/strong&gt;：依赖升级也走分支 + 回测回归测试——numpy/scipy/pandas 的大版本升级等同于「换了一次底层库」，净值曲线 diff 必须过；&lt;/li&gt;
&lt;li&gt;内网机构场景：搭建私有 PyPI 镜像，锁定数据商 SDK 版本。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;关联阅读&lt;/strong&gt;：&lt;a
 class="link"
 href="http://airyv.com/quant/git-collaboration/"&gt;&lt;span class="markdown-link-inner"&gt;Git 与协作&lt;/span&gt;&lt;/a&gt;
 让质量门禁落在合并时刻；&lt;a
 class="link"
 href="http://airyv.com/quant/backtest-engine-design/"&gt;&lt;span class="markdown-link-inner"&gt;回测框架设计&lt;/span&gt;&lt;/a&gt;
 定义哪些模块最值得测试；&lt;a
 class="link"
 href="http://airyv.com/quant/quant-devops/"&gt;&lt;span class="markdown-link-inner"&gt;DevOps 与 CI/CD&lt;/span&gt;&lt;/a&gt;
 把 pytest/mypy 自动化到每次提交。&lt;/p&gt;</description></item><item><title>日志、监控与告警基础</title><link>http://airyv.com/quant/logging-monitoring/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://airyv.com/quant/logging-monitoring/</guid><description>&lt;p&gt;量化系统 99% 的时间无人值守，&lt;strong&gt;它的可靠性完全由日志与监控决定&lt;/strong&gt;。个人量化者常见的两个极端：完全没有（出事靠事后翻券商 App 猜），或日志泛滥（每天几个 GB 没人看）。本篇给出分层最小的方案：每一层回答一个问题。&lt;/p&gt;
&lt;h2 id="第一层日志事后能重建现场"&gt;第一层：日志——事后能重建现场
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;结构化日志优于文本日志&lt;/strong&gt;。每条记录是带字段的一行（JSON 或键值对），而不是一句散文：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2026-09-18 09:31:02 [SIGNAL] {&amp;#34;strategy&amp;#34;:&amp;#34;mom20&amp;#34;,&amp;#34;action&amp;#34;:&amp;#34;BUY&amp;#34;,&amp;#34;code&amp;#34;:&amp;#34;600519.SH&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;target_w&amp;#34;:0.032,&amp;#34;price&amp;#34;:1458.0,&amp;#34;cash&amp;#34;:120340.5,&amp;#34;latency_ms&amp;#34;:42}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;必记的四类事件（对应一次交易的完整生命周期）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;数据事件&lt;/strong&gt;：行情/财务数据更新到哪个时间戳、缺失了哪些标的——数据断更是大多数「策略今天没交易」的真因；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;信号事件&lt;/strong&gt;：每个目标仓位的计算结果 + 关键中间量（因子值、排名）——事后复盘「为什么买了它」的唯一依据；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;订单事件&lt;/strong&gt;：下单、回报、部分成交、废单、撤单——含本地时间与交易所回报时间，延迟异常的原始证据；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;状态事件&lt;/strong&gt;：进程启动/重启、配置版本、资金账户快照（每日收盘后一条总账）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;分级（DEBUG/INFO/WARNING/ERROR）+ 轮转（按天切割、保留 90 天）+ &lt;strong&gt;日志里绝不打印密钥与完整账号&lt;/strong&gt;。技术栈：Python 用 &lt;code&gt;logging&lt;/code&gt; + &lt;code&gt;structlog&lt;/code&gt;，个人项目写文件 + 每日压缩即可；机构的用 ELK/Loki 集中检索（见&lt;a
 class="link"
 href="http://airyv.com/quant/quant-system-architecture/"&gt;&lt;span class="markdown-link-inner"&gt;系统架构&lt;/span&gt;&lt;/a&gt;
）。一个进阶习惯：&lt;strong&gt;每条日志带「运行指纹」&lt;/strong&gt;（代码版本 + 数据版本 + 配置哈希）——三个月后任何一条决策都能定位到「哪个版本的程序读了哪个版本的数据」（版本纪律见&lt;a
 class="link"
 href="http://airyv.com/quant/git-collaboration/"&gt;&lt;span class="markdown-link-inner"&gt;Git&lt;/span&gt;&lt;/a&gt;
）。&lt;/p&gt;
&lt;h2 id="第二层监控事前发现异常"&gt;第二层：监控——事前发现异常
&lt;/h2&gt;&lt;p&gt;监控回答「现在正常吗」，要盯的不是 CPU 内存这类通用指标（那交给云监控），而是&lt;strong&gt;业务健康度指标&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;指标&lt;/th&gt;
 &lt;th&gt;正常形态&lt;/th&gt;
 &lt;th&gt;异常含义&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;数据新鲜度&lt;/td&gt;
 &lt;td&gt;收盘后 17:00 前完成更新&lt;/td&gt;
 &lt;td&gt;数据管道故障，次日信号将过期&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;信号数量&lt;/td&gt;
 &lt;td&gt;日均 ±3σ 区间内&lt;/td&gt;
 &lt;td&gt;因子可能失效或数据错误（如全为 0）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;订单成交率&lt;/td&gt;
 &lt;td&gt;&amp;gt; 95%&lt;/td&gt;
 &lt;td&gt;废单潮 = 账户/权限/资金问题&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;实盘 vs 模拟偏离&lt;/td&gt;
 &lt;td&gt;日收益差 &amp;lt; 0.1%&lt;/td&gt;
 &lt;td&gt;执行故障或成本模型失效&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;当日 PnL&lt;/td&gt;
 &lt;td&gt;在策略分布的 ±4σ 内&lt;/td&gt;
 &lt;td&gt;市场极端或逻辑异常&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;持仓数量/集中度&lt;/td&gt;
 &lt;td&gt;符合限额&lt;/td&gt;
 &lt;td&gt;优化器或风控模块异常&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;vs 模拟偏离是最被低估的指标&lt;/strong&gt;：每天让实盘与一个影子模拟盘并行运行，两者收益差的分布一旦漂移，就是执行或数据出了问题——比看绝对收益灵敏得多。它也是区分「策略亏钱」与「系统出错」的第一道分诊（策略亏钱是市场问题，偏离是工程问题，处理人完全不同）。影子盘的实现成本极低：同一份信号代码跑在模拟账户上，只在日志里多一行（见&lt;a
 class="link"
 href="http://airyv.com/quant/real-time-risk/"&gt;&lt;span class="markdown-link-inner"&gt;事中风控&lt;/span&gt;&lt;/a&gt;
）。&lt;/p&gt;
&lt;h2 id="第三层告警什么才值得吵醒你"&gt;第三层：告警——什么才值得吵醒你
&lt;/h2&gt;&lt;p&gt;告警的工程学：&lt;strong&gt;太多 = 狼来了 = 无人再看&lt;/strong&gt;。三条铁律：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;每个告警必须可行动&lt;/strong&gt;：收到后明确知道下一步做什么（重启服务/暂停交易/人工核对），做不到的降级进日报；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分级路由&lt;/strong&gt;：P0（交易中断、风控熔断触发、资金异常）立即电话/短信，P1（数据迟到、成交率低）IM 即时消息，P2（绩效周环比下滑）进日报。个人用 Server 酱/企业微信机器人 + 手机推送即可实现三级；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;心跳（dead man&amp;rsquo;s switch）&lt;/strong&gt;：不是「出错才报」，而是「预期没发生也要报」——每天 17:05 没收到「今日运行完成」的推送，等同于收到一条 P0。大量真实事故是&lt;strong&gt;静默失败&lt;/strong&gt;（进程死了但没人发错误），心跳是对付它的唯一手段。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="与风控的关系监控是风控的眼睛"&gt;与风控的关系：监控是风控的眼睛
&lt;/h2&gt;&lt;p&gt;本篇的指标体系与&lt;a
 class="link"
 href="http://airyv.com/quant/real-time-risk/"&gt;&lt;span class="markdown-link-inner"&gt;事中风控&lt;/span&gt;&lt;/a&gt;
高度重叠，分工是：&lt;strong&gt;监控发现问题 → 风控执行动作&lt;/strong&gt;。监控发现「实盘 vs 模拟偏离超阈值」只是通知；「当日回撤触及熔断线」则由风控模块自动降仓/平仓，事后留痕。个人实现上可以合并成一个脚本，但&lt;strong&gt;逻辑上必须分开&lt;/strong&gt;：发现（可误报）与动作（不可误触发）用不同的阈值与确认机制。&lt;/p&gt;
&lt;h2 id="最小可用清单个人版半天工作量"&gt;最小可用清单（个人版，半天工作量）
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ logging 结构化日志（四类事件全覆盖 + 运行指纹）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ 每日收盘后一行式日报推送（净值、持仓数、信号数、现金）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ 心跳推送（固定时间没收到 = P0）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ 三个 P0 告警：进程死（心跳兜底）、数据过期、PnL 超 4σ
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;□ 月度回看：本月告警次数、误报率——告警系统自己也要被审计
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这套东西的性价比，高于任何额外的一个因子。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关联阅读&lt;/strong&gt;：&lt;a
 class="link"
 href="http://airyv.com/quant/real-time-risk/"&gt;&lt;span class="markdown-link-inner"&gt;事中风控&lt;/span&gt;&lt;/a&gt;
 是监控之上的自动动作层；&lt;a
 class="link"
 href="http://airyv.com/quant/strategy-deployment/"&gt;&lt;span class="markdown-link-inner"&gt;策略上线流程&lt;/span&gt;&lt;/a&gt;
 定义了监控从第一天就要在位；&lt;a
 class="link"
 href="http://airyv.com/quant/dr-and-security/"&gt;&lt;span class="markdown-link-inner"&gt;灾备与故障恢复&lt;/span&gt;&lt;/a&gt;
 处理监控本身挂掉怎么办。&lt;/p&gt;</description></item><item><title>量化常用开源框架概览</title><link>http://airyv.com/quant/quant-frameworks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://airyv.com/quant/quant-frameworks/</guid><description>&lt;p&gt;框架的价值不是「帮你写回测」，而是&lt;strong&gt;强制你面对正确的问题&lt;/strong&gt;：成交价用哪个？成本怎么算？停牌能不能成交？——成熟框架把这些坑内置成了默认答案。本篇按用途给一张地图，并回答「什么时候自己写」。&lt;/p&gt;
&lt;h2 id="事件驱动回测框架"&gt;事件驱动回测框架
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Backtrader&lt;/strong&gt;：个人量化的常青树。事件驱动、broker 抽象贴近真实下单（限价/市价/止损单）、文档社区成熟。适合：中低频股票/期货策略、需要逐 bar 撮合逻辑的场景。短板：性能一般（百万 bar 量级变慢）、多标的组合优化需要自己动手——它假设「策略是个体交易者」，不是「组合管理器」。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zipline / Zi-Reloaded&lt;/strong&gt;：Quantopian 遗产，&lt;code&gt;initialize/handle_data&lt;/code&gt; 范式与 Pipeline API（横截面因子批量计算）是其精华。适合：美股因子研究、喜欢 Pipeline 声明式风格的研究者。原版停更后用社区维护的 zi-reloaded；A 股数据适配需要自己处理（复权、涨跌停）——&lt;strong&gt;框架默认的市场是美股，制度细节的空缺就是偏差的入口&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RQAlpha（米筐开源）&lt;/strong&gt;：国产框架里工程化最好的选择之一，A 股制度细节（T+1、涨跌停、停牌、分红送转）&lt;strong&gt;默认正确处理&lt;/strong&gt;——这是它相对舶来品的决定性优势。风格与 Zipline 相近，可配合米筐的 RQData 使用。适合：A 股中低频策略的严肃回测。判断一个 A 股框架是否合格的三道测试题：跌停日卖出成交吗？分红后持仓股数变吗？次新上市首日能买吗？——RQAlpha 都答对。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JoinQuant/聚宽 &amp;amp; 米筐平台（在线）&lt;/strong&gt;：云端一体化（数据+研究+回测+模拟盘），jqdata API 在国内个人研究者中普及度最高。适合快速验证 A 股想法、不想搭数据管道的人。注意：&lt;strong&gt;平台锁定与导出成本&lt;/strong&gt;——研究资产尽早沉淀为本地代码与数据，把「平台」降级为「数据源」，否则多年的策略积累锁死在别人手里。&lt;/p&gt;
&lt;h2 id="向量化回测框架"&gt;向量化回测框架
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;VectorBT&lt;/strong&gt;：整列运算的极简回测（信号矩阵 → 组合模拟），速度比事件驱动快 2–3 个数量级，参数扫描（100 组均线的网格）是它的主场。短板：撮合模型简化（默认下一收盘价成交），&lt;strong&gt;成本与制度细节要自己保证正确&lt;/strong&gt;。适合：因子 idea 的快速筛选、参数稳健性热力图；不适合：精确执行逻辑的最终验证。&lt;/p&gt;
&lt;p&gt;正确用法是&lt;strong&gt;两级流水&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;第一级：VectorBT 海选（200 组参数 × 10 年，分钟级出热力图）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ 入围 5 组
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;第二级：RQAlpha/事件驱动精测（含真实成本、涨跌停、停牌，逐组复核）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ 最终 1–2 组进仿真盘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;只用第一级下结论&lt;/strong&gt;是最常见的自欺——向量化框架的乐观偏差（无成本、理想成交）叠加起来轻松虚增 5–10 个点年化。&lt;/p&gt;
&lt;h2 id="专项库不是回测框架但常被误当框架"&gt;专项库（不是回测框架，但常被误当框架）
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;QuantLib&lt;/strong&gt;：固定收益与衍生品定价的工业级库（利率曲线构建、波动率曲面、奇异期权、债券久期凸性）。C++ 内核 Python 绑定。适合做衍生品/固收的人；股票多因子研究者用不到——别为了「专业感」引入两倍于策略代码的依赖。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PyPortfolioOpt&lt;/strong&gt;：组合优化的教科书级实现：均值-方差、Black-Litterman、层次风险平价（HRP）、收缩协方差，全部几行调用。适合把&lt;a
 class="link"
 href="http://airyv.com/quant/mpt-mean-variance/"&gt;&lt;span class="markdown-link-inner"&gt;组合构建&lt;/span&gt;&lt;/a&gt;
章的方法直接落地。短板：约束表达力弱于专业优化器——复杂的行业/换手/暴露约束要用 cvxpy 自建（见&lt;a
 class="link"
 href="http://airyv.com/quant/portfolio-constraints/"&gt;&lt;span class="markdown-link-inner"&gt;约束优化&lt;/span&gt;&lt;/a&gt;
）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;其他值得认识的&lt;/strong&gt;：&lt;code&gt;qlib&lt;/code&gt;（微软开源，ML 量化流水线，见&lt;a
 class="link"
 href="http://airyv.com/quant/ml-strategies/"&gt;&lt;span class="markdown-link-inner"&gt;机器学习策略&lt;/span&gt;&lt;/a&gt;
）、&lt;code&gt;empyrical&lt;/code&gt;/&lt;code&gt;quantstats&lt;/code&gt;（绩效指标计算）、&lt;code&gt;riskfolio-lib&lt;/code&gt;（组合优化进阶）、&lt;code&gt;arctic&lt;/code&gt;（时序存储，见&lt;a
 class="link"
 href="http://airyv.com/quant/scheduling-databases/"&gt;&lt;span class="markdown-link-inner"&gt;调度与数据库&lt;/span&gt;&lt;/a&gt;
）。&lt;/p&gt;
&lt;h2 id="选型决策与自建的分界线"&gt;选型决策与自建的分界线
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;你的阶段&lt;/th&gt;
 &lt;th&gt;推荐&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;第一个回测，学习概念&lt;/td&gt;
 &lt;td&gt;Backtrader 或聚宽（在线）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;A 股日频多因子，要制度正确性&lt;/td&gt;
 &lt;td&gt;RQAlpha / 聚宽 + 本地 VectorBT 海选&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;参数扫描、因子海选&lt;/td&gt;
 &lt;td&gt;VectorBT + 自定义成本模型&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;期权/固收定价&lt;/td&gt;
 &lt;td&gt;QuantLib&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;组合权重计算&lt;/td&gt;
 &lt;td&gt;PyPortfolioOpt / cvxpy&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;什么时候自己写引擎？&lt;/strong&gt; 三个信号同时出现：框架的撮合假设与你交易的制度细节持续冲突（如集合竞价、批量撮合）；你需要在回测内做实时组合优化；框架成为研究吞吐的瓶颈。在此之前，&lt;strong&gt;「自研回测引擎」是工程快感、不是研究产出&lt;/strong&gt;——把同样的时间投入因子研究，期望收益高得多（见&lt;a
 class="link"
 href="http://airyv.com/quant/backtest-engine-design/"&gt;&lt;span class="markdown-link-inner"&gt;回测框架设计&lt;/span&gt;&lt;/a&gt;
：即便自建，也该先读懂框架处理了哪些偏差）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关联阅读&lt;/strong&gt;：&lt;a
 class="link"
 href="http://airyv.com/quant/backtest-biases/"&gt;&lt;span class="markdown-link-inner"&gt;回测偏差大全&lt;/span&gt;&lt;/a&gt;
 是评估任何框架的检查表——框架默认处理了哪几条、没处理哪几条；&lt;a
 class="link"
 href="http://airyv.com/quant/data-types/"&gt;&lt;span class="markdown-link-inner"&gt;数据工程&lt;/span&gt;&lt;/a&gt;
 决定框架之外你仍要自建的数据层。&lt;/p&gt;</description></item></channel></rss>