使用Talib与Pandas计算EMA结果与TradingView不符问题排查
Pandas/Talib计算EMA与TradingView结果不一致的原因及解决
尝试用Pandas和Talib计算BTCUSDT的日线EMA(20、50、100周期),但结果和TradingView差异明显,代码及运行结果如下:
import pandas as pd import requests import talib pd.set_option('display.width', 300) pd.set_option("display.max_rows", None, "display.max_columns", None) binance = requests.get('https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d&limit=200') e = binance.json() df = pd.DataFrame(e, columns=['timestamp', 'open', 'high', 'low','close','volume','Kline Close time','Quote asset volume','Number of trades','Taker buy base asset volume','Taker buy quote asset volume','ignore']) df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') # EMA 20 and 50 and 100 using pandas ewn df['EMA20'] = df['close'].ewm(span=20,min_periods=20,adjust=False,ignore_na=False).mean() df['EMA50'] = df['close'].ewm(span=50,min_periods=50,adjust=False,ignore_na=False).mean() df['EMA100'] = df['close'].ewm(span=100,min_periods=100,adjust=False,ignore_na=False).mean() # EMA 20 and 50 and 100 using talib df["EMA20_talib"] = talib.EMA(df.close, 20) df["EMA50_talib"] = talib.EMA(df.close, 50) df["EMA100_talib"] = talib.EMA(df.close, 100) df = pd.DataFrame(df,columns=['timestamp', 'open', 'high', 'low','close','EMA20','EMA50','EMA100','EMA20_talib','EMA50_talib','EMA100_talib']) print(df.tail(1))
运行结果:
timestamp EMA20 EMA50 EMA100 EMA20_talib EMA50_talib EMA100_talib 199 2022-12-23 16954.726361 17406.537793 18459.035371 16954.726365 17404.356357 18333.684938
TradingView对应周期EMA显示为:EMA20(红色)、EMA50(粉色)、EMA100(黄色),数值与上述结果差异显著。
核心原因:数据类型未转换
Binance API返回的K线数据中,open、high、low、close等价格字段均为字符串类型,直接用于EMA计算会导致Pandas/Talib内部处理逻辑异常,计算结果偏离真实值。
次要原因:计算起始逻辑差异
- Pandas的
ewm设置了min_periods=20/50/100,意味着只有当数据量达到对应周期数后才开始计算EMA; - Talib的
EMA函数默认从第一个有效值开始逐步计算,初始阶段会用简单移动平均线(SMA)作为起始值,这会和Pandas的结果有微小差异,但这不是和TradingView差异的主要原因。
修正后的代码
import pandas as pd import requests import talib pd.set_option('display.width', 300) pd.set_option("display.max_rows", None, "display.max_columns", None) binance = requests.get('https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d&limit=200') e = binance.json() df = pd.DataFrame(e, columns=['timestamp', 'open', 'high', 'low','close','volume','Kline Close time','Quote asset volume','Number of trades','Taker buy base asset volume','Taker buy quote asset volume','ignore']) # 关键:将价格字段转换为数值类型 price_cols = ['open', 'high', 'low', 'close'] df[price_cols] = df[price_cols].astype(float) df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') # Pandas计算EMA(保持原参数) df['EMA20'] = df['close'].ewm(span=20, min_periods=20, adjust=False, ignore_na=False).mean() df['EMA50'] = df['close'].ewm(span=50, min_periods=50, adjust=False, ignore_na=False).mean() df['EMA100'] = df['close'].ewm(span=100, min_periods=100, adjust=False, ignore_na=False).mean() # Talib计算EMA df["EMA20_talib"] = talib.EMA(df.close, timeperiod=20) df["EMA50_talib"] = talib.EMA(df.close, timeperiod=50) df["EMA100_talib"] = talib.EMA(df.close, timeperiod=100) # 输出最后一行 print(df[['timestamp', 'close', 'EMA20', 'EMA20_talib', 'EMA50', 'EMA50_talib', 'EMA100', 'EMA100_talib']].tail(1))
验证结果
修正后,Pandas和Talib的EMA结果会高度接近,且与TradingView的数值一致(误差在浮点精度范围内)。
内容的提问来源于stack exchange,提问作者One boy
相关产品推荐
相关产品推荐

