σμ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 学习路线›模块 2 · 用于市场数据的 NumPy 与 pandas›主题 2.1·~45分钟入门

NumPy 数组与 dtype

路线进度模块 2/11 · 主题 1/20
2.1 NumPy 数组与 dtype
—实验得分— / 100总 XP—连续天数—

为什么用数组,数组是什么

Python 列表可以装任何东西,所以灵活,但处理数字很慢:每个元素都是一个独立对象。NumPy 提供 ndarray,一块内存里依次排列着同一种类型的数字。在编译代码中对整块数据运算,通常比 Python 循环快几十倍,占用的内存也少得多。几乎所有量化库(pandas、SciPy、scikit-learn)都建立在它之上。按惯例用 import numpy as np 导入。

import numpy as np

# Create arrays
prices = np.array([184.25, 185.0, 183.2])
print(prices)                       # [184.25 185.   183.2 ]
print(np.zeros(3))                  # [0. 0. 0.]
print(np.arange(0, 10, 3))          # [0 3 6 9]
print(np.linspace(0, 1, 5))         # [0.   0.25 0.5  0.75 1.  ]

# An array knows its shape
table = np.array([[1, 2, 3], [4, 5, 6]])
print(table.shape, table.ndim, table.size)   # (2, 3) 2 6

创建数组

np.array(列表) 把列表(二维则用列表的列表)转换成数组。np.zeros(n) 和 np.ones(n) 创建填充好的数组,np.zeros((行, 列)) 接收一个形状元组。np.arange(起点, 终点, 步长) 与 range 类似,但允许浮点步长,且不包含终点;由于舍入误差,更推荐 np.linspace(起点, 终点, num),它恰好给出 num 个等间距的点,并且包含两端。每个数组都有 .shape(各维大小)、.ndim(维数)和 .size(元素总数)。

import numpy as np

# arange with floats can surprise; linspace gives exactly the points you ask for
print(len(np.arange(0, 1, 0.1)))     # 10  (1.0 is excluded)
print(len(np.linspace(0, 1, 11)))    # 11  (both ends included)

# Shapes and sizes
grid = np.zeros((3, 4))
print(grid.shape, grid.ndim, grid.size)   # (3, 4) 2 12
print(np.ones(2) * 5)                      # [5. 5.]

dtype:整个数组只有一种类型

每个数组都有一个 dtype:int64(整数)、float64(小数)、bool,以及更小或更大的变体,如 float32、int8。NumPy 根据数据选择 dtype:全是整数得到 int64,只要有一个小数就全部变成 float64,而 np.nan(非数,缺失值的标记)是浮点数,所以会强制 float64。可以用 dtype=... 自己指定,或用返回新数组的 .astype(...) 转换。更小的 dtype 省内存(float32 只占 float64 的一半),但会牺牲精度。

import numpy as np

print(np.array([1, 2, 3]).dtype)            # int64
print(np.array([1, 2.5, 3]).dtype)          # float64  (one decimal upgrades everything)
print(np.array([True, False]).dtype)        # bool
print(np.array([1, 2, np.nan]))             # [ 1.  2. nan]  (nan is a float)

# astype returns a new array; smaller dtypes use less memory
prices = np.zeros(1000)
print(prices.nbytes)                        # 8000
print(prices.astype(np.float32).nbytes)     # 4000
print(np.array(["1.5", "2"], dtype=float))  # [1.5 2. ]  (text converted to numbers)

类型转换的陷阱:截断与溢出

用 .astype(int) 把小数转成整数会向零截断,而浮点数无法精确表示大多数小数,所以 19.99 * 100 是 1998.9999999999998,被截断成 1998,少了一分钱。要把价格转换成整数分,应先四舍五入:np.round(prices * 100).astype(np.int64)。整数 dtype 的范围也是固定的,并且会悄悄回绕:int8 的范围是 -128 到 127,所以 100 * 2 变成 -56。金额和计数请用 int64;并记住整数用 / 相除总是得到浮点数,而 // 向下取整。

import numpy as np

# Truncation: astype(int) cuts the decimals off
print(np.array([1.9, -1.9]).astype(int))              # [ 1 -1]
print(19.99 * 100, int(19.99 * 100))                  # 1998.9999999999998 1998
print(np.round(np.array([19.99]) * 100).astype(np.int64))   # [1999]

# Overflow: an int8 wraps around silently
small = np.array([100, 50], dtype=np.int8)
print(small * 2)                                      # [-56 100]

# / always gives floats, // floors
counts = np.array([1, 2, 3])
print(counts / 2, counts // 2)                        # [0.5 1.  1.5] [0 1 1]
先看 shape 和 dtypeNumPy 代码出问题时,先打印所有相关数组的 .shape 和 .dtype:本该是 float64 却出现 int64,或形状是 (5, 1) 而不是 (5,),能解释大多数 bug。构建数组时优先用 NumPy 函数(np.linspace、np.asarray、astype),而不是 Python 循环;实验拒绝循环正是出于这个原因。
  • np.array、zeros、ones、arange、linspace 创建数组;.shape、.ndim、.size 描述数组。
  • 每个数组一种 dtype:int64、float64、bool;astype 转换成新数组。
  • astype(int) 会截断(先四舍五入);小整数 dtype 会悄悄回绕;nan 强制使用浮点数。

下一节:数组的索引与切片,选取行、列、窗口以及满足条件的值。

实验:评分内容

  • 用 make_grid 生成等间距的点25 分
  • 用 to_float_array 把混合的原始值转为浮点数25 分
  • 用 describe_array 报告形状、大小与 dtype25 分
  • 用 to_cents 安全地把价格转换为整数分25 分
资源管理器 · lab-34-1
▾ lab-34-1
…
bash · 浏览器内
learner@quantcraft:~/lab-34-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

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

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

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

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

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