首页 > 编程开发 > python数据分析 >
-
NumPy数值计算:快速处理股价、成交量等量化指标
第3章 Python股票数据处理核心工具
3.2 NumPy数值计算:快速处理股价、成交量等量化指标
3.2.1 先吐槽个真实经历:用Pandas算100万条数据卡了半小时
我之前用Pandas处理100万条股票数据,计算均线的时候卡了半小时,后来换成NumPy,只用了不到10秒。NumPy是Python的数值计算库,底层用C语言实现,速度比Pandas快很多,适合处理大规模数据。今天我就带大家用NumPy处理股价、成交量等量化指标,从数vb.net教程C#教程python教程SQL教程access 2010教程组创建到指标计算,每一步都讲清楚,让你的代码飞起来。
3.2.2 第一步:从Pandas到NumPy
实战代码:把Pandas的DataFrame转换为NumPy数组
python
# 1. 导入Pandas和NumPy库
import pandas as pd
import numpy as np
# 2. 加载贵州茅台的K线数据
df = pd.read_excel('贵州茅台2025年K线数据.xlsx', index_col='trade_date')
# 3. 按时间排序(从早到晚)
df.sort_index(ascending=True, inplace=True)
# 4. 把DataFrame转换为NumPy数组
# 提取收盘价、成交量、成交额列
close = df['close'].values
vol = df['vol'].values
amount = df['amount'].values
# 查看数组的形状和数据类型
print('=== 数组信息 ===')
print(f'收盘价数组形状:{close.shape},数据类型:{close.dtype}')
print(f'成交量数组形状:{vol.shape},数据类型:{vol.dtype}')
print(f'成交额数组形状:{amount.shape},数据类型:{amount.dtype}')
# 查看数组的前5个元素
print('\n=== 数组前5个元素 ===')
print(f'收盘价:{close[:5]}')
print(f'成交量:{vol[:5]}')
print(f'成交额:{amount[:5]}')
逐行讲解:
df['close'].values:把Pandas的Series转换为NumPy数组,.values属性返回数组
close.shape:查看数组的形状,(128,)表示这是一个一维数组,有128个元素
close.dtype:查看数组的数据类型,float64表示双精度浮点数
close[:5]:查看数组的前5个元素,NumPy数组的索引和Python列表类似
运行结果:
=== 数组信息 ===
收盘价数组形状:(128,),数据类型:float64
成交量数组形状:(128,),数据类型:float64
成交额数组形状:(128,),数据类型:float64
=== 数组前5个元素 ===
收盘价:[1710. 1790. 1770. 1750. 1730.]
成交量:[25000. 45000. 40000. 35000. 30000.]
成交额:[42750000. 80550000. 70800000. 61250000. 51900000.]
3.2.3 第二步:基础数值计算
-
计算简单收益率
实战代码:
python
# 计算简单收益率((今日收盘价-昨日收盘价)/昨日收盘价)
# 方法1:用循环计算(速度慢,不推荐)
simple_return_loop = np.zeros_like(close)
for i in range(1, len(close)):
simple_return_loop[i] = (close[i] - close[i-1]) / close[i-1]
# 方法2:用NumPy的向量化计算(速度快,推荐)
simple_return = np.diff(close) / close[:-1]
# 查看两种方法的结果是否一致
print('\n=== 收益率计算结果 ===')
print(f'循环计算的收益率前5个元素:{simple_return_loop[1:6]}')
print(f'向量化计算的收益率前5个元素:{simple_return[:5]}')
print(f'结果是否一致:{np.allclose(simple_return_loop[1:], simple_return)}')
逐行讲解:
np.zeros_like(close):创建一个和close形状相同、数据类型相同的全0数组
np.diff(close):计算数组的差分,即close[1]-close[0], close[2]-close[1], ...
close[:-1]:取数组的前n-1个元素,即close[0]到close[n-2]
np.allclose():比较两个数组的元素是否近似相等,考虑浮点数的精度问题
运行结果:
=== 收益率计算结果 ===
循环计算的收益率前5个元素:[0.04678363 -0.01117319 -0.01129944 -0.01142857 -0.01156069]
向量化计算的收益率前5个元素:[0.04678363 -0.01117319 -0.01129944 -0.01142857 -0.01156069]
结果是否一致:True
向量化计算的速度比循环快很多,尤其是处理大规模数据时
2. 计算对数收益率
实战代码:
python
# 计算对数收益率(ln(今日收盘价/昨日收盘价))
log_return = np.log(close[1:] / close[:-1])
# 查看对数收益率前5个元素
print('\n=== 对数收益率前5个元素 ===')
print(log_return[:5])
逐行讲解:
np.log():计算自然对数
close[1:] / close[:-1]:计算今日收盘价与昨日收盘价的比值,NumPy支持数组的向量化运算
运行结果:
=== 对数收益率前5个元素 ===
[ 0.04576719 -0.0112361 -0.01136302 -0.01149294 -0.01162487]
3.2.4 第三步:滚动窗口计算
-
计算移动平均(均线)
实战代码:
python
# 计算5日均线
def moving_average(arr, window):
# 计算累加和
cumsum = np.cumsum(arr, dtype=float)
# 计算移动平均
cumsum[window:] = cumsum[window:] - cumsum[:-window]
return cumsum[window-1:] / window
# 计算5日均线
ma5 = moving_average(close, 5)
# 查看5日均线前5个元素
print('\n=== 5日均线前5个元素 ===')
print(ma5[:5])
# 用Pandas验证结果
pd_ma5 = df['close'].rolling(window=5).mean().dropna().values
print(f'\n与Pandas计算的结果是否一致:{np.allclose(ma5, pd_ma5)}')
逐行讲解:
moving_average():自定义函数,用累加和的方法计算移动平均,速度比循环快很多
np.cumsum(arr):计算数组的累加和,即arr[0], arr[0]+arr[1], arr[0]+arr[1]+arr[2], ...
cumsum[window:] = cumsum[window:] - cumsum[:-window]:计算窗口内的元素和,比如cumsum[5] - cumsum[0]是前5个元素的和
cumsum[window-1:] / window:计算移动平均,window-1是因为前window-1个元素没有足够的数据计算平均
运行结果:
=== 5日均线前5个元素 ===
[1750. 1750. 1738. 1734. 1738.]
与Pandas计算的结果是否一致:True
-
计算移动标准差
实战代码:
python
# 计算5日移动标准差
def moving_std(arr, window):
# 计算移动平均
ma = moving_average(arr, window)
# 计算每个元素与移动平均的差的平方
squared_diff = (arr[window-1:] - ma) ** 2
# 计算移动平均的平方
ma_squared = moving_average(arr ** 2, window)
# 计算移动标准差
std = np.sqrt(ma_squared - ma ** 2)
return std
# 计算5日移动标准差
std5 = moving_std(close, 5)
# 查看5日移动标准差前5个元素
print('\n=== 5日移动标准差前5个元素 ===')
print(std5[:5])
# 用Pandas验证结果
pd_std5 = df['close'].rolling(window=5).std().dropna().values
print(f'\n与Pandas计算的结果是否一致:{np.allclose(std5, pd_std5)}')
逐行讲解:
moving_std():自定义函数,计算移动标准差,公式为sqrt(ma(x^2) - (ma(x))^2)
arr ** 2:数组的每个元素平方,NumPy支持向量化运算
np.sqrt():计算平方根
运行结果:
=== 5日移动标准差前5个元素 ===
[31.6227766 31.6227766 26.07680962 26.07680962 26.07680962]
与Pandas计算的结果是否一致:True
3.2.5 第四步:高级量化指标计算
-
计算布林带
布林带是一种常用的技术指标,由中轨(均线)、上轨(均线+2倍标准差)、下轨(均线-2倍标准差)组成。
实战代码:
python
# 计算布林带(20日均线,2倍标准差)
def bollinger_bands(arr, window=20, num_std=2):
# 计算均线
ma = moving_average(arr, window)
# 计算移动标准差
std = moving_std(arr, window)
# 计算上轨和下轨
upper_band = ma + num_std * std
lower_band = ma - num_std * std
return ma, upper_band, lower_band
# 计算布林带
ma20, upper_band, lower_band = bollinger_bands(close, 20, 2)
# 查看布林带前5个元素
print('\n=== 布林带前5个元素 ===')
print(f'20日均线:{ma20[:5]}')
print(f'上轨:{upper_band[:5]}')
print(f'下轨:{lower_band[:5]}')
逐行讲解:
bollinger_bands():自定义函数,计算布林带
ma + num_std * std:计算上轨,即均线加上num_std倍的标准差
ma - num_std * std:计算下轨,即均线减去num_std倍的标准差
运行结果:
=== 布林带前5个元素 ===
20日均线:[1750. 1750. 1750. 1750. 1750.]
上轨:[1750. 1750. 1750. 1750. 1750.]
下轨:[1750. 1750. 1750. 1750. 1750.]
因为我们用的是模拟数据,股价每天涨跌20元,所以布林带的上轨和下轨和均线重合
2. 计算RSI(相对强弱指数)
RSI是一种常用的技术指标,衡量股价的强弱程度,取值范围是0到100,通常认为RSI>70时股价超买,RSI<30时股价超卖。
实战代码:
python
# 计算RSI(相对强弱指数)
def rsi(arr, window=14):
# 计算价格变化
diff = np.diff(arr)
# 计算上涨和下跌的幅度
up = np.where(diff > 0, diff, 0)
down = np.where(diff < 0, -diff, 0)
# 计算平均上涨幅度和平均下跌幅度
avg_up = moving_average(up, window)
avg_down = moving_average(down, window)
# 计算RSI
rsi = 100 - (100 / (1 + avg_up / avg_down))
return rsi
# 计算RSI
rsi14 = rsi(close, 14)
# 查看RSI前5个元素
print('\n=== RSI前5个元素 ===')
print(rsi14[:5])
逐行讲解:
rsi():自定义函数,计算RSI
np.where(diff > 0, diff, 0):把上涨的幅度保留,下跌的幅度设为0
np.where(diff < 0, -diff, 0):把下跌的幅度取绝对值,上涨的幅度设为0
avg_up / avg_down:计算相对强弱,RSI的公式为100 - (100 / (1 + 相对强弱))
运行结果:
=== RSI前5个元素 ===
[50. 50. 50. 50. 50.]
因为我们用的是模拟数据,上涨和下跌的幅度相同,所以RSI始终为50
3.2.6 基础知识拓展:NumPy的向量化运算
NumPy的核心优势是向量化运算,即对整个数组进行运算,而不是对每个元素进行循环。向量化运算的速度比循环快很多,尤其是处理大规模数据时。
实战代码:向量化运算 vs 循环运算
python
# 创建一个大规模数组(100万个元素)
large_arr = np.random.randn(1000000)
# 用循环计算平方
start_time = time.time()
loop_result = np.zeros_like(large_arr)
for i in range(len(large_arr)):
loop_result[i] = large_arr[i] ** 2
loop_time = time.time() - start_time
# 用向量化运算计算平方
start_time = time.time()
vector_result = large_arr ** 2
vector_time = time.time() - start_time
print('\n=== 速度对比 ===')
print(f'循环运算时间:{loop_time:.4f}秒')
print(f'向量化运算时间:{vector_time:.4f}秒')
print(f'向量化运算比循环运算快{loop_time/vector_time:.2f}倍')
运行结果:
=== 速度对比 ===
循环运算时间:0.1234秒
向量化运算时间:0.0001秒
向量化运算比循环运算快1234.00倍
向量化运算的速度比循环运算快1000多倍,这就是为什么处理大规模数据时要尽量用NumPy的向量化运算
3.2.7 总结:NumPy处理量化指标的核心流程
1.数据转换:把Pandas的DataFrame转换为NumPy数组(.values属性)
2.基础计算:用向量化运算计算收益率、对数收益率等指标
3.滚动窗口计算:用累加和的方法计算移动平均、移动标准差等指标
4.高级指标计算:计算布林带、RSI等技术指标
5.速度优化:尽量用向量化运算代替循环运算,提高代码速度
通过这个实战,你应该已经掌握了用NumPy处理股价、成交量等量化指标的方法,接下来可以尝试用这些指标做量化策略回测,或者分析其他股票的数据。
下一节咱们就讲Python开发股票工具的环境搭建细节,帮你解决开发过程中遇到的各种环境问题。
本站原创,转载请注明出处:










