σμ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.19·~40分钟中级

K 线图

路线进度模块 2/11 · 主题 19/20
2.19 K 线图
—实验得分— / 100总 XP—连续天数—

一张图里的四个价格

只画收盘价的折线图丢掉了一天的大部分信息。K线(蜡烛图)同时保留四个价格:开盘、最高、最低和收盘。粗的实体从开盘画到收盘,并按方向着色(收盘不低于开盘为绿色,否则为红色);细的影线从最低画到最高。一眼就能看出这一天走到了哪里、波动多大,以及买方还是卖方占了上风。

import numpy as np
import pandas as pd

df = pd.DataFrame(
    {
        "open":  [100.0, 103.0, 102.0, 104.0],
        "high":  [104.0, 105.0, 106.0, 104.5],
        "low":   [ 99.0, 101.0, 101.5, 101.0],
        "close": [103.0, 102.0, 105.5, 104.0],
    },
    index=pd.bdate_range("2026-03-02", periods=4),
)

# Green when the day closed at or above its open, red otherwise: one np.where on whole columns
colors = np.where(df["close"] >= df["open"], "green", "red")
print(colors.tolist())   # ['green', 'red', 'green', 'green']

计算实体

实体是一个矩形。它从开盘与收盘中较低的一个开始(df[["open", "close"]].min(axis=1) 按行取最小值),高度是绝对差 abs(close - open)。开盘价与收盘价相同的一天,实体高度为 0:这就是十字星,一根代表犹豫的蜡烛。把实体与整个区间 high - low 相比,可以看出这一天有多果断;对整列这样做,一行代码就能找出一年里所有的十字星。

body = pd.DataFrame({
    "bottom": df[["open", "close"]].min(axis=1),    # the lower of open and close, row by row
    "height": (df["close"] - df["open"]).abs(),
})
print(body)
#             bottom  height
# 2026-03-02   100.0     3.0
# 2026-03-03   102.0     1.0
# 2026-03-04   102.0     3.5
# 2026-03-05   104.0     0.0

# Body as a share of the day's range: the last day is a doji
share = body["height"] / (df["high"] - df["low"])
print(share.round(2).tolist())          # [0.6, 0.25, 0.78, 0.0]
print((share <= 0.1).tolist())          # [False, False, False, True]

绘制:影线与柱

matplotlib 没有专门的K线函数,但两个简单的调用就够了。ax.vlines(x, ymin, ymax) 一次为每个 x 画一条竖线:这就是从最低到最高的影线。ax.bar(x, height, bottom=..., width=0.6, color=...) 为每个 x 画一根从 bottom 起的柱:这就是实体,color 接受每根柱一个颜色的列表。把蜡烛放在位置 0, 1, 2, ...(np.arange(len(df)))而不是日期上,周末就不会留下空隙。传入整列即可避免对每天的循环。

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
x = np.arange(len(df))
ax.vlines(x, df["low"], df["high"], color="black", linewidth=1)                       # the wicks
ax.bar(x, body["height"], bottom=body["bottom"], width=0.6, color=colors)               # the bodies

print(len(ax.collections), len(ax.patches))            # 1 4   one set of wicks, four bodies
print([p.get_y() for p in ax.patches])                  # [100.0, 102.0, 102.0, 104.0]   body bottoms
print(ax.collections[0].get_segments()[0].tolist())     # [[0.0, 99.0], [0.0, 104.0]]    the first wick, low to high
# Candles whose body is at most 10% of the day's range are dojis
doji = share <= 0.1
print(df.index[doji].strftime("%d %b").tolist())   # ['05 Mar']
图形可以被读回图表本身也是数据:ax.patches 保存柱,ax.collections 保存影线,它们的位置、大小和颜色都可以检查。测试 Axes 而不是像素,是自动验证绘图函数的方法,也是调试看起来不对的图表的方法。
  • 一根蜡烛显示开、高、低、收:实体从开盘到收盘,影线从最低到最高。
  • 实体底部是逐行的 min(open, close)(min(axis=1)),高度是 abs(close - open);实体为 0 就是十字星。
  • 所有影线用一次 ax.vlines、所有实体用一次 ax.bar(颜色列表)绘制,不要对每天循环。

下一节:直方图与分布,统计收益率落入各区间的频次。

实验:评分内容

  • 用 candle_colors 按涨跌方向给每根蜡烛上色25 分
  • 用 candle_body 计算每根蜡烛的实体25 分
  • 用 doji_days 找出犹豫不决的日子25 分
  • 用 draw_candles 在 Axes 上画出蜡烛25 分
资源管理器 · lab-52-1
▾ lab-52-1
…
bash · 浏览器内
learner@quantcraft:~/lab-52-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

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

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

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

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

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