02 数学以及统计学回顾

金融大数据 · 核心基础

本章学习目标:为何数学是金融的基石?

欢迎大家。今天我们不讨论具体的经济模型,而是回到一切的原点:数学

在座的各位都具备扎实的数理基础,但我们将从一个全新的视角——金融应用——来重新审视这些工具。我们的目标是将抽象的数学符号,转化为解决实际金融问题的直觉和代码。

本章学习路线图

我们将分三步,构建起金融量化分析的数学大厦。

本章学习路线图 一个包含三个部分的路线图:线性代数、微积分和统计学。 金融量化分析的数学大厦 1. 线性代数 描述多维世界的语言 2. 微积分 捕捉动态变化的工具 3. 统计学 量化不确定性的科学

机器学习为何离不开数学?

机器学习,尤其是在金融领域的应用,本质上是一个数学优化问题。我们将理论、数据和目标,用数学语言串联起来。

机器学习的数学支柱 中心思想“金融机器学习”被三个支柱支撑:数据表示、模型构建与训练、结果评估。 金融机器学习 (本质是数学优化问题) 数据表示 线性代数 (向量, 矩阵) 模型构建与训练 微积分 (梯度, 优化) 结果评估 统计学 (期望, 方差, R²)

第一部分:线性代数回顾

线性代数:描述多维金融世界的语言

想象一下,你如何向计算机描述一个包含100只股票的投资组合?或者如何表示整个市场过去一年的每日收益率?

线性代数提供了一套优雅而高效的语言来完成这项任务。

  • 向量 (Vectors):表示有序的金融数据,如资产权重或价格序列。
  • 矩阵 (Matrices):表示二维数据集,如多只股票的收益率或协方差。
从金融概念到数学对象 图示显示一个投资组合被抽象成一个向量,而市场历史数据被抽象成一个矩阵。 投资组合 (Portfolio) AAPL: 60% GOOG: 30% MSFT: 10% w = [ 0.6 0.3 0.1 ] 市场收益率 (Returns) AAPL GOOG Day1: +0.5% -0.2% Day2: -0.1% +0.3% R= [ 0.005, -0.002 -0.001, 0.003 ]

基本构件 1:标量 (Scalar)

标量 是最简单的数学对象:一个单独的数字。

在金融语境中,它可以代表: - 无风险利率: \(r_f = 0.02\) - 某公司的股票价格: \(P_{AAPL} = 175.50\) - 一项资产的权重: \(w_1 = 0.4\)

我们通常用小写斜体字母表示标量,例如 \(a=1\)\(x=3.14\)

标量可视化 一条数轴,上面标记了多个整数点,并在1.5的位置有一个蓝点,表示一个标量值。 -2 -1 0 1 2 x = 1.5

基本构件 2:向量 (Vector)

向量 是一列有序的数字。这个“有序”的特性至关重要。

例如,一个两资产投资组合的权重向量: \[ \large{\mathbf{w} = \begin{bmatrix} 0.6 \\ 0.4 \end{bmatrix}} \] 这明确表示第一个资产(比如股票)占60%,第二个资产(比如债券)占40%。顺序不能颠倒。

我们通常用小写粗体字母(如 \(\mathbf{x}\))表示向量。其标准形式是一个用方括号包围的列。

\[ \large{\mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix}} \]

向量的几何直观:空间中的箭头

我们可以把一个 \(n\) 维向量看作是 \(n\) 维空间中的一个点,或者更直观地,一个从原点出发,指向该点的箭头

例如,向量 \(\mathbf{x} = \begin{bmatrix} 2 \\ 1 \end{bmatrix}\) 在二维空间中,代表从 \((0,0)\) 指向 \((2,1)\) 的箭头。

向量的几何表示 一个二维坐标系,其中一个从原点(0,0)指向点(2,1)的蓝色箭头代表向量x。 x₁ x₂ x = (0,0)

行向量 vs. 列向量

默认情况下,我们通常将向量视为列向量(如前页所示)。

通过转置 (Transpose) 操作(记为 \(T\)),我们可以将其变为行向量

\[ \large{\mathbf{x} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} \quad \xrightarrow{\text{Transpose}} \quad \mathbf{x}^T = \begin{bmatrix} x_1, x_2, \dots, x_n \end{bmatrix}} \]

这个看似简单的区分在矩阵运算中至关重要,它决定了向量之间如何相乘。

在 Python 中创建向量

接下来,我们将在 Python 中使用 NumPy 库来创建和操作向量。NumPy 是 Python 科学计算的核心库。

我们将演示: 1. 如何创建一个基本的 NumPy 数组来表示向量。 2. 如何明确区分行向量和列向量的维度。 3. 如何执行转置操作。

在 Python 中创建向量

在Python中,一个向量就是一个NumPy数组。

import numpy as np

# 向量 x =
x = np.array([1, 2])
print(f'向量 x: {x}')
print(f'向量 x 的维度: {x.shape}') # (2,)

# 要明确创建一个列向量 (2x1 矩阵), 可以这样做:
x_col = np.array([[1], [2]])
print(f'\n明确的列向量 x_col:\n{x_col}')
print(f'列向量的维度: {x_col.shape}') # (2, 1)

# 转置操作
x_row = x_col.T
print(f'\n转置后的行向量 x_row:\n{x_row}')
print(f'行向量的维度: {x_row.shape}') # (1, 2)
向量 x: [1 2]
向量 x 的维度: (2,)

明确的列向量 x_col:
[[1]
 [2]]
列向量的维度: (2, 1)

转置后的行向量 x_row:
[[1 2]]
行向量的维度: (1, 2)

向量加法:合并两种效应

假设一个投资组合的收益由两部分构成: 1. 市场整体变动带来的收益: \(\mathbf{r}_{\text{market}} = \begin{bmatrix} 0.02 \\ -0.01 \end{bmatrix}\) 2. 公司特有事件带来的收益: \(\mathbf{r}_{\text{firm}} = \begin{bmatrix} 0.005 \\ 0.015 \end{bmatrix}\)

总收益就是这两个向量的和,代表了两种效应的叠加。

向量加法的代数法则:逐元素相加

向量加法非常直观:将两个向量对应的元素相加。前提是两个向量的维度必须相同

\[ \large{\mathbf{x} + \mathbf{y} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} + \begin{bmatrix} y_1 \\ y_2 \\ \vdots \\ y_n \end{bmatrix} = \begin{bmatrix} x_1 + y_1 \\ x_2 + y_2 \\ \vdots \\ x_n + y_n \end{bmatrix}} \]

例如: \[ \large{\begin{bmatrix} 2 \\ 1 \end{bmatrix} + \begin{bmatrix} 0.5 \\ 1.5 \end{bmatrix} = \begin{bmatrix} 2 + 0.5 \\ 1 + 1.5 \end{bmatrix} = \begin{bmatrix} 2.5 \\ 2.5 \end{bmatrix}} \]

向量减法同理,也是逐元素相减。

向量加法的几何诠释:平行四边形法则

几何上,向量加法遵循“头尾相接”或“平行四边形”法则。将第二个向量的起点移动到第一个向量的终点,从原点到第二个向量终点的新箭头就是它们的和。

向量加法的几何表示 向量x和y通过平行四边形法则相加得到向量z。 x y x+y

向量加法在 Python 中的实现

NumPy 的设计使得向量运算和标量运算一样简单,使用 +- 运算符即可。

