如何在 pandas/每列自定义填充方法中正确重新采样 ohlc 数据
How to resample ohlc data properly in pandas / custom fill method per column
我有缺少时间范围的 OHLC 数据。假设我有以下 pandas 数据帧,由变量 df:
表示
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
现在,我对 pandas 数据帧重新采样以填补缺失的空白,我得到以下结果:
df = df.resample('T').ffill()
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
从上面我们可以看出,缺失的空隙(00:01:00)是借助ffill()填充的。但是,该行(以 00:01:00 开头的行)中的数据未正确显示,因为开盘价应与前一行(以 00:00:00 开头的行)的收盘价相同。同样,该行(以 00:01:00 开头的行)的收盘价应与下一行(以 00:02:00 开头的行)的开盘价相同。所需的输出应如下所示:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67123 0.67123 0.67064 0.67062
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
如何解决 pandas 中的这个问题?
遗憾的是,您不能直接指定每列的填充方法。
解决方法是不在重采样期间填充值,而是在之后填充:
df = df.resample('T').fillna(None)
df['Open'], df['Close'] = (df['Open'].fillna(df['Close'].ffill()),
df['Close'].fillna(df['Open'].bfill()))
df = df.ffill()
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67123 0.67123 0.67064 0.67062
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
上一个答案(对 OHLC 不正确,但概括起来很有趣)
(df.resample('T')
.fillna(None)
.assign(Close=lambda d: d['Close'].bfill()) # bfill for Close
.ffill() # ffill for others
)
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67068 0.67123 0.67064 0.67223
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
交叉填充值:
(df.resample('T')
.fillna(None)
.assign(Open=lambda d: d['Open'].fillna(d['Close'].ffill())) # Open = last Close
.ffill() # ffill the others
)
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67123 0.67123 0.67064 0.67123
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
更多选项
这是另一个示例,我们将对 High 进行插值并将 Low 保留为 NaN:
(df.resample('T')
.fillna(None)
.assign(Open=lambda d: d['Open'].ffill(),
Close=lambda d: d['Close'].bfill(),
High=lambda d: d['High'].interpolate()
)
)
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67068 0.67274 NaN 0.67223
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
是正确的方向,但是有两个问题:
- 如果连续多行缺失值将不起作用,
- “高”和“低”的填充在 OHLC 上下文中不合逻辑。
下面是我会做的(重采样后):
Cross-fill 第一个缺失行
result = df.copy()
result['open'] = df['open'].fillna(df['close'].ffill(),limit=1)
result['close'] = df['close'].fillna(df['open'].bfill(),limit=1)
现在,在其余行中传播相等的开盘价和闭盘价:
result['open'] = result['open'].fillna(result['close'].ffill())
result['close'] = result['close'].fillna(result['close'].ffill())
最后,逻辑上将高低设置为开盘价和收盘价的最小值和最大值:
result['high'] = result['high'].fillna(result[['open','close']].max(axis=1))
result['low'] = result['low'].fillna((result[['open','close']].min(axis=1)))
此方法适用于多个连续缺失行的情况,并且还会逻辑处理 'high' 和 'low' 的缺失值。
我有缺少时间范围的 OHLC 数据。假设我有以下 pandas 数据帧,由变量 df:
表示 Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
现在,我对 pandas 数据帧重新采样以填补缺失的空白,我得到以下结果:
df = df.resample('T').ffill()
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
从上面我们可以看出,缺失的空隙(00:01:00)是借助ffill()填充的。但是,该行(以 00:01:00 开头的行)中的数据未正确显示,因为开盘价应与前一行(以 00:00:00 开头的行)的收盘价相同。同样,该行(以 00:01:00 开头的行)的收盘价应与下一行(以 00:02:00 开头的行)的开盘价相同。所需的输出应如下所示:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67123 0.67123 0.67064 0.67062
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
如何解决 pandas 中的这个问题?
遗憾的是,您不能直接指定每列的填充方法。
解决方法是不在重采样期间填充值,而是在之后填充:
df = df.resample('T').fillna(None)
df['Open'], df['Close'] = (df['Open'].fillna(df['Close'].ffill()),
df['Close'].fillna(df['Open'].bfill()))
df = df.ffill()
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67123 0.67123 0.67064 0.67062
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
上一个答案(对 OHLC 不正确,但概括起来很有趣)
(df.resample('T')
.fillna(None)
.assign(Close=lambda d: d['Close'].bfill()) # bfill for Close
.ffill() # ffill for others
)
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67068 0.67123 0.67064 0.67223
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
交叉填充值:
(df.resample('T')
.fillna(None)
.assign(Open=lambda d: d['Open'].fillna(d['Close'].ffill())) # Open = last Close
.ffill() # ffill the others
)
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67123 0.67123 0.67064 0.67123
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
更多选项
这是另一个示例,我们将对 High 进行插值并将 Low 保留为 NaN:
(df.resample('T')
.fillna(None)
.assign(Open=lambda d: d['Open'].ffill(),
Close=lambda d: d['Close'].bfill(),
High=lambda d: d['High'].interpolate()
)
)
输出:
Open High Low Close
2019-04-19 00:00:00 0.67068 0.67123 0.67064 0.67123
2019-04-19 00:01:00 0.67068 0.67274 NaN 0.67223
2019-04-19 00:02:00 0.67062 0.67425 0.67060 0.67223
- 如果连续多行缺失值将不起作用,
- “高”和“低”的填充在 OHLC 上下文中不合逻辑。
下面是我会做的(重采样后):
Cross-fill 第一个缺失行
result = df.copy() result['open'] = df['open'].fillna(df['close'].ffill(),limit=1) result['close'] = df['close'].fillna(df['open'].bfill(),limit=1)
现在,在其余行中传播相等的开盘价和闭盘价:
result['open'] = result['open'].fillna(result['close'].ffill()) result['close'] = result['close'].fillna(result['close'].ffill())
最后,逻辑上将高低设置为开盘价和收盘价的最小值和最大值:
result['high'] = result['high'].fillna(result[['open','close']].max(axis=1)) result['low'] = result['low'].fillna((result[['open','close']].min(axis=1)))
此方法适用于多个连续缺失行的情况,并且还会逻辑处理 'high' 和 'low' 的缺失值。