σμ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.2·~35分钟入门

数组的索引与切片

路线进度模块 2/11 · 主题 2/20
2.2 数组的索引与切片
—实验得分— / 100总 XP—连续天数—

位置与切片,现在扩展到多个维度

数组的索引与列表一样:a[0] 是第一个元素,a[-1] 是最后一个,a[start:stop:step] 是在 stop 之前停止的切片。不同之处在于数组可以有多个维度,你要为每个维度各给一个索引或切片,用逗号隔开:m[行, 列]。单独的 : 表示“这一维的全部”,所以 m[:, 1] 是整个第二列,m[1](或 m[1, :])是整个第二行。负数从末尾数起,步长 -1 表示反向。

import numpy as np

a = np.array([10., 11., 12., 13., 14., 15.])
print(a[0], a[-1])           # 10.0 15.0
print(a[1:4])                # [11. 12. 13.]
print(a[-2:])                # [14. 15.]
print(a[::2])                # [10. 12. 14.]
print(a[::-1])               # [15. 14. 13. 12. 11. 10.]

# Two dimensions: one index or slice per dimension
m = np.arange(12).reshape(3, 4)
print(m[1, 2])               # 6
print(m[:, 1])               # [1 5 9]      the whole second column
print(m[-1, :])              # [ 8  9 10 11] the last row
print(m[0:2, 1:3])           # [[1 2]
                             #  [5 6]]

切片是视图,不是副本

与列表切片不同,NumPy 的基本切片不会复制数据:它是指向同一块内存的视图,因此通过它写入会改动原数组。这使得即使对巨大的数组切片也是瞬间完成,但也常让人意外:part = a[1:4]; part[0] = 99 也会改变 a[1]。需要独立数组时调用 .copy()。可以用 np.shares_memory(a, b) 检查。行、列、步长和反向切片都有同样的视图行为。

import numpy as np

a = np.array([10., 11., 12., 13., 14., 15.])

part = a[1:4]           # a view, no data copied
part[0] = 99
print(a)                # [10. 99. 12. 13. 14. 15.]   a changed too

safe = a[1:4].copy()    # an independent array
safe[0] = -1
print(a)                # [10. 99. 12. 13. 14. 15.]   unchanged

print(np.shares_memory(a, a[::2]))   # True
print(np.shares_memory(a, safe))     # False

布尔掩码与索引列表

对数组做比较会得到同样大小的布尔数组:r > 0 在收益为正的位置是 True。把这个掩码用作索引,r[r > 0],就只选出这些元素。条件用 &(与)、|(或)、~(非)组合,每个条件都要加括号,因为 Python 的 and/or 不能用于数组。整数列表或数组也可以,a[[0, 2, 5]] 会按该顺序取出恰好这些位置。用掩码或索引列表选择会复制数据,也可以通过掩码赋值:a[a > 3] = 0。

import numpy as np

r = np.array([0.01, -0.02, 0.03, -0.01, 0.0, 0.02])
print(r > 0)                        # [ True False  True False False  True]
print(r[r > 0])                     # [0.01 0.03 0.02]
print(r[(r > 0) & (r < 0.025)])     # [0.01 0.02]    parentheses are required
print(np.where(r > 0)[0])           # [0 2 5]        positions where it holds

# Pick by position, in any order
w = np.array([3.0, 9.0, 1.0, 7.0])
order = np.argsort(-w)              # positions from the largest value down
print(order[:2], w[order[:2]])      # [1 3] [9. 7.]

# Assign through a mask
counts = np.array([1, 2, 3, 4, 5, 6])
counts[counts > 3] = 0
print(counts)                       # [1 2 3 0 0 0]
import numpy as np

# Rows are days, columns are assets (AAPL, MSFT, GOOG)
R = np.array([[ 0.02, -0.01,  0.03],
              [ 0.01,  0.00,  0.02],
              [-0.03,  0.02, -0.01],
              [ 0.00,  0.01,  0.04]])

print(R[:, [0, 2]])             # the AAPL and GOOG columns, as a copy
print(R[R[:, 0] > 0])           # the days on which AAPL rose (whole rows)
print(R[R[:, 0] > 0].shape)     # (2, 3)
print(R[-2:, 1].mean())         # 0.015  last two days of MSFT
知道自己拿到的是视图还是副本基本切片(a[1:4]、m[:, 1]、a[::2])是视图;掩码和索引列表(a[a > 0]、a[[0, 2]])是副本。返回参数切片的函数,等于给调用者一扇通向其自身数据的窗口,之后的写入可能出乎意料地改动它。要有意识地选择:速度重要且数据只读时返回视图,否则用 .copy()。实验的测试会检查这两种行为。
  • 每维一个索引或切片:m[行, 列]、m[:, 1](一列)、m[-1](最后一行)、a[::-1]。
  • 基本切片是视图(写入会反映;用 .copy() 分离);掩码和索引列表生成副本。
  • 掩码:a[a > 0],用带括号的 &、|、~ 组合;np.argsort 给出排序后的位置。

下一节:向量化,用整个数组的运算取代 Python 循环。

实验:评分内容

  • 用 last_rows 取最近的几行25 分
  • 用 positive_values 只保留正值25 分
  • 用 every_kth 每隔 k 个取一个值25 分
  • 用 top_k_indices 找出最大的 k 个值的位置25 分
资源管理器 · lab-35-1
▾ lab-35-1
…
bash · 浏览器内
learner@quantcraft:~/lab-35-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

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

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

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

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

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