# 定义两个向量
x = np.array([1.0, 2.0]) 
y = np.array([0.5, 1.5])

# 向量加法
z_add = x + y
print(f'x + y = {z_add}')

# 向量减法
z_sub = x - y
print(f'x - y = {z_sub}')
x + y = [1.5 3.5]
x - y = [0.5 0.5]

标量与向量的乘法:缩放向量

假设你决定将某个投资策略的风险敞口(由向量 \(\mathbf{x}\) 代表)加倍。这在数学上如何表示?

这就是标量与向量的乘法:用一个标量 \(a\) 乘以一个向量 \(\mathbf{x}\)

\[ \large{a\mathbf{x} = a \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} = \begin{bmatrix} ax_1 \\ ax_2 \\ \vdots \\ ax_n \end{bmatrix}} \]

它的作用是缩放 (scale) 向量的长度,而不改变其基本方向。

标量乘法的几何效果

  • 如果 \(a > 1\):向量被拉长
  • 如果 \(0 < a < 1\):向量被缩短
  • 如果 \(a < 0\):向量的方向反转180度,并根据 \(|a|\) 的大小进行缩放。
标量乘法的几何效果 一个原始向量x,一个被2倍拉长的向量2x,以及一个方向相反且被-1倍缩短的向量-x。 x 2x -x

标量乘法的 Python 实现

NumPy 中,标量与向量的乘法就像普通数字乘法一样,使用 * 运算符。

import numpy as np

# 原始向量
x = np.array([1.0, 2.0]) 

# 标量
a1 = 2
a2 = -1.5

# 标量乘法
x1 = a1 * x
print(f'Original x = {x}')
print(f'   {a1} * x = {x1}')

x2 = a2 * x
print(f' {a2} * x = {x2}')
Original x = [1. 2.]
   2 * x = [2. 4.]
 -1.5 * x = [-1.5 -3. ]

线性组合:用基本向量构建一切

线性组合 (Linear Combination) 是线性代数中最核心的概念之一。它是将我们刚学过的两种运算——向量加法和标量乘法——结合起来。

给定一组向量 \(\{\mathbf{v}_1, \mathbf{v}_2, \dots, \mathbf{v}_k\}\) 和一组标量 \(\{c_1, c_2, \dots, c_k\}\),它们的线性组合是: \[ \large{\mathbf{z} = c_1\mathbf{v}_1 + c_2\mathbf{v}_2 + \dots + c_k\mathbf{v}_k} \] 金融应用:一个投资组合的总回报,就是其持有的每项资产回报向量(\(\mathbf{v}_i\))按其投资权重(\(c_i\))进行的线性组合。

向量的点积:衡量“一致性”

点积 (Dot Product),也称内积 (Inner Product),是两个向量之间最重要的运算之一。它将两个维度相同的向量相乘,得到一个标量

假设我们有两个向量: - 投资组合权重向量 \(\mathbf{w} = \begin{bmatrix} 0.6 \\ 0.3 \\ 0.1 \end{bmatrix}\) - 资产预期收益率向量 \(\mathbf{r} = \begin{bmatrix} 0.10 \\ 0.08 \\ 0.05 \end{bmatrix}\)

投资组合的总预期收益率就是这两个向量的点积。

点积的计算公式

点积的计算方法是:将两个向量的对应元素相乘,然后将结果相加。

\[ \large{\mathbf{x}^T \mathbf{y} = \mathbf{x} \cdot \mathbf{y} = \sum_{i=1}^n x_i y_i = x_1y_1 + x_2y_2 + \dots + x_ny_n} \]

例如: \(\mathbf{x} = \begin{bmatrix} 1 \\ 0 \\ 2 \end{bmatrix}\), \(\mathbf{y} = \begin{bmatrix} -1 \\ -5 \\ 3 \end{bmatrix}\)

\[ \large{\mathbf{x}^T \mathbf{y} = (1 \times -1) + (0 \times -5) + (2 \times 3) = -1 + 0 + 6 = 5} \]

点积的几何意义:投影与角度

点积的真正威力在于它的几何意义。它与两个向量之间的夹角 \(\theta\) 密切相关: \[ \large{\mathbf{x}^T \mathbf{y} = \lVert\mathbf{x}\rVert \lVert\mathbf{y}\rVert \cos(\theta)} \] 这告诉我们: - 若 \(\mathbf{x}^T \mathbf{y} > 0\) (\(\cos\theta > 0\)):向量方向大致相同 (夹角 \(< 90^\circ\))。 - 若 \(\mathbf{x}^T \mathbf{y} = 0\) (\(\cos\theta = 0\)):向量正交 (Orthogonal),即垂直 (夹角 \(= 90^\circ\))。 - 若 \(\mathbf{x}^T \mathbf{y} < 0\) (\(\cos\theta < 0\)):向量方向大致相反 (夹角 \(> 90^\circ\))。

金融直觉:如果两只股票的每日收益率向量点积为正,说明它们倾向于同向变动。

点积几何意义的可视化

点积衡量了一个向量在另一个向量方向上的投影长度。

点积的投影几何意义 向量y在向量x上的投影。点积的大小与这个投影的长度有关。 x y θ y在x上的投影 (长度 = ||y|| cos(θ))

点积在 Python 中的实现

NumPy 提供了多种方式计算点积。在现代 Python (3.5+) 和 NumPy 中,推荐使用 @ 运算符,因为它最清晰地表达了数学意图。

x = np.array([1,  2,  3]) 
y = np.array([-1, -5, 3])

# 方法 1: 使用 @ 运算符 (推荐)
dot_product_1 = x @ y
print(f'使用 @ 运算符: {dot_product_1}')

# 方法 2: 使用 np.dot() 函数
dot_product_2 = np.dot(x, y)
print(f'使用 np.dot(): {dot_product_2}')

# 方法 3: 逐元素相乘再求和 (展示了其定义)
dot_product_3 = np.sum(x * y)
print(f'逐元素相乘再求和: {dot_product_3}')
使用 @ 运算符: -2
使用 np.dot(): -2
逐元素相乘再求和: -2

向量范数:衡量向量的“大小”或“长度”

我们如何量化一个向量的“大小”?例如,一个代表投资组合每日收益波动的向量,我们如何衡量其整体波动幅度?

范数 (Norm) 就是一个衡量向量大小的函数,记作 \(\lVert\mathbf{x}\rVert\)。它必须满足三个性质: 1. 正定性\(\lVert\mathbf{x}\rVert \ge 0\),且仅当 \(\mathbf{x} = \mathbf{0}\) 时等号成立。 2. 齐次性\(\lVert k\mathbf{x}\rVert = |k| \lVert\mathbf{x}\rVert\)。 3. 三角不等式\(\lVert\mathbf{x} + \mathbf{y}\rVert \le \lVert\mathbf{x}\rVert + \lVert\mathbf{y}\rVert\)

L1 范数:曼哈顿距离

L1 范数 (或称 Manhattan Norm) 是向量中所有元素绝对值之和

\[ \large{\lVert\mathbf{x}\rVert_1 = \sum_{i=1}^n |x_i|} \]

直观理解:想象在像曼哈顿这样的棋盘格城市中,从原点到一个点必须沿着街道走,L1范数就是你需要走过的总街区数。

例子: \(\mathbf{x} = \begin{bmatrix} 1 \\ -2 \end{bmatrix}\) \[ \large{\lVert\mathbf{x}\rVert_1 = |1| + |-2| = 1 + 2 = 3} \]

