3、Python基础速通(二):列表、字典、元组、集合——量化数据处理的基石
上一章我们聊了变量和基础运算,算是把地基打好了。但做量化交易,你面对的不是一个数字,而是一堆数字——股票池、历史K线、持仓列表、订单簿……这些数据怎么装、怎么查、怎么改?
这就得靠Python的四大容器:列表、字典、元组、集合。说白了,它们就是用来装数据的「箱子」,但每个箱子的用法和脾气都不一样。
我个人习惯,写策略之前,先把这四种结构在脑子里过一遍。选错了容器,后面改代码能改到怀疑人生。
3.1 列表:你的数据流水线
列表是Python里最常用的容器。它就像一条传送带,数据按顺序排好,你可以随时往里面加东西、取东西、改东西。
创建与基础操作
# 一个简单的股票代码列表
stock_list = ['000001', '600519', '300750', '002415']
# 获取第2个元素(索引从0开始)
print(stock_list[1]) # 输出: 600519
# 切片:取前3个
print(stock_list[:3]) # 输出: ['000001', '600519', '300750']
# 追加新股票
stock_list.append('000002')
print(stock_list) # 输出: ['000001', '600519', '300750', '002415', '000002']
我在项目中遇到过一个问题:用列表存了1000只股票的日收益率,然后想批量计算移动平均。如果直接用for循环一个个算,速度慢得让人抓狂。后来我改用列表推导式,一行代码搞定。
# 列表推导式:快速生成数据
prices = [100, 102, 101, 105, 108]
# 计算每日收益率(百分比)
returns = [(prices[i] - prices[i-1]) / prices[i-1] * 100 for i in range(1, len(prices))]
print(returns) # 输出: [2.0, -0.98, 3.96, 2.86]
列表的常用方法
| 方法 | 作用 | 量化场景举例 |
|---|---|---|
| append() | 末尾添加元素 | 实时行情来了,追加到价格列表 |
| extend() | 合并另一个列表 | 把两个时间段的K线数据拼接 |
| sort() | 原地排序 | 按收益率排序,找出最强/最弱股票 |
| index() | 查找元素位置 | 找到某只股票在池子里的索引 |
3.2 字典:股票代码与数据的「通讯录」
字典存的是键值对。你可以把它想象成一本通讯录:你查「600519」,它告诉你「贵州茅台」和它的当前股价。在量化里,字典最适合做映射关系。
为什么字典在量化中这么重要?
你想想看,如果你有3000只股票,每只股票都有开盘价、收盘价、最高价、最低价、成交量……如果用列表存,你得记住每个字段在第几个位置。用字典就简单了:
# 用字典存储一只股票的关键数据
stock_info = {
'code': '600519',
'name': '贵州茅台',
'close': 1850.00,
'volume': 3200000,
'ma5': 1835.50,
'ma20': 1800.20
}
# 获取收盘价
print(stock_info['close']) # 输出: 1850.0
# 更新数据
stock_info['close'] = 1860.50
print(stock_info['close']) # 输出: 1860.5
我曾经犯过一个低级错误:用字典存了全市场股票的实时行情,每次更新时直接赋值。结果跑了一段时间,发现内存暴涨。后来才意识到,字典的键是字符串,每个键都会占用内存。3000只股票,每只股票存10个字段,就是3万个键值对。嗯,这里要注意:字典虽好,但别滥用。
字典的常用操作
# 批量更新多个字段
stock_info.update({'close': 1870.00, 'volume': 3500000})
# 安全取值(不存在时返回默认值)
pe = stock_info.get('pe_ratio', 0)
print(pe) # 输出: 0(因为字典里没有这个键)
# 遍历字典
for key, value in stock_info.items():
print(f"{key}: {value}")
3.3 元组:不可变的「安全箱」
元组和列表很像,但有一个关键区别:元组一旦创建,就不能修改。你想想看,在量化交易中,有些数据是绝对不能改的——比如交易信号的参数、策略的固定配置、或者某只股票的历史最高价。
# 定义一个交易信号参数
trade_params = (5, 20, 0.02) # 短周期、长周期、止损比例
# 尝试修改会报错
# trade_params[0] = 10 # TypeError: 'tuple' object does not support item assignment
# 但可以整体替换
trade_params = (10, 30, 0.03) # 这是合法的
我个人习惯,把策略里那些「写死了」的参数都用元组存。比如均线周期、仓位比例、滑点设置。这样别人改代码时,一眼就能看出哪些是「不能动的」。
元组的解包
# 从数据库查出来的一条记录
record = ('000001', '平安银行', 12.35, 5000000)
code, name, price, volume = record
print(f"{name} 当前价格: {price}") # 输出: 平安银行 当前价格: 12.35
3.4 集合:去重与交集运算的利器
集合,说白了就是一个「不重复的元素集」。在量化里,最常见的场景就是去重和求交集。
场景一:去重
假设你从多个数据源拉取了股票列表,里面可能有重复的代码。用集合去重,一行搞定:
# 多个数据源合并的股票列表(有重复)
raw_list = ['000001', '600519', '000001', '300750', '600519', '002415']
unique_stocks = set(raw_list)
print(unique_stocks) # 输出: {'000001', '002415', '300750', '600519'}
场景二:求交集
做量化选股时,经常需要找「同时满足多个条件」的股票。比如:既在沪深300成分股里,又满足技术面买入信号。
# 沪深300成分股
hs300 = {'000001', '000002', '600519', '300750', '002415'}
# 技术面选股结果
tech_signals = {'600519', '300750', '000858', '002304'}
# 求交集:同时满足两个条件的股票
final_pool = hs300 & tech_signals
print(final_pool) # 输出: {'600519', '300750'}
3.5 四种容器的选择指南
说了这么多,到底什么时候用哪个?我总结了一张表,你直接照着用就行:
| 容器类型 | 适用场景 | 量化案例 |
|---|---|---|
| 列表 | 有序、可变的序列数据 | 历史K线、收益率序列、订单队列 |
| 字典 | 键值映射、快速查找 | 股票代码→行情数据、策略参数配置 |
| 元组 | 不可变的固定数据 | 策略参数、数据库记录、函数多返回值 |
| 集合 | 去重、集合运算 | 股票池去重、多条件选股交集 |