σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academy学习路线
Ctrl K
AO
+1.2k 位学习者
登录加入 ↗
学习路线
AO
+1.2k 位学习者
登录
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python 学习路线›模块 1 · 面向量化的 Python 基础›主题 1.21·~40分钟入门

包与项目结构

路线进度模块 1/11 · 主题 21/33
1.21 包与项目结构
—实验得分— / 100总 XP—连续天数—

从单个文件到装满模块的文件夹

项目变大后,单个文件就不够用了。包(package)是 Python 可作为一个整体导入的模块文件夹。在文件夹里放一个名为 __init__.py 的文件(可以是空的),其中每个 .py 文件就成为该包的模块,用点号表示:quant/pricing.py 是 quant.pricing,quant/data/loaders.py 是 quant.data.loaders。包里面的文件夹是子包,各自需要 __init__.py。

# A small project on disk
#
# quant-tools/
#   pyproject.toml
#   README.md
#   quant/
#     __init__.py
#     pricing.py
#     data/
#       __init__.py
#       loaders.py
#   tests/
#     test_pricing.py

# quant/pricing.py
def mid(bid, ask):
    return (bid + ask) / 2

# anywhere else in the project
from quant.pricing import mid
import quant.data.loaders

print(mid(184.0, 185.0))  # 184.5

可扩展的目录结构

把可导入的代码放在以项目命名的一个包文件夹里,其他内容放在它旁边而不是里面:测试放在 tests/,用 README.md 说明项目,用 pyproject.toml 给项目命名并列出依赖,数据或 notebook 放在各自的文件夹中。测试文件命名为 test_*.py,这样 pytest 之类的工具才能找到。名字清晰、职责单一的小模块(pricing.py、loaders.py)比一个冗长的 utils.py 更容易测试和复用。

# pyproject.toml (names the project and its dependencies)
#
# [project]
# name = "quant-tools"
# version = "0.1.0"
# requires-python = ">=3.11"
# dependencies = ["numpy"]

# tests/test_pricing.py: found automatically because of the name
from quant.pricing import mid

def test_mid():
    assert mid(184.0, 185.0) == 184.5

在包内部导入

在包内部,可以从顶层用完整路径导入(from quant.pricing import mid,绝对导入),也可以相对当前模块导入(from .pricing import mid,一个点表示同一个包,两个点表示上一级,相对导入)。绝对导入通常更清晰。__init__.py 在包第一次被导入时运行,因此可以重新导出用户需要的名字(from .pricing import mid),这样 import quant; quant.mid(...) 就能用。运行包内代码要用 python -m quant.data.loaders,而不是 python quant/data/loaders.py,这样带点的名字才能被解析。

# quant/__init__.py: runs on the first "import quant"
from .pricing import mid          # relative: same package

__all__ = ["mid"]                 # what "from quant import *" would give

# quant/data/loaders.py
from quant.pricing import mid     # absolute: always starts at the top
from .. import pricing            # relative: two dots = the parent package

# In a terminal, from the project folder:
#   python -m quant.data.loaders   (runs the module as part of the package)
#   pytest -q                      (finds tests/test_*.py)
# A file path and its module name are two spellings of one thing
path = "quant/data/loaders.py"
name = path[:-3].replace("/", ".")
print(name)                          # quant.data.loaders
print(name.split(".")[0])            # quant  (the top-level package)

# __init__.py stands for its folder
print("quant/__init__.py"[:-3].replace("/", "."))  # quant.__init__ -> the package is "quant"
缺少 __init__.py 是个悄无声息的陷阱Python 有时可以导入没有 __init__.py 的文件夹(“命名空间包”),但工具、测试运行器和安装程序对它的表现并不一致,在你电脑上能用的导入到别处可能失败。请给每个包文件夹都放一个 __init__.py。实验会让你找出包含代码却缺少它的文件夹。
  • 包是含有 __init__.py 的文件夹;quant/data/loaders.py 就是模块 quant.data.loaders。
  • 代码放在包里;测试、README、pyproject.toml 和数据放在旁边。
  • 优先使用绝对导入;用 python -m package.module 运行包内代码。

下一节:虚拟环境与 pip,让每个项目恰好拥有它所需的库。

实验:评分内容

  • 用 module_name 把文件路径转换为模块名25 分
  • 用 find_modules 列出项目中可导入的模块25 分
  • 用 missing_init 找出缺少 __init__.py 的文件夹25 分
  • 用 import_line 为模块写出导入语句25 分
资源管理器 · lab-21-1
▾ lab-21-1
…
bash · 浏览器内
learner@quantcraft:~/lab-21-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

lab-21-1 中的所有内容将恢复为初始文件,终端也会被清空。你当前的解答将丢失,且无法撤销。

将被重置
  • main.py → 初始代码
  • 终端历史与测试输出
  • 未提交的更改
将被保留
  • 实验最高得分
  • 你的 XP 与连续天数
  • 讲解进度与笔记

登录后即可运行你的代码。

所有讲解均可免费阅读。创建账户或登录后,即可运行代码、运行测试并提交此实验。

  • 浏览器内 IDE 与 bash 终端,无需安装
  • 即时评分、XP 以及你在学习路线中的位置
创建账户登录
或
使用 GitHub 继续