在机器学习中,L1范数常用于特征选择(Lasso回归),因为它倾向于产生稀疏解(许多权重为零)。

L2 范数:欧几里得距离

L2 范数 (或称 Euclidean Norm) 是我们最熟悉的“距离”概念。它是向量元素平方和的平方根

\[ \large{\lVert\mathbf{x}\rVert_2 = \sqrt{\sum_{i=1}^n x_i^2}} \] 几何意义:它就是从原点到向量所指向的点的直线距离

例子: \(\mathbf{x} = \begin{bmatrix} 1 \\ -2 \end{bmatrix}\) \[ \large{\lVert\mathbf{x}\rVert_2 = \sqrt{1^2 + (-2)^2} = \sqrt{1 + 4} = \sqrt{5} \approx 2.236} \]

如果没有特别指明,通常所说的“范数”或“向量长度”都指L2范数。

L1 vs. L2 范数可视化

L1 和 L2 范数的差异可以通过“单位球”的形状直观地理解,即所有范数值为1的点的集合。

L1和L2范数的单位球 两个坐标系,左边显示L1范数的单位球(一个菱形),右边显示L2范数的单位球(一个圆形)。 L1 范数: ||x||₁ = 1 (菱形/Diamond) L2 范数: ||x||₂ = 1 (圆形/Circle)

范数在 Python 中的计算

NumPylinalg 模块可以方便地计算各种范数,通过 ord 参数指定范数的阶数。

x = np.array([1, -2, 2])

# L1 范数 (ord=1)
l1_norm = np.linalg.norm(x, ord=1)
print(f'L1 Norm of x (|1|+|-2|+|2|): {l1_norm}')

# L2 范数 (ord=2 is default)
l2_norm = np.linalg.norm(x)
print(f'L2 Norm of x (sqrt(1²+2²+2²)): {l2_norm}')
L1 Norm of x (|1|+|-2|+|2|): 5.0
L2 Norm of x (sqrt(1²+2²+2²)): 3.0

单位向量:只关心方向

一个单位向量 (Unit Vector) 是一个长度(L2范数)为1的向量。它只保留了方向信息,而“抛弃”了大小信息。

如何将任意非零向量 \(\mathbf{x}\) 转换为单位向量 \(\hat{\mathbf{x}}\)将其除以它自身的L2范数即可\[ \large{\hat{\mathbf{x}} = \frac{\mathbf{x}}{\lVert\mathbf{x}\rVert_2}} \]

金融应用:在构建风险因子模型时,我们有时需要将因子“标准化”,使其具有单位方差,这与单位向量的概念密切相关。

向量相似度:欧几里得距离

我们如何量化两个投资策略(表示为向量)的相似性?

方法一:欧几里得距离

计算两个向量终点之间的直线距离。这可以通过计算差向量的L2范数来实现: \(d(\mathbf{x}, \mathbf{y}) = \lVert\mathbf{x} - \mathbf{y}\rVert_2\)。 - 距离越小,向量越相似。 - 这个方法同时考虑了大小方向。对于比较投资组合的绝对表现差异可能很有用。

向量相似度:余弦相似度

方法二:余弦相似度 (Cosine Similarity)

这个方法只关心方向,不关心大小。它计算两个向量之间夹角的余弦值。

\[ \large{\cos(\theta) = \frac{\mathbf{x}^T \mathbf{y}}{\lVert\mathbf{x}\rVert_2 \lVert\mathbf{y}\rVert_2}} \] - 结果在 [-1, 1] 之间。 - 1: 方向完全相同。 - 0: 方向正交(无关)。 - -1: 方向完全相反。

金融应用:比较两只股票收益率序列的变动模式时,余弦相似度比欧几里得距离更有用,因为它不受股票自身波动率大小的影响。

相似度计算可视化

下面的图表演示了这两种相似度度量的区别。

欧几里得距离 vs. 余弦相似度 两个场景对比:第一个场景两个向量方向相同但长度不同,第二个场景两个向量长度相似但方向不同。 方向一致,大小不同 x= y= 余弦相似度 = 1.0 欧氏距离 = 1.41 方向垂直,大小相近 x= y=[-1,2] 余弦相似度 = 0.0 欧氏距离 = 3.16

矩阵:二维数据表

矩阵 (Matrix) 是一个二维的数字数组,可以看作是向量的推广。我们用大写粗体字母表示矩阵,如 \(\mathbf{A}\)

