修复未来函数bug
This commit is contained in:
@@ -66,7 +66,7 @@ class TqsdkEngine:
|
||||
self.roll_over_mode = roll_over_mode
|
||||
self.history_length = history_length
|
||||
self.close_bar_delta = close_bar_delta
|
||||
|
||||
|
||||
self.next_close_time = None
|
||||
|
||||
# Tqsdk API 和模拟器
|
||||
@@ -112,15 +112,13 @@ class TqsdkEngine:
|
||||
self.klines = api.get_kline_serial(
|
||||
symbol, duration_seconds, data_length=history_length + 2
|
||||
)
|
||||
self.klines_1min = api.get_kline_serial(
|
||||
symbol, 60
|
||||
)
|
||||
self.klines_1min = api.get_kline_serial(symbol, 60)
|
||||
self.now = None
|
||||
self.quote = None
|
||||
if roll_over_mode:
|
||||
self.quote = api.get_quote(symbol)
|
||||
|
||||
self.kline_row = None
|
||||
self.partial_bar: Bar = None
|
||||
|
||||
print("TqsdkEngine: 初始化完成。")
|
||||
|
||||
@@ -338,14 +336,19 @@ class TqsdkEngine:
|
||||
self._strategy.trading = False
|
||||
|
||||
is_trading_time = is_futures_trading_time()
|
||||
|
||||
|
||||
for i in range(self.history_length + 1, 0 if not is_trading_time else 1, -1):
|
||||
kline_row = self.klines.iloc[-i]
|
||||
kline_dt = pd.to_datetime(kline_row.datetime, unit="ns", utc=True)
|
||||
kline_dt = kline_dt.tz_convert(BEIJING_TZ)
|
||||
self.main(kline_row, self.klines.iloc[-i - 1])
|
||||
|
||||
print(f"TqsdkEngine: 加载历史k线完成, bars数量:{len(self.all_bars)},last bar datetime:{self.all_bars[-1].datetime}")
|
||||
print(
|
||||
f"TqsdkEngine: 加载历史k线完成, bars数量:{len(self.all_bars)},last bar datetime:{self.all_bars[-1].datetime}"
|
||||
)
|
||||
|
||||
for bar in self.all_bars[-5:]:
|
||||
print(bar)
|
||||
|
||||
self._strategy.trading = True
|
||||
self._last_underlying_symbol = self.quote.underlying_symbol
|
||||
@@ -357,7 +360,9 @@ class TqsdkEngine:
|
||||
# 初始化策略 (如果策略有 on_init 方法)
|
||||
if hasattr(self._strategy, "on_init"):
|
||||
self._strategy.on_init()
|
||||
|
||||
|
||||
new_bar = False
|
||||
|
||||
if is_trading_time:
|
||||
print(f"TqsdkEngine: 当前是交易时间,处理最新一根k线")
|
||||
|
||||
@@ -367,10 +372,12 @@ class TqsdkEngine:
|
||||
self.kline_row = kline_row
|
||||
|
||||
self.main(self.klines.iloc[-1], self.klines.iloc[-2])
|
||||
new_bar = True
|
||||
|
||||
# 迭代 K 线数据
|
||||
# 使用 self._api.get_kline_serial 获取到的 K 线是 Pandas DataFrame,
|
||||
# 直接迭代其行(Bar)更符合回测逻辑
|
||||
|
||||
print(f"TqsdkEngine: 开始等待最新数据")
|
||||
while True:
|
||||
# Tqsdk API 的 wait_update() 确保数据更新
|
||||
@@ -383,14 +390,21 @@ class TqsdkEngine:
|
||||
self._last_underlying_symbol = self.quote.underlying_symbol
|
||||
|
||||
if self._api.is_changing(self.klines_1min.iloc[-1], "datetime"):
|
||||
kline_dt = pd.to_datetime(self.kline_row.datetime, unit="ns", utc=True)
|
||||
kline_dt = kline_dt.tz_convert(BEIJING_TZ)
|
||||
if self.kline_row is not None:
|
||||
kline_dt = pd.to_datetime(self.kline_row.datetime, unit="ns", utc=True)
|
||||
kline_dt = kline_dt.tz_convert(BEIJING_TZ)
|
||||
|
||||
is_close_bar = is_bar_pre_close_period(kline_dt, int(self.kline_row.duration), pre_close_minutes=3)
|
||||
is_close_bar = is_bar_pre_close_period(
|
||||
kline_dt, int(self.kline_row.duration), pre_close_minutes=3
|
||||
)
|
||||
|
||||
if is_close_bar:
|
||||
print(f'TqsdkEngine: close bar, kline_dt:{kline_dt}, now: {datetime.now()}')
|
||||
self.close_bar(kline_row)
|
||||
if is_close_bar and new_bar:
|
||||
print(
|
||||
f"TqsdkEngine: close bar, kline_dt:{kline_dt}, now: {datetime.now()}"
|
||||
)
|
||||
self.close_bar(kline_row)
|
||||
|
||||
new_bar = False
|
||||
|
||||
if self._api.is_changing(self.klines.iloc[-1], "datetime"):
|
||||
kline_row = self.klines.iloc[-1]
|
||||
@@ -403,6 +417,8 @@ class TqsdkEngine:
|
||||
)
|
||||
self.main(kline_row, self.klines.iloc[-2])
|
||||
|
||||
new_bar = True
|
||||
|
||||
def close_bar(self, kline_row):
|
||||
kline_dt = pd.to_datetime(kline_row.datetime, unit="ns", utc=True)
|
||||
kline_dt = kline_dt.tz_convert(BEIJING_TZ)
|
||||
@@ -419,13 +435,6 @@ class TqsdkEngine:
|
||||
open_oi=kline_row.open_oi,
|
||||
close_oi=kline_row.close_oi,
|
||||
)
|
||||
self.all_bars[-1] = current_bar
|
||||
|
||||
self.close_list[-1] = current_bar.close
|
||||
self.open_list[-1] = current_bar.open
|
||||
self.high_list[-1] = current_bar.high
|
||||
self.low_list[-1] = current_bar.low
|
||||
self.volume_list[-1] = current_bar.volume
|
||||
|
||||
self.last_processed_bar = current_bar
|
||||
|
||||
@@ -436,64 +445,37 @@ class TqsdkEngine:
|
||||
self._process_queued_requests()
|
||||
|
||||
def main(self, kline_row, prev_kline_row):
|
||||
if True:
|
||||
kline_dt = pd.to_datetime(prev_kline_row.datetime, unit="ns", utc=True)
|
||||
kline_dt = kline_dt.tz_convert(BEIJING_TZ)
|
||||
if len(self.all_bars) > 0:
|
||||
# 创建 core_data.Bar 对象
|
||||
current_bar = Bar(
|
||||
datetime=kline_dt,
|
||||
symbol=self._last_underlying_symbol,
|
||||
open=prev_kline_row.open,
|
||||
high=prev_kline_row.high,
|
||||
low=prev_kline_row.low,
|
||||
close=prev_kline_row.close,
|
||||
volume=prev_kline_row.volume,
|
||||
open_oi=prev_kline_row.open_oi,
|
||||
close_oi=prev_kline_row.close_oi,
|
||||
)
|
||||
self.all_bars[-1] = current_bar
|
||||
kline_dt = pd.to_datetime(kline_row.datetime, unit="ns", utc=True)
|
||||
kline_dt = kline_dt.tz_convert(BEIJING_TZ)
|
||||
|
||||
self.close_list[-1] = current_bar.close
|
||||
self.open_list[-1] = current_bar.open
|
||||
self.high_list[-1] = current_bar.high
|
||||
self.low_list[-1] = current_bar.low
|
||||
self.volume_list[-1] = current_bar.volume
|
||||
|
||||
self.last_processed_bar = current_bar
|
||||
|
||||
# if self._strategy.trading is True:
|
||||
# self._strategy.on_close_bar(current_bar)
|
||||
|
||||
# # 处理订单和取消请求
|
||||
# self._process_queued_requests()
|
||||
|
||||
# on open bar --------------------------------------
|
||||
# 创建 core_data.Bar 对象
|
||||
kline_dt = pd.to_datetime(kline_row.datetime, unit="ns", utc=True)
|
||||
kline_dt = kline_dt.tz_convert(BEIJING_TZ)
|
||||
current_bar = Bar(
|
||||
datetime=kline_dt,
|
||||
symbol=self._last_underlying_symbol,
|
||||
open=kline_row.open,
|
||||
high=kline_row.high,
|
||||
low=kline_row.low,
|
||||
close=kline_row.close,
|
||||
volume=kline_row.volume,
|
||||
open_oi=kline_row.open_oi,
|
||||
close_oi=kline_row.close_oi,
|
||||
if self.partial_bar is not None:
|
||||
last_bar = Bar(
|
||||
datetime=pd.to_datetime(prev_kline_row.datetime, unit="ns", utc=True).tz_convert(BEIJING_TZ),
|
||||
symbol=self.partial_bar.symbol,
|
||||
open=prev_kline_row.open,
|
||||
high=prev_kline_row.high,
|
||||
low=prev_kline_row.low,
|
||||
close=prev_kline_row.close,
|
||||
volume=prev_kline_row.volume,
|
||||
open_oi=prev_kline_row.open_oi,
|
||||
close_oi=prev_kline_row.close_oi,
|
||||
)
|
||||
|
||||
# 设置当前 Bar 到 Context
|
||||
self._context.set_current_bar(current_bar)
|
||||
self.all_bars.append(last_bar)
|
||||
|
||||
self.close_list.append(last_bar.close)
|
||||
self.open_list.append(last_bar.open)
|
||||
self.high_list.append(last_bar.high)
|
||||
self.low_list.append(last_bar.low)
|
||||
self.volume_list.append(last_bar.volume)
|
||||
|
||||
self.last_processed_bar = last_bar
|
||||
|
||||
# Tqsdk 的 is_changing 用于判断数据是否有变化,对于回测遍历 K 线,每次迭代都算作新 Bar
|
||||
# 如果 kline_row.datetime 与上次不同,则认为是新 Bar
|
||||
if (
|
||||
self.roll_over_mode
|
||||
and self.last_processed_bar is not None
|
||||
and self._last_underlying_symbol != self.last_processed_bar.symbol
|
||||
and self._strategy.trading is True
|
||||
and self._strategy.trading
|
||||
):
|
||||
self._is_rollover_bar = True
|
||||
print(
|
||||
@@ -507,27 +489,22 @@ class TqsdkEngine:
|
||||
self.last_processed_bar.symbol, self._last_underlying_symbol
|
||||
)
|
||||
else:
|
||||
self._is_rollover_bar = False
|
||||
self._strategy.on_open_bar(kline_row.open, self._last_underlying_symbol)
|
||||
# 处理订单和取消请求
|
||||
if self._strategy.trading is True:
|
||||
self._process_queued_requests()
|
||||
|
||||
self.all_bars.append(current_bar)
|
||||
|
||||
self.close_list.append(current_bar.close)
|
||||
self.open_list.append(current_bar.open)
|
||||
self.high_list.append(current_bar.high)
|
||||
self.low_list.append(current_bar.low)
|
||||
self.volume_list.append(current_bar.volume)
|
||||
|
||||
self.last_processed_bar = current_bar
|
||||
|
||||
# 调用策略的 on_bar 方法
|
||||
self._strategy.on_open_bar(current_bar)
|
||||
|
||||
# 处理订单和取消请求
|
||||
if self._strategy.trading is True:
|
||||
self._process_queued_requests()
|
||||
|
||||
# 记录投资组合快照
|
||||
self._record_portfolio_snapshot(current_bar.datetime)
|
||||
self.partial_bar = Bar(
|
||||
datetime=kline_dt,
|
||||
symbol=self.quote.underlying_symbol,
|
||||
open=0,
|
||||
high=0,
|
||||
low=0,
|
||||
close=0,
|
||||
volume=0,
|
||||
open_oi=0,
|
||||
close_oi=0,
|
||||
)
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user