Signed-off-by: Dinger <quantdinger@gmail.com>
This commit is contained in:
Dinger
2026-03-25 18:08:45 +08:00
parent 05117f3f5b
commit 15c901364b
4 changed files with 199 additions and 12 deletions
+20 -9
View File
@@ -1274,15 +1274,21 @@ class BacktestService:
signals = pd.Series(0, index=df.index)
try:
# Prepare execution environment
# Reset DatetimeIndex to integer so user code can use df.at[0, ...] or df.iloc[0, ...]
df_for_exec = df.copy()
if isinstance(df_for_exec.index, pd.DatetimeIndex):
df_for_exec = df_for_exec.reset_index(drop=False)
if 'time' not in df_for_exec.columns:
df_for_exec.rename(columns={df_for_exec.columns[0]: 'time'}, inplace=True)
local_vars = {
'df': df.copy(),
'open': df['open'],
'high': df['high'],
'low': df['low'],
'close': df['close'],
'volume': df['volume'],
'signals': signals,
'df': df_for_exec,
'open': df_for_exec['open'],
'high': df_for_exec['high'],
'low': df_for_exec['low'],
'close': df_for_exec['close'],
'volume': df_for_exec['volume'],
'signals': pd.Series(0, index=df_for_exec.index),
'np': np,
'pd': pd,
}
@@ -1366,8 +1372,13 @@ import pandas as pd
if not exec_result['success']:
raise RuntimeError(f"Code execution failed: {exec_result['error']}")
# Get the executed df
# Get the executed df, restore DatetimeIndex for signal alignment
executed_df = exec_env.get('df', df)
if isinstance(df.index, pd.DatetimeIndex) and not isinstance(executed_df.index, pd.DatetimeIndex):
if 'time' in executed_df.columns:
executed_df = executed_df.set_index('time')
elif len(executed_df) == len(df):
executed_df.index = df.index
# Validation: if chart signals are provided, df['buy']/df['sell'] must exist for backtest normalization.
# This keeps indicator scripts simple and consistent (chart=buy/sell, execution=normalized in backend).