一个 \(m \times n\) 的矩阵有 \(m\) 行和 \(n\) 列。 \[ \large{\mathbf{A} = \begin{bmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ a_{21} & a_{22} & \dots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \dots & a_{mn} \end{bmatrix}} \] 金融应用: - 一个 \(m \times n\) 矩阵可以表示 \(m\) 只股票过去 \(n\) 天的收益率数据。 - 一个 \(m \times m\)协方差矩阵可以表示 \(m\) 只股票收益率之间的联动关系。

矩阵在 Python 中的表示

我们同样使用 NumPy 数组来表示矩阵,此时它是一个二维数组。

# 构造一个 2x3 的矩阵 (2 行, 3 列)
A = np.array([
    [1,2,3],
    [-2, 12, 4]
])

print('矩阵 A:')
print(A)

# 获取矩阵的维度
print(f'\n矩阵 A 的维度 (行, 列): {A.shape}')
矩阵 A:
[[ 1  2  3]
 [-2 12  4]]

矩阵 A 的维度 (行, 列): (2, 3)

矩阵乘法:核心运算

矩阵乘法是线性代数中最常用也最复杂的运算之一。

  • 规则:要计算 \(\mathbf{C} = \mathbf{A}\mathbf{B}\),矩阵 \(\mathbf{A}\)列数必须等于矩阵 \(\mathbf{B}\)行数
  • 如果 \(\mathbf{A}\)\(m \times p\) 矩阵,\(\mathbf{B}\)\(p \times n\) 矩阵,则结果 \(\mathbf{C}\) 是一个 \(m \times n\) 矩阵。
  • 计算:结果矩阵 \(\mathbf{C}\) 中第 \(i\) 行第 \(j\) 列的元素 \((C)_{ij}\),是 \(\mathbf{A}\)\(i\) 行向量\(\mathbf{B}\)\(j\) 列向量点积\[ \large{(C)_{ij} = \sum_{k=1}^p a_{ik}b_{kj}} \]

矩阵乘法图解

计算 \(C_{11}\):取 A 的第 1 行和 B 的第 1 列,做点积。

矩阵乘法可视化 展示了矩阵A的第一行和矩阵B的第一列如何相乘得到结果矩阵C的第一个元素。 A (m × p) a₁₁ a₁₂ a₂₁ a₂₂ × B (p × n) b₁₁ b₁₂ b₂₁ b₂₂ = C (m × n) C₁₁ C₁₁ = (a₁₁ × b₁₁) + (a₁₂ × b₂₁)

矩阵乘法示例

给定 \(\mathbf{A} \in \mathbb{R}^{2 \times 3}\)\(\mathbf{B} \in \mathbb{R}^{3 \times 2}\),求 \(\mathbf{C} = \mathbf{AB}\)

\[ \large{\mathbf{A} = \begin{bmatrix} 1 & 0 & 2 \\ -2 & 12 & 4 \end{bmatrix}, \quad \mathbf{B} = \begin{bmatrix} 10 & -2 \\ 4 & 1 \\ 0 & 7 \end{bmatrix}} \]

\[ \large{C_{11} = (1 \cdot 10) + (0 \cdot 4) + (2 \cdot 0) = 10} \] \[ \large{C_{12} = (1 \cdot -2) + (0 \cdot 1) + (2 \cdot 7) = 12} \] \[ \large{C_{21} = (-2 \cdot 10) + (12 \cdot 4) + (4 \cdot 0) = 28} \] \[ \large{C_{22} = (-2 \cdot -2) + (12 \cdot 1) + (4 \cdot 7) = 4 + 12 + 28 = 44} \]

\[ \large{\mathbf{C} = \begin{bmatrix} 10 & 12 \\ 28 & 44 \end{bmatrix}} \]

矩阵乘法在 Python 中的实现

与向量点积一样,我们使用 @ 运算符进行矩阵乘法。NumPy 会自动处理行与列的点积。

A = np.array([[1,2,3], [-2, 12, 4]])
B = np.array([[10, -2],[1,2],[3,4]])

# 矩阵乘法
C = A @ B

print('矩阵 A (2x3):')
print(A)
print('\n矩阵 B (3x2):')
print(B)
print('\n结果 C = A @ B (2x2):')
print(C)
矩阵 A (2x3):
[[ 1  2  3]
 [-2 12  4]]

矩阵 B (3x2):
[[10 -2]
 [ 1  2]
 [ 3  4]]

结果 C = A @ B (2x2):
[[21 14]
 [ 4 44]]

矩阵与向量的乘法

矩阵与向量的乘法是矩阵乘法的特例。我们可以将一个 \(p\) 维列向量看作一个 \(p \times 1\) 的矩阵。

如果 \(\mathbf{A}\)\(m \times p\) 矩阵,\(\mathbf{x}\)\(p\) 维列向量,则结果 \(\mathbf{y} = \mathbf{Ax}\) 是一个 \(m\) 维列向量。

重要直觉:矩阵-向量乘法 \(\mathbf{Ax}\) 是将输入向量 \(\mathbf{x}\) 通过矩阵 \(\mathbf{A}\) 所描述的线性变换,映射到输出向量 \(\mathbf{y}\)

矩阵与标量的乘法

这与向量和标量的乘法类似:将矩阵中的每一个元素都与该标量相乘。

例如: \(a=2, \mathbf{B} = \begin{bmatrix} 10 & -2 \\ 4 & 1 \\ 0 & 7 \end{bmatrix}\) \[ \large{a\mathbf{B} = 2 \begin{bmatrix} 10 & -2 \\ 4 & 1 \\ 0 & 7 \end{bmatrix} = \begin{bmatrix} 20 & -4 \\ 8 & 2 \\ 0 & 14 \end{bmatrix}} \]

a = 2
B = np.array([[10, -2],[1,2],[3,4]])
aB = a * B
print(aB)
[[20 -4]
 [ 2  4]
 [ 6  8]]

矩阵的逆:线性代数中的“除法”

对于一个标量 \(a \neq 0\),它的逆是 \(a^{-1}\),满足 \(a \cdot a^{-1} = 1\)。 矩阵的逆(Inverse)是类似的概念。

  • 定义:对于一个方阵 (square matrix) \(\mathbf{A}\) (即 \(n \times n\) 矩阵),如果存在另一个 \(n \times n\) 矩阵 \(\mathbf{B}\) 使得 \(\mathbf{A}\mathbf{B} = \mathbf{B}\mathbf{A} = \mathbf{I}\),则称 \(\mathbf{A}\)可逆的 (invertible),并记 \(\mathbf{B} = \mathbf{A}^{-1}\)
  • \(\mathbf{I}\)单位矩阵 (Identity Matrix),一个主对角线为1,其余为0的方阵。它在线性代数中扮演着数字“1”的角色。

单位矩阵 (Identity Matrix)

单位矩阵 \(\mathbf{I}\) 在矩阵乘法中的作用,就像数字 1 在普通乘法中的作用。任何矩阵乘以单位矩阵,都等于其自身。 \[ \large{\mathbf{AI} = \mathbf{IA} = \mathbf{A}} \] \[ \large{\mathbf{I}_3 = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}} \]

为何矩阵求逆很重要?

矩阵求逆的核心应用是求解线性方程组

考虑一个简单的线性方程组: \[ \large{\mathbf{Ax} = \mathbf{b}} \] 这里,\(\mathbf{A}\) 是系数矩阵,\(\mathbf{x}\) 是未知变量向量,\(\mathbf{b}\) 是常数向量。

如果我们知道 \(\mathbf{A}^{-1}\),我们可以两边左乘 \(\mathbf{A}^{-1}\)\[ \large{\mathbf{A}^{-1}\mathbf{A}\mathbf{x} = \mathbf{A}^{-1}\mathbf{b}} \] \[ \large{\mathbf{I}\mathbf{x} = \mathbf{A}^{-1}\mathbf{b}} \] \[ \large{\mathbf{x} = \mathbf{A}^{-1}\mathbf{b}} \] 我们就直接解出了 \(\mathbf{x}\)

金融应用:在投资组合优化中,求解最优权重通常归结为求解一个大型线性方程组。

求解 2x2 矩阵的逆:一个例子

我们用一个例子来展示如何求解。求矩阵 \(\mathbf{A}\) 的逆 \(\mathbf{A}^{-1}\)\[ \large{\mathbf{A} = \begin{bmatrix} 4 & 7 \\ 2 & 6 \end{bmatrix}} \] 我们设所求的逆矩阵为: \[ \large{\mathbf{A}^{-1} = \begin{bmatrix} a & b \\ c & d \end{bmatrix}} \] 我们的目标是求解 \(a, b, c, d\)

求解 2x2 矩阵的逆:建立方程

根据定义 \(\mathbf{A}\mathbf{A}^{-1} = \mathbf{I}\)\[ \large{\begin{bmatrix} 4 & 7 \\ 2 & 6 \end{bmatrix} \begin{bmatrix} a & b \\ c & d \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}} \] 通过矩阵乘法,我们得到: \[ \large{\begin{bmatrix} 4a + 7c & 4b + 7d \\ 2a + 6c & 2b + 6d \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}} \] 这给了我们两组独立的 \(2 \times 2\) 线性方程组。

求解 2x2 矩阵的逆:求解方程组

第一组 (求解 a, c): 1. \(4a + 7c = 1\) 2. \(2a + 6c = 0 \implies a = -3c\)

将 (2) 代入 (1): \(4(-3c) + 7c = 1 \implies -12c + 7c = 1 \implies -5c = 1 \implies c = -0.2\) 代回 (2): \(a = -3(-0.2) = 0.6\)

第二组 (求解 b, d): 3. \(4b + 7d = 0 \implies b = -7d/4\) 4. \(2b + 6d = 1\)

将 (3) 代入 (4): \(2(-7d/4) + 6d = 1 \implies -3.5d + 6d = 1 \implies 2.5d = 1 \implies d = 0.4\) 代回 (3): \(b = -7(0.4)/4 = -0.7\)

求解 2x2 矩阵的逆:最终结果

我们解出了 \(a=0.6, b=-0.7, c=-0.2, d=0.4\)。 所以,逆矩阵为: \[ \large{\mathbf{A}^{-1} = \begin{bmatrix} 0.6 & -0.7 \\ -0.2 & 0.4 \end{bmatrix}} \]

