Skip to content

Commit b418caf

Browse files
committed
Fix stale tick prices for stacked bars
When a bar is delivered from _barstack via _fromstack (commonly the final bar flushed by _last() in resampled / replayed feeds), the data.tick_* attributes were not synchronized to the bar's OHLC values. Instead they retained values from the previous bar, producing a stale-tick effect that caused broker._try_exec to misprice market orders against the most recent bar. This patch adds a self._tick_fill(force=True) call at the end of _fromstack() so the tick_* attributes always reflect the bar that was just delivered.
1 parent 8a71452 commit b418caf

2 files changed

Lines changed: 19 additions & 0 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919

2020
---
2121

22+
## 🐛 Recent Bug Fixes / 最近修复
23+
24+
### Stacked Bar Tick Refresh (2026-05-28)
25+
26+
**Bug**: 在 `cerebro.resampledata()` / `cerebro.replaydata()` 场景下,当 resampler 通过 `_fromstack` 弹出暂存的 bar 时(特别是数据耗尽时由 `_last()` 刷出的最后一根 bar),`data.tick_open / tick_high / tick_low / tick_close` 不会同步更新到当前 bar 的 OHLC,而是保留前一根 bar 的值("stale tick")。这导致 broker 在用 `tick_open` 估值未平仓位的市价单时使用了过时的价格。
27+
28+
**Fix**: 在 `backtrader/feed.py::_fromstack()` 末尾添加 `self._tick_fill(force=True)`,确保从栈中弹出的 bar 立刻同步 `tick_*` 属性到当前 bar 的 OHLC。
29+
30+
**Impact**: 修复后,使用 `cerebro.resampledata()` 时未平仓位的市价单成交价更准确地反映当前 bar 的 OHLC,而不是上一根 bar 的过时值。
31+
32+
---
33+
2234
## English
2335

2436
### Introduction

backtrader/feed.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,13 @@ def _fromstack(self, forward=False, stash=False):
652652
for line, val in zip(self.itersize(), coll.popleft()):
653653
line[0] = val
654654

655+
# Bug fix: refresh tick_* attributes when delivering a bar from
656+
# the stack. Without this, the tick_open / tick_high / tick_low /
657+
# tick_close attributes can retain values from the previous bar,
658+
# producing a "stale tick" effect that misprices market orders
659+
# executed against bars delivered via _last() / _fromstack
660+
# (typically the final bar in resampled / replayed feeds).
661+
self._tick_fill(force=True)
655662
return True
656663

657664
return False

0 commit comments

Comments
 (0)