使用Python实现海龟交易策略时遭遇KeyError错误求助
问题分析与解决方案
核心错误原因
你遇到的KeyError是因为DataFrame的行索引是日期类型(通过index_col='Date'设置),但你在遍历的时候用了整数i去调用data.loc[i, ...]——loc是基于标签的索引,找不到对应的整数标签就会抛出KeyError。
关键修复点
1. 正确遍历DataFrame行
改用iloc(基于整数位置的索引)来访问行,或者用enumerate(data.iterrows())同时获取位置和行数据。推荐用iloc更高效。
2. 修正ATR计算逻辑
海龟策略的真实波幅(TR)需要取三个值的最大值:
- 当日最高价 - 当日最低价
- 当日最高价 - 前一日收盘价
- 前一日收盘价 - 当日最低价
再对TR做10日移动平均得到ATR,你之前的计算方式不符合标准定义。
3. 移除多余的dropna()
计算均线时,rolling().mean()会自动在窗口不足时返回NaN,手动调用dropna()会删除这些行的对应列值,导致后续数据不完整。
修正后的完整代码
import yfinance as yf import pandas as pd # 下载并保存数据(可选,若已保存可注释) start_date = '2022-01-01' end_date = '2022-12-31' data = yf.Ticker("ETH-USD").history(start=start_date, end=end_date, interval="1d") data.to_csv('eth-usd.csv') # 加载数据 pd.options.display.max_rows = 1000 data = pd.read_csv('eth-usd.csv', index_col='Date', parse_dates=True) # 计算20日和10日移动平均线(移除多余dropna) data['20d'] = data['Close'].rolling(20).mean() data['10d'] = data['Close'].rolling(10).mean() # 计算标准ATR data['TR'] = pd.concat([ data['High'] - data['Low'], abs(data['High'] - data['Close'].shift(1)), abs(data['Close'].shift(1) - data['Low']) ], axis=1).max(axis=1) data['ATR'] = data['TR'].rolling(10).mean() # 初始化参数 initial_capital = 10000 shares_to_trade = 100 # 创建仓位、盈亏、收益列 data['Position'] = None data['P/L'] = 0.0 data['Returns'] = 0.0 # 遍历行(用iloc按位置访问) for i in range(1, len(data)): # 跳过均线或ATR为NaN的行(窗口未形成) if pd.isna(data.iloc[i]['20d']) or pd.isna(data.iloc[i]['10d']): continue if data.iloc[i]['20d'] > data.iloc[i]['10d']: data.iloc[i, data.columns.get_loc('Position')] = 'Long' # 多仓的盈亏计算:当日收盘价与前日收盘价的差 × 持仓量 data.iloc[i, data.columns.get_loc('P/L')] = shares_to_trade * (data.iloc[i]['Close'] - data.iloc[i-1]['Close']) elif data.iloc[i]['10d'] > data.iloc[i]['20d']: data.iloc[i, data.columns.get_loc('Position')] = 'Short' # 空仓的盈亏计算:(前日收盘价 - 当日收盘价) × 持仓量 data.iloc[i, data.columns.get_loc('P/L')] = shares_to_trade * (data.iloc[i-1]['Close'] - data.iloc[i]['Close']) # 计算累计收益 data['Returns'] = data['P/L'].cumsum() / initial_capital # 绘制收益曲线 data['Returns'].plot(title='ETH-USD Turtle Strategy Returns')
额外说明
- 修正了盈亏计算逻辑:原代码的P/L计算不符合实际交易逻辑,改成了基于当日和前日收盘价的差值来计算每日盈亏。
- 添加了对NaN值的判断,避免在均线窗口未形成时进行仓位判断。
内容的提问来源于stack exchange,提问作者Mikheil Siradze
相关产品推荐
相关产品推荐