验证: \[ \large{\mathbf{A}\mathbf{A}^{-1} = \begin{bmatrix} 4 & 7 \\ 2 & 6 \end{bmatrix} \begin{bmatrix} 0.6 & -0.7 \\ -0.2 & 0.4 \end{bmatrix} = \begin{bmatrix} 2.4-1.4 & -2.8+2.8 \\ 1.2-1.2 & -1.4+2.4 \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}} = \mathbf{I} \] 验证通过!

矩阵求逆的 Python 实现

在实际应用中,我们从不手动求逆。我们让计算机来做,这更快也更不容易出错。

A = np.array([[1,2],[3,4]])

# 使用 np.linalg.inv() 函数求逆
try:
    A_inv = np.linalg.inv(A)
    print('矩阵 A:')
    print(A)
    print('\n矩阵 A 的逆 A_inv:')
    print(np.round(A_inv, decimals=2))

    # 验证 A @ A_inv 是否为单位矩阵
    I = A @ A_inv
    print('\n验证 A @ A_inv (结果应接近单位矩阵):')
    # np.round() 用于处理微小的浮点数误差
    print(np.round(I, decimals=5))

except np.linalg.LinAlgError:
    print("矩阵 A 是奇异矩阵 (singular), 不可逆。")
矩阵 A:
[[1 2]
 [3 4]]

矩阵 A 的逆 A_inv:
[[-2.   1. ]
 [ 1.5 -0.5]]

验证 A @ A_inv (结果应接近单位矩阵):
[[1. 0.]
 [0. 1.]]

线性代数部分练习与应用

现在,让我们通过解决课本上的练习题来巩固我们学到的知识。这不仅是计算,更是将抽象概念应用到具体数字上的过程。

习题 2.5.1 向量运算 给定向量: \(\mathbf{x} = \begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix}, \quad \mathbf{y} = \begin{bmatrix} -0.5 \\ 2 \\ 0 \end{bmatrix}\)

请计算: 1. \(-2\mathbf{x}\) 2. \(\mathbf{x}+\mathbf{y}\) 3. \(\mathbf{x} \cdot \mathbf{y}\) (点积) 4. \(\mathbf{x}^T\mathbf{y}\)

练习 2.5.1 Python 求解

x = np.array([1.0, 2.0,3.0]) 
y = np.array([-0.5, 2, 0])

# 1. -2x
neg_2x = -2 * x
print(f'1. -2x = {neg_2x}')

# 2. x + y
x_plus_y = x + y
print(f'2. x + y = {x_plus_y}')

# 3. x . y (点积)
dot_product = x @ y
print(f'3. x . y (dot product) = {dot_product}')

# 4. x^T y
# 在 NumPy 中, x.T @ y 对于一维数组和 x @ y 结果相同
# 但为了概念清晰,我们明确其数学含义
transpose_dot = x.T @ y
print(f'4. x^T y = {transpose_dot}')

print('\n结论: 向量的点积 (x.y) 和 x^T y 在计算上是等价的。')
1. -2x = [-2. -4. -6.]
2. x + y = [0.5 4.  3. ]
3. x . y (dot product) = 3.5
4. x^T y = 3.5

结论: 向量的点积 (x.y) 和 x^T y 在计算上是等价的。

练习 2.5.2 矩阵运算

给定矩阵 \(\mathbf{A} = \begin{pmatrix} 0.3 & -2.9 & -10 \\ -3 & 1 & 0.5 \end{pmatrix}\) 和上题中的向量 \(\mathbf{x} = \begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix}\)

请回答和计算: 1. 该矩阵的维度是什么? 2. 计算 \(\mathbf{Ax}\)。 3. 求 \(\mathbf{A}^T\)

练习 2.5.2 Python 求解

import numpy as np

# A(2x3)
A = np.array([
    [0.3, -2.9, -10],
    [-3, 1, 0.5]
])

# x must have 3 elements to match A's columns
x = np.array([1.0, 2.0, 3.0]) 

# 1. 矩阵的维度
rows, cols = A.shape
print(f'1. 矩阵 A 的维度是: {rows} 行, {cols} 列')

# 2. 计算 Ax
# A(2x3) @ x(3,) -> 结果是 (2,) 向量
Ax = A @ x
print(f'\n2. Ax = {Ax}')
print(f'   计算过程 (第一行): (0.3*1) + (-2.9*2) + (-10*3) = {0.3 * 1 - 2.9 * 2 - 10 * 3}')
print(f'   计算过程 (第二行): (-3*1) + (1*2) + (0.5*3) = {-3 * 1 + 1 * 2 + 0.5 * 3}')

# 3. 求 A^T
A_T = A.T
print(f'\n3. A 的转置 A^T 是:\n{A_T}')
print(f'   A^T 的维度是: {A_T.shape}')
1. 矩阵 A 的维度是: 2 行, 3 列

2. Ax = [-35.5   0.5]
   计算过程 (第一行): (0.3*1) + (-2.9*2) + (-10*3) = -35.5
   计算过程 (第二行): (-3*1) + (1*2) + (0.5*3) = 0.5

3. A 的转置 A^T 是:
[[  0.3  -3. ]
 [ -2.9   1. ]
 [-10.    0.5]]
   A^T 的维度是: (3, 2)

第二部分:微积分回顾

微积分:捕捉金融世界的动态变化

金融市场瞬息万变。资产价格、利率、风险,所有这些都不是静止的。我们如何描述和分析这些变化

微积分,特别是微分,是研究“变化率”的数学语言。

  • 导数 (Derivative):衡量当一个变量发生微小变化时,另一个函数变量会如何响应。
  • 梯度 (Gradient):导数在多维空间中的推广,它指向函数增长最快的方向。

这对于金融中的优化问题——例如,最大化收益或最小化风险——至关重要。

一维微分:函数的变化率

微分的直观意义是函数在某一点的瞬时变化率,也就是该点切线的斜率

