问题描述
mkdictw = C.get_market_data_ex(['low', 'high','close'], A.stock, period='1mon', count=17, dividend_type='front', end_time=today,fill_data=True,subscribe = False)
hightw=np.array(mkdictw[gupiao]['high'])
lowsw = np.array(mkdictw[gupiao]['low'])
closesw = np.array(mkdictw[gupiao]['close'])
cci_listm = talib.CCI(hightw,lowsw,closesw,timeperiod=14)
出错运行不了提示 talib.cci nan
解决方案
在 QMT 中使用 talib 计算技术指标时遇到 nan,通常是由以下几个原因导致的。针对您的代码,主要有以下几个优化点:
1. 数据量 (count) 太少
talib.CCI 的 timeperiod=14 意味着计算第一个有效的 CCI 值需要前 14 个周期的数据。在 talib 的计算结果中,前 13 个值必然是 nan。您设置的 count=17,这意味着计算结果中只有最后 3 个值是有数据的,前面 14 个全是 nan。如果这 17 个数据中再有缺失值,可能导致所有结果都是 nan。
解决方法:将 count 适当调大,例如设置为 50 或 100。
2. 原始数据中包含 nan(缺失值)
get_market_data_ex 获取的数据中,如果股票在某个月份停牌,或者上市时间不足,对应的数据可能会是 nan。talib 在计算时,只要输入数组中包含 nan,后续的计算结果也会变成 nan。
解决方法:在传入 talib 之前,使用 pandas 的 fillna 方法对缺失值进行前向填充(ffill),或者剔除缺失值。
3. 数据类型问题
talib 要求输入的 numpy 数组数据类型必须是 float64。虽然通常默认是 float,但显式转换可以避免底层 C 语言库报错。
修改后的代码示例
建议您按照以下方式修改代码,增加数据获取量,并进行数据清洗和类型转换:
import numpy as np
import pandas as pd
import talib
# 1. 增加 count 数量,确保有足够的数据计算指标(例如改为 50)
mkdictw = C.get_market_data_ex(['low', 'high', 'close'], A.stock, period='1mon', count=50, dividend_type='front', end_time=today, fill_data=True, subscribe=False)
# 获取该股票的数据 DataFrame
df = mkdictw[gupiao]
# 2. 处理缺失值:使用前向填充(ffill)填补停牌导致的 nan,如果最前面还有 nan 则用后向填充(bfill)
df = df.fillna(method='ffill').fillna(method='bfill')
# 3. 转换为 numpy 数组,并确保数据类型为 float64
hightw = np.array(df['high'], dtype=np.float64)
lowsw = np.array(df['low'], dtype=np.float64)
closesw = np.array(df['close'], dtype=np.float64)
# 4. 计算 CCI
cci_listm = talib.CCI(hightw, lowsw, closesw, timeperiod=14)
# 打印最后一个值查看结果(注意:cci_listm 的前 13 个值仍然会是 nan,这是正常的)
print("最新 CCI 值:", cci_listm[-1])
总结排查步骤:
- 打印
hightw、lowsw、closesw,看看里面是不是已经有nan了。 - 记住
talib返回的数组长度和输入一样,但前timeperiod - 1个元素必定是nan,取值时请取最后一个元素cci_listm[-1]。