Python原生列表的局限性:
NumPy数组的设计哲学:
金融应用场景:
| 策略 | 方法 | 适用场景 |
|---|---|---|
| 从序列转换 | np.array([1,2,3]) |
小规模数据 |
| 生成函数 | np.zeros(), np.ones() |
初始化、模拟 |
| 从文件读取 | np.loadtxt() |
导入外部数据 |
常用生成函数:
np.arange(10):类似range()的数组版本np.random.*:随机数生成系列函数(2000, 500)
[[ 0.21286835 0.71661866 -0.32039462 0.08239331 0.37557726]
[ 1.99367332 -0.79226854 0.81194438 -0.09726054 -0.68500609]
[-1.36229143 -0.93272179 -0.16735951 0.90490057 0.71315935]
[ 1.27674206 1.76844381 1.03884891 -0.70976226 -0.04694749]
[ 0.99955956 0.12310658 -1.03571279 0.48472374 -1.97164068]]
| 属性 | 说明 | 示例 |
|---|---|---|
shape |
数组维度(行×列) | (2000, 500) |
ndim |
维度数量 | 2 |
size |
元素总数 | 1000000 |
dtype |
数据类型 | float64 |
shape返回元组,表示各维度大小size等于shape各维度的乘积import numpy as np
arr_1d = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
print('基本索引:')
print(f' arr_1d[0] = {arr_1d[0]}') # 正索引:第一个元素
print(f' arr_1d[-1] = {arr_1d[-1]}') # 负索引:最后一个元素
print('\n切片操作:')
print(f' arr_1d[2:7] = {arr_1d[2:7]}') # 索引2到6
print(f' arr_1d[::2] = {arr_1d[::2]}') # 步长为2基本索引:
arr_1d[0] = 10
arr_1d[-1] = 100
切片操作:
arr_1d[2:7] = [30 40 50 60 70]
arr_1d[::2] = [10 30 50 70 90]
[start:stop:step]start:起始索引(包含),省略则从头开始stop:结束索引(不包含),省略则到末尾step:步长,省略默认为1金融应用:
arr[2:7]:提取第3天到第7天的数据arr[::2]:从日频数据中提取隔日数据二维数组索引:
arr_2d[0, 0] = 1
arr_2d[1, :] = [5 6 7 8]
arr_2d[:, 2] = [ 3 7 11]
arr_2d[0:2, 1:3] =
[[2 3]
[6 7]]
花式索引 arr_1d[[0, 2, 4]]: [10 30 50]
布尔索引 arr_1d[>50]: [ 60 70 80 90 100]
金融应用:
关键区别:切片是视图(共享内存),.copy()是独立副本。
向量化(Vectorization):用数组表达式代替显式循环
import numpy as np
import time
n = 10_000_000
arr1 = np.random.randn(n)
arr2 = np.random.randn(n)
# Python循环
start = time.time()
result_loop = [arr1[i] + arr2[i] for i in range(n)]
time_loop = time.time() - start
# NumPy向量化
start = time.time()
result_vec = arr1 + arr2
time_vec = time.time() - start
print(f'数组大小: {n:,} 元素')
print(f'Python循环: {time_loop:.4f}秒')
print(f'向量化运算: {time_vec:.4f}秒')
print(f'性能提升: {time_loop / time_vec:.1f}倍')
print(f'结果一致: {np.allclose(result_loop, result_vec)}')数组大小: 10,000,000 元素
Python循环: 1.7238秒
向量化运算: 0.0077秒
性能提升: 223.7倍
结果一致: True
import numpy as np
n_stocks = 100 # 100只股票
n_days = 252 # 1年交易日
# 随机权重归一化
weights = np.random.random(n_stocks)
weights = weights / weights.sum()
# 模拟日收益率矩阵
np.random.seed(42)
returns = np.random.randn(n_stocks, n_days) * 0.02
# 矩阵乘法计算组合收益率
portfolio_returns = weights @ returns # (100,) @ (100,252) = (252,)print('投资组合统计:')
print(f' 年化收益率: {portfolio_returns.mean() * 252:.4f}')
print(f' 年化波动率: {portfolio_returns.std() * np.sqrt(252):.4f}')
# 夏普比率 = 年化收益率 / 年化波动率(假设无风险利率为0)
sharpe = (portfolio_returns.mean() * 252) / (portfolio_returns.std() * np.sqrt(252))
print(f' 夏普比率: {sharpe:.4f}')
# 累计收益率
cum_returns = np.cumprod(1 + portfolio_returns) - 1
print(f' 年累计收益: {cum_returns[-1]:.4f}')投资组合统计:
年化收益率: -0.0041
年化波动率: 0.0360
夏普比率: -0.1151
年累计收益: -0.0048
@ 运算符与广播机制@ 运算符:矩阵乘法
np.matmul()weights @ returns:权重向量 × 收益率矩阵广播机制:不同形状数组的自动对齐
(100,) @ (100, 252) → (252,)| 特性 | NumPy数组 | Pandas Series |
|---|---|---|
| 索引 | 整数位置 | 自定义标签 |
| 缺失值 | 需用NaN手动表示 | 原生支持 |
| 数据对齐 | 手动对齐 | 自动对齐 |
| 功能 | 纯数值计算 | 统计、可视化 |
Series:
0 1
1 3
2 5
3 6
4 10
5 23
dtype: int64
索引: RangeIndex(start=0, stop=6, step=1)
值: [ 1 3 5 6 10 23]
类型: int64
带日期索引的Series:
2023-01-01 100.5
2023-01-02 102.3
2023-01-03 101.8
2023-01-04 103.2
2023-01-05 104.5
2023-01-06 103.9
Freq: D, dtype: float64
按日期切片(1月2日到4日):
2023-01-02 102.3
2023-01-03 101.8
2023-01-04 103.2
Freq: D, dtype: float64
索引选择方式:
.iloc[].loc[]series[条件]现代投资组合理论假设收益率服从正态分布,但实证发现:
关键统计量:
import numpy as np
from scipy.stats import skew, kurtosis
np.random.seed(42)
returns = np.random.randn(252) * 0.02 # 模拟一年日收益率
print('收益率描述统计:')
print(f' 均值: {returns.mean():.6f}')
print(f' 标准差: {returns.std():.6f}')
print(f' 最小值: {returns.min():.6f}')
print(f' 最大值: {returns.max():.6f}')
print(f' 中位数: {np.median(returns):.6f}')收益率描述统计:
均值: -0.000075
标准差: 0.019306
最小值: -0.052395
最大值: 0.077055
中位数: 0.001184
分位数:
Q1(25%): -0.013711
Q2(50%): 0.001184
Q3(75%): 0.011861
分布形状:
偏度: 0.3002
峰度: 0.5796
annual_return = returns.mean() * 252 # 年化收益率
annual_vol = returns.std() * np.sqrt(252) # 年化波动率
sharpe_ratio = annual_return / annual_vol # 夏普比率
print('年化指标:')
print(f' 年化收益率: {annual_return:.4f} ({annual_return:.2%})')
print(f' 年化波动率: {annual_vol:.4f} ({annual_vol:.2%})')
print(f' 夏普比率: {sharpe_ratio:.4f}')年化指标:
年化收益率: -0.0190 (-1.90%)
年化波动率: 0.3065 (30.65%)
夏普比率: -0.0619
年化公式:
import numpy as np
np.random.seed(42)
# 模拟100只基金的年化收益率(均值8%,标准差15%)
fund_returns = np.random.randn(100) * 0.15 + 0.08
print('基金业绩分位数:')
print(f' 中位数(50%): {np.percentile(fund_returns, 50):.4f}')
print(f' 前25%(75%): {np.percentile(fund_returns, 75):.4f}')
print(f' 前10%(90%): {np.percentile(fund_returns, 90):.4f}')
print(f' 前1%(99%): {np.percentile(fund_returns, 99):.4f}')基金业绩分位数:
中位数(50%): 0.0610
前25%(75%): 0.1409
前10%(90%): 0.2309
前1%(99%): 0.3173
业绩分档阈值:
0%分位: -0.3130
25%分位: -0.0101
50%分位: 0.0610
75%分位: 0.1409
100%分位: 0.3578
各档基金数量:
第1档: 0只基金
第2档: 25只基金
第3档: 25只基金
第4档: 25只基金
第5档: 24只基金
原始数组(1维): [ 1 2 3 4 5 6 7 8 9 10 11 12]
重塑为3×4矩阵:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
重塑为4×3矩阵:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
重塑为2×6矩阵:
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
注意:元素总数必须匹配(12 = 3×4 = 4×3 = 2×6)
4×3矩阵:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
转置(.T) → 3×4:
[[ 1 4 7 10]
[ 2 5 8 11]
[ 3 6 9 12]]
ravel()展平(视图): [ 1 2 3 4 5 6 7 8 9 10 11 12]
flatten()展平(副本): [ 1 2 3 4 5 6 7 8 9 10 11 12]
ravel vs flatten:
ravel():返回视图,修改会影响原数组flatten():返回副本,修改不影响原数组import pandas as pd
import numpy as np
np.random.seed(42)
dates = pd.date_range('2023-01-01', periods=5)
stocks = ['贵州茅台', '五粮液', '招商银行']
df_wide = pd.DataFrame(
np.random.randn(5, 3).round(4),
index=dates, columns=stocks
)
print('宽格式(日期×股票):')
print(df_wide)
print('\n长格式(股票×日期) — 通过转置:')
print(df_wide.T)宽格式(日期×股票):
贵州茅台 五粮液 招商银行
2023-01-01 0.4967 -0.1383 0.6477
2023-01-02 1.5230 -0.2342 -0.2341
2023-01-03 1.5792 0.7674 -0.4695
2023-01-04 0.5426 -0.4634 -0.4657
2023-01-05 0.2420 -1.9133 -1.7249
长格式(股票×日期) — 通过转置:
2023-01-01 2023-01-02 2023-01-03 2023-01-04 2023-01-05
贵州茅台 0.4967 1.5230 1.5792 0.5426 0.2420
五粮液 -0.1383 -0.2342 0.7674 -0.4634 -1.9133
招商银行 0.6477 -0.2341 -0.4695 -0.4657 -1.7249
| 主题 | 核心要点 |
|---|---|
| 数组创建 | np.array(), np.random, np.arange() |
| 索引切片 | [start:stop:step], 花式索引, 布尔索引 |
| 向量化运算 | 避免循环,性能提升数十倍 |
| Series | 带标签的一维数组,自动对齐 |
| 统计分析 | 均值、标准差、偏度、峰度 |
| 重塑转置 | reshape(), .T, ravel() |
[商业大数据分析与应用]