函数 \(f(x)\)\(x_0\) 处的微分(或导数)记为 \(f'(x_0)\)\(\frac{df}{dx}|_{x_0}\)。它描述了当 \(x\)\(x_0\) 附近发生一个极小的变动时,\(f(x)\) 相应的变化量。

金融应用:期权定价中的 “Delta” 就是期权价格(函数)相对于标的资产价格(变量)的导数。它告诉我们股票价格每变动1美元,期权价格会变动多少。

常见函数的导数

以下是一些我们需要熟记的求导法则: 1. 常数: \(f(x) = c \implies f'(x) = 0\) 2. 线性函数: \(f(x) = ax \implies f'(x) = a\) 3. 幂函数: \(f(x) = x^n \implies f'(x) = nx^{n-1}\) 4. 加法法则: \((f+g)' = f' + g'\) 5. 乘法法则: \((fg)' = f'g + fg'\) 6. 自然对数: \(f(x) = \ln(x) \implies f'(x) = \frac{1}{x}\) 7. 指数函数: \(f(x) = e^x \implies f'(x) = e^x\)

链式法则:求解复合函数的导数

当我们处理嵌套函数(复合函数)时,例如 \(f(g(x))\),我们需要使用链式法则 (Chain Rule)

\[ \large{\frac{d}{dx}f(g(x)) = f'(g(x)) \cdot g'(x)} \]

直观解释:“外层函数的导数(保持内层不变)”乘以“内层函数的导数”。

例子:求 \(h(x) = (x^2+1)^3\) 的导数。 - 外层函数 \(f(g) = g^3 \implies f'(g) = 3g^2\) - 内层函数 \(g(x) = x^2+1 \implies g'(x) = 2x\) - \(h'(x) = f'(g(x)) \cdot g'(x) = 3(x^2+1)^2 \cdot (2x) = 6x(x^2+1)^2\)

多维微分:梯度 (Gradient)

当函数有多个输入变量时,例如 \(f(x_1, x_2, \dots, x_n)\),我们如何描述它的变化?

我们引入偏导数 (Partial Derivative) \(\frac{\partial f}{\partial x_k}\),它表示当只有变量 \(x_k\) 发生变动而其他变量保持不变时,函数 \(f\) 的变化率。

将所有偏导数收集到一个向量中,就得到了梯度 (Gradient),记为 \(\nabla f(\mathbf{x})\)\[ \large{\nabla f(\mathbf{x}) = \begin{bmatrix} \frac{\partial f}{\partial x_1} \\ \frac{\partial f}{\partial x_2} \\ \vdots \\ \frac{\partial f}{\partial x_n} \end{bmatrix}} \]

梯度的几何意义:最陡峭的登山路径

梯度向量 \(\nabla f(\mathbf{x})\) 指向函数 \(f\) 在点 \(\mathbf{x}\) 处增长最快的方向。

梯度的几何意义 一个表示山丘的等高线图。在某一点上,梯度向量指向最陡峭的上坡方向,负梯度指向最陡峭的下坡方向。 当前位置 (x) ∇f(x) (最陡峭上坡) -∇f(x) (最陡峭下坡)

梯度下降法:机器学习的引擎

这个“最陡峭下坡”的概念是机器学习模型训练的核心算法——梯度下降 (Gradient Descent)——的基础。

为了找到一个函数(例如,模型的“损失函数”)的最小值,我们从一个随机点开始,然后反复地沿着负梯度方向小步移动。

\[ \large{\mathbf{x}_{\text{new}} = \mathbf{x}_{\text{old}} - \eta \nabla f(\mathbf{x}_{\text{old}})} \]

  • \(\eta\) (eta) 是学习率 (learning rate),控制我们每一步走多远。

这个简单的迭代过程,是训练从线性回归到深度神经网络等众多模型的基础。

寻找局部最大/最小值

一个可微函数的局部最大值或最小值(统称为极值点)在哪里出现?

  • 一维情况:在 \(f'(x_0) = 0\) 的点。即函数切线斜率为0(水平)的地方。
  • 多维情况:在 \(\nabla f(\mathbf{x}_0) = \mathbf{0}\) 的点。即梯度为零向量,在任何方向上函数值的瞬时变化率都为0。

这个条件是函数取得极值的必要条件 (Necessary Condition),但不是充分条件 (Sufficient Condition)。一个梯度为0的点也可能是鞍点。

寻找极值的例子

我们来看一个函数 \(f(x) = x^3 - 6x^2 + 5x + 12\)

  1. 求导\(f'(x) = 3x^2 - 12x + 5\)
  2. 令导数为0\(3x^2 - 12x + 5 = 0\)
  3. 求解:使用求根公式 \(x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}\) \[ \large{x = \frac{12 \pm \sqrt{(-12)^2 - 4(3)(5)}}{2(3)} = \frac{12 \pm \sqrt{144 - 60}}{6} = \frac{12 \pm \sqrt{84}}{6}} \] 所以极值点大约在 \(x \approx 0.47\)\(x \approx 3.53\)

极值点可视化

import numpy as np
import matplotlib.pyplot as plt

def f(x):
    return x**3 - 6*x**2 + 5*x + 12

# 求解导数为0的点
# f'(x) = 3x^2 - 12x + 5 = 0
roots = np.roots([3, -12, 5])
x_max, x_min = np.sort(roots)

# 绘图
x_vals = np.linspace(-1, 5, 400)
y_vals = f(x_vals)


plt.figure(figsize=(10, 6))
plt.plot(x_vals, y_vals, label='$f(x) = x^3 - 6x^2 + 5x + 12$', color='#0A369D')
plt.plot(x_max, f(x_max), 'o', color='#F79F79', markersize=8, label=f'局部最大值 at x={x_max:.2f}')
plt.plot(x_min, f(x_min), 'o', color='#228B22', markersize=8, label=f'局部最小值 at x={x_min:.2f}')

plt.title('函数及其局部极值点', fontsize=16)
plt.xlabel('x', fontsize=12)
plt.ylabel('f(x)', fontsize=12)
plt.axhline(0, color='gray', linestyle='--', linewidth=0.5)
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend(fontsize=12)
plt.show()
Figure 1: 函数 f(x) = x³ - 6x² + 5x + 12 的局部极值点

练习 2.5.2.1 微积分计算

给定函数 \(f(x_1, x_2) = -5x_1^3 - x_2^2 + x_1x_2 - 5\)

\(x_1=5, x_2=-1\) 时,求: 1. \(\frac{\partial f(x_1, x_2)}{\partial x_1}\) 2. \(\nabla f(x_1, x_2)\)

练习 2.5.2.1 手动求解

1. 求关于 \(x_1\) 的偏导数\(x_2\) 看作常数,对 \(x_1\) 求导: \[ \large{\frac{\partial f}{\partial x_1} = \frac{\partial}{\partial x_1}(-5x_1^3 - x_2^2 + x_1x_2 - 5)} \] \[ \large{= -5(3x_1^2) - 0 + (1 \cdot x_2) - 0 = -15x_1^2 + x_2} \] 代入 \(x_1=5, x_2=-1\)\[ \large{\frac{\partial f}{\partial x_1} \bigg|_{(5, -1)} = -15(5^2) + (-1) = -15(25) - 1 = -375 - 1 = -376} \]

练习 2.5.2.1 手动求解 (续)

2. 求梯度 首先求关于 \(x_2\) 的偏导数 (把 \(x_1\) 看作常数): \[ \large{\frac{\partial f}{\partial x_2} = \frac{\partial}{\partial x_2}(-5x_1^3 - x_2^2 + x_1x_2 - 5)} \] \[ \large{= 0 - 2x_2 + (x_1 \cdot 1) - 0 = -2x_2 + x_1} \] 梯度向量是: \[ \large{\nabla f(x_1, x_2) = \begin{bmatrix} \frac{\partial f}{\partial x_1} \\ \frac{\partial f}{\partial x_2} \end{bmatrix} = \begin{bmatrix} -15x_1^2 + x_2 \\ -2x_2 + x_1 \end{bmatrix}} \] 代入 \(x_1=5, x_2=-1\)\[ \large{\nabla f(5, -1) = \begin{bmatrix} -15(5^2) + (-1) \\ -2(-1) + 5 \end{bmatrix} = \begin{bmatrix} -376 \\ 2 + 5 \end{bmatrix} = \begin{bmatrix} -376 \\ 7 \end{bmatrix}} \]

练习 2.5.2.1 Python 求解 (使用 SymPy)

我们可以使用符号计算库 SymPy 来验证我们的结果。

import sympy as sp

# 定义符号变量
x1, x2 = sp.symbols('x1 x2')

# 定义函数
f = -5*x1**3 - x2**2 + x1*x2 - 5

# 1. 求关于 x1 的偏导数
df_dx1 = sp.diff(f, x1)
print(f'df/dx1 = {df_dx1}')

# 代入数值
val_df_dx1 = df_dx1.subs({x1: 5, x2: -1})
print(f'在 (5, -1) 处 df/dx1 的值为: {val_df_dx1}')

# 2. 求梯度
grad_f = [sp.diff(f, var) for var in (x1, x2)]
print(f'\n梯度向量 ∇f = {grad_f}')

# 代入数值
val_grad_f = [expr.subs({x1: 5, x2: -1}) for expr in grad_f]
print(f'在 (5, -1) 处 ∇f 的值为: {val_grad_f}')
df/dx1 = -15*x1**2 + x2
在 (5, -1) 处 df/dx1 的值为: -376

梯度向量 ∇f = [-15*x1**2 + x2, x1 - 2*x2]
在 (5, -1) 处 ∇f 的值为: [-376, 7]

第三部分:统计学回顾

统计学:在不确定性中寻找规律

金融市场充满了不确定性随机性。明天的股价是多少?下个季度的GDP增长率如何?我们无法精确预测。

统计学是科学地处理不确定性的工具。它帮助我们: - 描述数据:用均值、方差等指标总结数据的特征。 - 推断关系:用相关性、回归等方法发现变量间的联系。 - 量化风险:概率论是衡量和管理金融风险的基础。

随机变量:不确定的数值结果

随机变量 (Random Variable) 是一个其数值取决于随机事件结果的变量。我们通常用大写字母表示,如 \(X\)

  • 离散随机变量:只能取有限个或可数个值。
    • 例子:掷骰子的点数 (1, 2, 3, 4, 5, 6);一天内某支股票上涨的天数。
  • 连续随机变量:可以取某一区间内的任何值。
    • 例子:明天S&P 500指数的收益率;一家公司未来的盈利。

随机变量的一个具体实现值(观测值)用小写字母表示,如 \(x_i\)

期望:随机变量的“平均”取值

期望 (Expectation) 或期望值 \(E(X)\),是随机变量 \(X\) 所有可能取值按其概率加权的平均值。它是对随机变量中心趋势的度量。

  • 离散型\(E(X) = \sum_{k} x_k p(x_k)\)
    • 例子:掷一个公平骰子,期望值是 \(1\cdot\frac{1}{6} + 2\cdot\frac{1}{6} + \dots + 6\cdot\frac{1}{6} = 3.5\)
  • 连续型\(E(X) = \int_{-\infty}^{\infty} x f(x) dx\),其中 \(f(x)\) 是概率密度函数。

在金融中,预期收益率 (Expected Return) 就是资产未来收益率这个随机变量的期望值。

样本均值 vs. 期望

在现实世界中,我们通常不知道真实的概率分布,所以无法计算理论上的期望 \(E(X)\)

我们能做的是从总体中抽取一个样本 (sample) \(\{x_1, x_2, \dots, x_n\}\),然后计算样本均值 (sample mean) \(\bar{x}\)\[ \large{\bar{x} = \frac{1}{n}\sum_{i=1}^n x_i} \] 根据大数定律,当样本量 \(n\) 足够大时,样本均值 \(\bar{x}\) 会非常接近总体的期望 \(E(X)\)

方差:衡量风险与波动

方差 (Variance),记为 \(\text{Var}(X)\)\(\sigma^2\),衡量了随机变量的取值与其期望值之间的偏离程度。方差越大,数据点越分散,不确定性(风险)越高。

  • 理论方差 (概率论中): \[ \large{\text{Var}(X) = E[(X - E(X))^2] = E(X^2) - [E(X)]^2} \]
  • 样本方差 (统计学中): \[ \large{s^2 = \frac{1}{n-1}\sum_{i=1}^n (x_i - \bar{x})^2} \] 注意分母是 \(n-1\),这是为了对总体方差进行无偏估计

标准差 (Standard Deviation) \(\sigma = \sqrt{\text{Var}(X)}\),是方差的平方根,其单位与原始数据相同,更易于解释。

偏差 (Bias) 与 方差 (Variance)

在评估一个统计模型时,我们关心两种主要的误差来源:偏差方差

  • 偏差 (Bias):模型的平均预测真实值之间的差距。高偏差意味着模型过于简单,未能捕捉数据规律(欠拟合)。
  • 方差 (Variance):模型在不同训练数据集上预测结果的变动程度。高方差意味着模型对训练数据过于敏感,连噪声都学进去了(过拟合)。

偏差-方差的权衡

一个好的模型需要在偏差和方差之间取得平衡。

偏差-方差权衡 三个靶子展示了理想模型、欠拟合模型和过拟合模型的射击结果。 低偏差, 低方差 (理想模型) 高偏差, 低方差 (欠拟合) 低偏差, 高方差 (过拟合)

相关性:衡量线性关系

相关性 (Correlation) 是量化两个变量之间变动一致性程度的指标。

  • 正相关:一个变量增加时,另一个变量也倾向于增加。
  • 负相关:一个变量增加时,另一个变量倾向于减少。
  • 不相关:两个变量之间没有明显的线性关系。

重要警告:相关性 \(\neq\) 因果性! (Correlation does not imply causation!) 一个经典的例子:夏天的冰淇淋销量和溺水人数高度正相关,但这不意味着吃冰淇淋会导致溺水。背后隐藏的变量是“天气炎热”。

相关性可视化

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
x = np.random.rand(50)

# Positive Correlation
y1 = x + np.random.normal(0, 0.1, 50)
# No Correlation
y2 = np.random.rand(50)
# Negative Correlation
y3 = -x + np.random.normal(0, 0.1, 50)


fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5), sharex=True, sharey=True)

ax1.scatter(x, y1, alpha=0.7, c='#0A369D')
corr1 = np.corrcoef(x, y1)[0, 1]
ax1.set_title(f'正相关 (ρ ≈ {corr1:.2f})', fontsize=16)

ax2.scatter(x, y2, alpha=0.7, c='#888888')
corr2 = np.corrcoef(x, y2)[0, 1]
ax2.set_title(f'不相关 (ρ ≈ {corr2:.2f})', fontsize=16)

ax3.scatter(x, y3, alpha=0.7, c='#DC143C')
corr3 = np.corrcoef(x, y3)[0, 1]
ax3.set_title(f'负相关 (ρ ≈ {corr3:.2f})', fontsize=16)

for ax in [ax1, ax2, ax3]:
    ax.set_xlabel('X')
    ax.grid(True, linestyle='--', alpha=0.6)
ax1.set_ylabel('Y')

plt.tight_layout()
plt.show()
Figure 2: 正相关、不相关与负相关

Pearson 相关系数

Pearson 相关系数 \(\rho\) 是衡量两个连续变量之间线性关系强度的最常用指标。

\[ \large{\rho_{X,Y} = \frac{\sum_{i=1}^n (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^n (x_i - \bar{x})^2} \sqrt{\sum_{i=1}^n (y_i - \bar{y})^2}} = \frac{\text{Cov}(X,Y)}{\sigma_X \sigma_Y}} \] - \(\rho\) 的取值范围是 \([-1, 1]\)。 - \(|\rho|\) 越接近 1,线性关系越强。 - \(\rho=1\):完全正相关。 - \(\rho=-1\):完全负相关。 - \(\rho \approx 0\):没有线性关系。

回归分析中的重要指标

在用模型(例如线性回归)进行预测时,我们需要一些指标来评估模型的好坏。这些指标都围绕着残差 (Residual)——真实值与预测值之间的差异——来构建。

  • 残差平方和 (RSS): 衡量模型整体误差的大小。
  • 总离差平方和 (TSS): 衡量数据本身的总波动。
  • 判定系数 (R²): 衡量模型解释了数据总波动的百分比。

残差平方和 (RSS) vs. 总离差平方和 (TSS)

\[ \text{RSS} = \sum_{i=1}^n (y_i - \hat{y}_i)^2 \quad (\text{模型未能解释的方差}) \] \[ \text{TSS} = \sum_{i=1}^n (y_i - \bar{y})^2 \quad (\text{数据总方差}) \]

  • TSS 代表了如果我们只用最简单的模型(即用均值 \(\bar{y}\) 去预测所有 \(y_i\))时,会产生的总误差。它为我们提供了一个比较基准。
  • RSS 是我们的复杂模型预测后,剩下的误差。
  • 一个好模型的 RSS 应该远小于 TSS。

判定系数 R²

判定系数 (Coefficient of Determination, R²) 是衡量模型拟合优度的核心指标。它表示因变量 \(y\) 的总变异中,可以被自变量 \(x\) 解释的比例

\[ \large{R^2 = 1 - \frac{\text{RSS}}{\text{TSS}} = \frac{\text{TSS} - \text{RSS}}{\text{TSS}}} \] - \(R^2\) 的取值范围通常在 [0, 1] 之间。 - \(R^2 = 0.9\) 意味着模型解释了数据总方差的 90%。 - \(R^2\) 越高,模型的解释能力越强。 - 优点:它是一个相对值,克服了 MSE 没有上界的缺点,使得不同模型和数据集之间的比较成为可能。

统计学部分练习:真实金融数据分析

理论知识需要通过实践来巩固。现在我们不再使用书上的小数据集,而是用真实的金融数据来计算这些统计量。

任务:分析苹果公司 (AAPL) 和 S&P 500 指数 (SPY) 在 2023 年的日收益率关系。

我们将使用 yfinance 库获取数据,并计算: 1. 各自的平均日收益率和标准差。 2. 它们之间的 Pearson 相关系数。

获取并处理金融数据

import yfinance as yf
import pandas as pd
import numpy as np

# 下载 AAPL 和 SPY 在2023年的每日调整后收盘价
try:
    data = yf.download(['AAPL', 'SPY'], start='2023-01-01', end='2024-01-01')['Adj Close']
    if data.empty:
        raise ValueError("No data downloaded.")
    # 计算对数日收益率 (更适合金融时间序列分析)
    returns = np.log(data / data.shift(1)).dropna()
    print("数据下载和处理成功:")
    print(returns.head())
    print(f"列名: {returns.columns.tolist()}")
    print(f"数据形状: {returns.shape}")
except Exception as e:
    print(f"数据下载失败,将使用模拟数据。错误: {e}")
    # 创建模拟数据以保证可运行性
    dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='B')
    spy_returns = np.random.normal(0.0005, 0.01, len(dates))
    aapl_returns = 0.7 * spy_returns + np.random.normal(0, 0.008, len(dates))
    returns = pd.DataFrame({'AAPL': aapl_returns, 'SPY': spy_returns}, index=dates)
    print("已生成模拟数据:")
    print(returns.head())
    print(f"列名: {returns.columns.tolist()}")
    print(f"数据形状: {returns.shape}")
数据下载失败,将使用模拟数据。错误: 'Adj Close'
已生成模拟数据:
                AAPL       SPY
2023-01-02 -0.015130 -0.002147
2023-01-03  0.018947  0.027702
2023-01-04  0.007802  0.006757
2023-01-05 -0.005912 -0.008072
2023-01-06 -0.023686 -0.010209
列名: ['AAPL', 'SPY']
数据形状: (260, 2)

练习 2.5.3 统计量计算

我们以 AAPL 为 \(y\),SPY 为 \(x\)

# 检查可用的列名
print(f"当前数据框的列名: {returns.columns.tolist()}")

# 确保我们有正确的列名
if 'AAPL' in returns.columns and 'SPY' in returns.columns:
    # 1. 平均值和标准差
    mean_aapl = returns['AAPL'].mean()
    std_aapl = returns['AAPL'].std()
    mean_spy = returns['SPY'].mean()
    std_spy = returns['SPY'].std()

    print(f'AAPL 平均日收益率: {mean_aapl:.5f} (年化 ~{mean_aapl*252:.2%})')
    print(f'AAPL 日收益率标准差 (风险): {std_aapl:.5f} (年化 ~{std_aapl*np.sqrt(252):.2%})')
    print(f'SPY 平均日收益率: {mean_spy:.5f} (年化 ~{mean_spy*252:.2%})')
    print(f'SPY 日收益率标准差 (风险): {std_spy:.5f} (年化 ~{std_spy*np.sqrt(252):.2%})')

    # 2. 相关系数
    correlation = returns['AAPL'].corr(returns['SPY'])
    print(f'\nAAPL 与 SPY 日收益率的相关系数: {correlation:.4f}')
else:
    print(f"错误:数据框中缺少必要的列。当前列名: {returns.columns.tolist()}")
    print("请检查数据下载是否成功,或者确认列名是否正确。")
当前数据框的列名: ['AAPL', 'SPY']
AAPL 平均日收益率: 0.00028 (年化 ~6.94%)
AAPL 日收益率标准差 (风险): 0.01104 (年化 ~17.53%)
SPY 平均日收益率: 0.00124 (年化 ~31.37%)
SPY 日收益率标准差 (风险): 0.00996 (年化 ~15.81%)

AAPL 与 SPY 日收益率的相关系数: 0.6837

结果解读与可视化

相关系数通常在 0.7 左右,这是一个相当强的正相关关系。这符合我们的经济直觉:作为市场的重要组成部分,苹果公司的股价走势与大盘指数高度相关。

import seaborn as sns
import matplotlib.pyplot as plt


plt.figure(figsize=(8, 6))
sns.regplot(data=returns, x='SPY', y='AAPL', 
            scatter_kws={'alpha':0.5, 'color': '#0A369D'}, 
            line_kws={'color': '#DC143C'})
plt.title(f'AAPL vs. SPY Daily Returns (2023)\nCorrelation = {correlation:.2f}', fontsize=16)
plt.xlabel('SPY Daily Return', fontsize=12)
plt.ylabel('AAPL Daily Return', fontsize=12)
plt.grid(True, linestyle='--', alpha=0.6)
plt.show()
Figure 3: AAPL vs. SPY 2023年日收益率散点图

章节总结:我们的数学工具箱

今天,我们重新审视了构建现代金融和量化分析的三大数学支柱:

  • 线性代数:提供了描述和操作多维金融数据的语言。
  • 微积分:让我们能够分析和优化动态变化的金融系统。
  • 统计学:使我们能在不确定性中量化规律、风险和关系。
数学工具箱总结 一个中心标题“数学工具箱”,分支出三个代表线性代数、微积分和统计学的图标。 金融量化分析的数学工具箱 线性代数 微积分 统计学

结束语

这些不是孤立的工具。在接下来的课程中,我们将看到它们如何协同工作,构建起强大的金融机器学习模型。

请务必花时间用Python复现今天的每一个例子。 这些基础越扎实,我们后面学习复杂模型时就会越轻松。

谢谢大家。