{ "cells": [ { "cell_type": "code", "id": "522f09ca7b3fe929", "metadata": { "ExecuteTime": { "end_time": "2025-09-23T07:14:21.841076Z", "start_time": "2025-09-23T07:14:21.809777Z" } }, "source": [ "from datetime import datetime\n", "\n", "from src.data_processing import load_raw_data\n", "%load_ext autoreload\n", "%autoreload 2\n", "\n", "import sys\n", "\n", "if '/mnt/d/PyProject/NewQuant/' not in sys.path:\n", " sys.path.append('/mnt/d/PyProject/NewQuant/')" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The autoreload extension is already loaded. To reload it, use:\n", " %reload_ext autoreload\n" ] } ], "execution_count": 30 }, { "cell_type": "code", "id": "4f7e4b438cea750e", "metadata": { "ExecuteTime": { "end_time": "2025-09-23T07:14:21.879680Z", "start_time": "2025-09-23T07:14:21.856562Z" } }, "source": [ "from turtle import down\n", "from src.analysis.result_analyzer import ResultAnalyzer\n", "# 导入所有必要的模块\n", "from src.data_manager import DataManager\n", "from src.backtest_engine import BacktestEngine\n", "from src.indicators.indicator_list import INDICATOR_LIST\n", "from src.indicators.indicators import *\n", "\n", "# 导入您自己的 SMC 策略\n", "from src.strategies.TrendlineBreakoutStrategy.TrendlineBreakoutStrategy import TrendlineBreakoutStrategy\n", "\n", "# --- 配置参数 ---\n", "# 获取当前脚本所在目录,假设数据文件在项目根目录下的 data 文件夹内\n", "data_file_path = '/mnt/d/PyProject/NewQuant/data/data/KQ_m@CZCE_SA/KQ_m@CZCE_SA_min15.csv'\n", "# data_file_path = \"/mnt/d/PyProject/NewQuant/data/data/KQ_m@DCE_m/KQ_m@DCE_m_min60.csv\"\n", "# data_file_path = \"/mnt/d/PyProject/NewQuant/data/data/KQ_m@CZCE_SA/KQ_m@CZCE_SA_min15.csv\"\n", "# data_file_path = \"/mnt/d/PyProject/NewQuant/data/data/KQ_m@DCE_m/KQ_m@DCE_m_min60.csv\"" ], "outputs": [], "execution_count": 31 }, { "metadata": { "ExecuteTime": { "end_time": "2025-09-23T07:14:21.911306Z", "start_time": "2025-09-23T07:14:21.891023Z" } }, "cell_type": "code", "source": [ "\n", "initial_capital = 100000.0\n", "slippage_rate = 0.000 # 假设每笔交易0.1%的滑点\n", "commission_rate = 0.0000 # 假设每笔交易0.02%的佣金\n", "\n", "global_config = {\n", " 'symbol': 'KQ_m@CZCE_SA', # 确保与数据文件中的 symbol 匹配\n", "}\n", "\n", "# 回测时间范围\n", "start_time = datetime(2021, 1, 1)\n", "end_time = datetime(2024, 3, 12)\n", "\n", "# start_time = datetime(2024, 1, 1)\n", "# end_time = datetime(2025, 8, 1)\n", "\n", "\n", "indicators = INDICATOR_LIST\n", "indicators = []\n", "\n", "# 确保 DataManager 能够重置以进行多次回测\n", "# data_manager.reset() # 首次运行不需要重置" ], "id": "9ee53c41eaaefabb", "outputs": [], "execution_count": 32 }, { "metadata": { "ExecuteTime": { "end_time": "2025-09-23T07:15:11.965857Z", "start_time": "2025-09-23T07:14:21.922851Z" } }, "cell_type": "code", "source": [ "from src.indicators.indicators import ROC_MA\n", "\n", "# --- 1. 初始化数据管理器 ---\n", "print(\"初始化数据管理器...\")\n", "data_manager = DataManager(file_path=data_file_path, symbol=global_config['symbol'], start_time=start_time,\n", " end_time=end_time)\n", "\n", "strategy_parameters = {\n", " 'main_symbol': 'SA', # <-- 替换为你的交易品种代码,例如 'GC=F' (黄金期货), 'ZC=F' (玉米期货)\n", " 'trade_volume': 1,\n", " 'order_direction': ['BUY', 'SELL'],\n", " # 'indicators': [PriceRangeToVolatilityRatio(7, 14, 2.8, 4.3), ROC_MA(10, 10, -2.7, -0.4)],\n", " 'enable_log': False\n", "}\n", "\n", "# --- 2. 初始化回测引擎并运行 ---\n", "print(\"\\n初始化回测引擎...\")\n", "engine = BacktestEngine(\n", " data_manager=data_manager,\n", " strategy_class=TrendlineBreakoutStrategy, # <--- 更改为您的 SMC 策略类\n", " # current_segment_symbol 参数已从 SMCPureH1LongStrategy 中移除,不需要设置\n", " strategy_params=strategy_parameters,\n", " initial_capital=initial_capital,\n", " slippage_rate=slippage_rate,\n", " commission_rate=commission_rate,\n", " roll_over_mode=True,\n", " start_time=start_time,\n", " end_time=end_time,\n", " indicators=indicators # 如果您的 SMC 策略不使用这些指标,也可以考虑移除\n", ")\n", "\n", "print(\"\\n开始运行回测...\")\n", "engine.run_backtest()\n", "print(\"\\n回测运行完毕。\")\n", "\n", "# --- 3. 获取回测结果 ---\n", "results = engine.get_backtest_results()\n", "portfolio_snapshots = results[\"portfolio_snapshots\"]\n", "trade_history = results[\"trade_history\"]\n", "initial_capital_result = results[\"initial_capital\"]\n", "bars = results[\"all_bars\"]\n", "\n", "# --- 4. 结果分析与可视化 ---\n", "if portfolio_snapshots:\n", " analyzer = ResultAnalyzer(portfolio_snapshots, trade_history, bars, initial_capital_result, INDICATOR_LIST)\n", "\n", " analyzer.generate_report()\n", "\n", " analyzer.analyze_indicators()\n", "else:\n", " print(\"\\n没有生成投资组合快照,无法进行结果分析。\")" ], "id": "f903fd2761d446cd", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "初始化数据管理器...\n", "数据加载成功: /mnt/d/PyProject/NewQuant/data/data/KQ_m@CZCE_SA/KQ_m@CZCE_SA_min15.csv\n", "数据范围从 2020-12-31 14:45:00 到 2025-08-26 13:45:00\n", "总计 25662 条记录。\n", "\n", "初始化回测引擎...\n", "模拟器初始化:初始资金=100000.00, 滑点率=0.0, 佣金率=0.0\n", "\n", "--- 回测引擎初始化完成 ---\n", " 策略: TrendlineBreakoutStrategy\n", " 初始资金: 100000.00\n", " 换月模式: 启用\n", "\n", "开始运行回测...\n", "\n", "--- 回测开始 ---\n", "TrendlineBreakoutStrategy 策略初始化回调被调用。\n", "开始将 DataFrame 转换为 Bar 对象流...\n", "Bar 对象流生成完毕。\n", "\n", "--- 回测结束,检查并平仓所有剩余持仓 ---\n", "--- 回测结束 ---\n", "总计处理了 17565 根K线。\n", "总计发生了 1974 笔交易。\n", "最终总净值: 101664.00\n", "总收益率: 1.66%\n", "\n", "回测运行完毕。\n" ] } ], "execution_count": 33 }, { "metadata": { "ExecuteTime": { "end_time": "2025-09-23T07:15:18.149306Z", "start_time": "2025-09-23T07:15:11.986337Z" } }, "cell_type": "code", "source": [ "from matplotlib import pyplot as plt\n", "from sklearn.metrics import confusion_matrix\n", "from src.core_data import Trade\n", "import pandas as pd\n", "import numpy as np\n", "import joblib\n", "import talib\n", "from dataclasses import dataclass, field\n", "from typing import Dict, List, Tuple, Optional\n", "\n", "# --- 机器学习库 ---\n", "import xgboost as xgb\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.preprocessing import StandardScaler\n", "from sklearn.metrics import accuracy_score, classification_report\n", "import seaborn as sns\n", "\n", "\n", "# 这是您提供的趋势线计算函数,我们将其独立出来用于特征计算\n", "def _calculate_latest_trendline_values(prices: np.ndarray) -> Tuple[Optional[float], Optional[float]]:\n", " n = len(prices)\n", " if n < 2 or np.isnan(prices).any(): return None, None\n", " x = np.arange(n)\n", " high_point_idx = np.argmax(prices)\n", " high_point_price = prices[high_point_idx]\n", " best_upper_slope = None\n", " min_upper_distance_sum = float('inf')\n", " for i in range(n):\n", " if i == high_point_idx or (i - high_point_idx) == 0: continue\n", " candidate_slope = (prices[i] - high_point_price) / (i - high_point_idx)\n", " intercept = high_point_price - candidate_slope * high_point_idx\n", " candidate_line = candidate_slope * x + intercept\n", " if np.all(candidate_line >= prices - 1e-9):\n", " distance_sum = np.sum(candidate_line - prices)\n", " if distance_sum < min_upper_distance_sum:\n", " min_upper_distance_sum = distance_sum\n", " best_upper_slope = candidate_slope\n", " if best_upper_slope is None: return None, None\n", " upper_intercept = high_point_price - best_upper_slope * high_point_idx\n", " latest_upper_value = best_upper_slope * (n - 1) + upper_intercept\n", " low_point_idx = np.argmin(prices)\n", " low_point_price = prices[low_point_idx]\n", " best_lower_slope = None\n", " min_lower_distance_sum = float('inf')\n", " for i in range(n):\n", " if i == low_point_idx or (i - low_point_idx) == 0: continue\n", " candidate_slope = (prices[i] - low_point_price) / (i - low_point_idx)\n", " intercept = low_point_price - candidate_slope * low_point_idx\n", " candidate_line = candidate_slope * x + intercept\n", " if np.all(candidate_line <= prices + 1e-9):\n", " distance_sum = np.sum(prices - candidate_line)\n", " if distance_sum < min_lower_distance_sum:\n", " min_lower_distance_sum = distance_sum\n", " best_lower_slope = candidate_slope\n", " if best_lower_slope is None: return None, None\n", " lower_intercept = low_point_price - best_lower_slope * low_point_idx\n", " latest_lower_value = best_lower_slope * (n - 1) + lower_intercept\n", " return latest_upper_value, latest_lower_value\n", "\n", "\n", "def calculate_features(df: pd.DataFrame, trendline_n: int = 50) -> pd.DataFrame:\n", " \"\"\"\n", " 【单一事实来源】\n", " 接收一个OHLCV DataFrame,计算并返回所有模型需要的特征。\n", " 训练和预测都必须调用此函数。\n", " \"\"\"\n", " # 确保数据按时间排序\n", " df = df.sort_values('datetime').reset_index(drop=True)\n", "\n", " # --- 基础指标 ---\n", " df['roc'] = talib.ROC(df['close'], timeperiod=10)\n", " df['roc_ma'] = talib.MA(df['roc'], timeperiod=5)\n", " df['rsi'] = talib.RSI(df['close'], timeperiod=14)\n", " df['adx'] = talib.ADX(df['high'], df['low'], df['close'], timeperiod=14)\n", "\n", " # --- 【修正】统一的趋势线和价差计算 ---\n", " close_prices = df['close'].values\n", " trend_results = [\n", " _calculate_latest_trendline_values(close_prices[i - trendline_n:i]) if i >= trendline_n else (np.nan, np.nan)\n", " for i in range(len(close_prices))\n", " ]\n", " trend_df = pd.DataFrame(trend_results, index=df.index, columns=['upper_trendline', 'lower_trendline'])\n", "\n", " df['trendline_slope'] = (trend_df['upper_trendline'] - trend_df['lower_trendline']) / trendline_n\n", "\n", " # 【关键修正】根据错误信息,训练时使用的是 'gap_from_prev_close'\n", " # 它的计算方式很可能就是当前close与上一根close的价差,我们在这里重现它\n", " df['gap_from_prev_close'] = df['close'].diff()\n", "\n", " # 同时,我们保留 price_gap_to_lower_trendline,因为这可能是个有用的特征\n", " # 如果你确定不再需要它,可以注释掉下面这行\n", " df['price_gap_to_lower_trendline'] = df['close'] - trend_df['lower_trendline']\n", "\n", " return df\n", "\n", "\n", "# ==============================================================================\n", "# 3. 核心功能:特征工程与数据预处理\n", "# ==============================================================================\n", "def create_features_from_ohlc(df: pd.DataFrame, trendline_n: int = 50) -> pd.DataFrame:\n", " \"\"\"\n", " 现在这个函数只是一个包装器,直接调用共享的特征计算函数。\n", " \"\"\"\n", " print(\"\\n开始计算特征...\")\n", " df_featured = calculate_features(df, trendline_n=trendline_n)\n", " df_featured = df_featured.dropna().reset_index(drop=True)\n", " print(\"特征计算和清洗完成。\")\n", " return df_featured\n", "\n", "\n", "import pandas as pd\n", "from typing import List\n", "\n", "\n", "# 假设 Trade class 和其他依赖已定义\n", "\n", "def build_training_set(trade_history: List[Trade], df_with_features: pd.DataFrame, feature_columns: List[str]) -> (pd.DataFrame, pd.Series):\n", " \"\"\"\n", " 将交易历史与带有特征的行情数据链接,构建训练集。\n", " 【已修正以兼容新版pandas】\n", " \"\"\"\n", " # 确保两个DataFrame的datetime列都是datetime对象\n", " df_with_features['datetime'] = pd.to_datetime(df_with_features['datetime'])\n", "\n", " # 为了快速查找,将datetime设置为索引并排序\n", " df_indexed = df_with_features.set_index('datetime').sort_index()\n", "\n", " features_list = []\n", " labels_list = []\n", "\n", " print(f\"\\n开始构建训练集,共 {len(trade_history) // 2} 对交易...\")\n", "\n", " # 提取所有开仓交易的时间和盈亏信息\n", " open_times = []\n", " trade_outcomes = []\n", " for i in range(0, len(trade_history), 2):\n", " open_trade = trade_history[i]\n", " close_trade = trade_history[i + 1]\n", " if open_trade.is_open_trade and close_trade.is_close_trade:\n", " open_times.append(open_trade.fill_time)\n", " trade_outcomes.append(1 if close_trade.realized_pnl > 0 else 0)\n", "\n", " # 将交易时间转换为pandas的DatetimeIndex\n", " trade_times_idx = pd.to_datetime(open_times)\n", "\n", " # --- 【核心修正】使用 get_indexer 进行定位 ---\n", " # get_indexer 会返回每个交易时间在df_indexed中的位置索引。\n", " # method='ffill' (forward fill) 确保如果某个交易时间不存在,\n", " # 它会找到该时间点之前最近的一个有效索引。\n", " locations = df_indexed.index.get_indexer(trade_times_idx, method='ffill')\n", "\n", " # 过滤掉无法找到位置的交易 (例如,交易时间早于所有行情数据)\n", " valid_locations = locations[locations != -1]\n", " valid_outcomes = [outcome for i, outcome in enumerate(trade_outcomes) if locations[i] != -1]\n", "\n", " if len(valid_locations) == 0:\n", " raise ValueError(\"未能将任何交易时间匹配到行情数据!请检查时间戳是否对齐。\")\n", "\n", " # 根据找到的位置索引,一次性提取所有对应的特征行\n", " matched_features_df = df_indexed.iloc[valid_locations]\n", "\n", " X = matched_features_df.reset_index(drop=True)\n", " y = pd.Series(valid_outcomes, name=\"is_profitable\")\n", "\n", " # 确保所有需要的列都存在\n", " missing_cols = [col for col in feature_columns if col not in X.columns]\n", " if missing_cols:\n", " raise KeyError(f\"以下特征列在数据中缺失: {missing_cols}\")\n", "\n", " X = X[feature_columns]\n", "\n", " print(f\"训练集构建完成。生成了 {len(X)} 个样本。\")\n", " print(f\"盈利样本比例: {y.mean() * 100:.2f}%\")\n", "\n", " return X, y\n", "\n", "\n", "# ==============================================================================\n", "# 4. 模型训练与评估 (与上一版基本相同)\n", "# ==============================================================================\n", "def train_and_evaluate_filter_model(X: pd.DataFrame, y: pd.Series, model_path: str, scaler_path: str):\n", " print(\"\\n--- 开始模型训练流程 ---\")\n", " X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)\n", " scaler = StandardScaler()\n", " X_train_scaled = scaler.fit_transform(X_train)\n", " X_test_scaled = scaler.transform(X_test)\n", " # joblib.dump(scaler, scaler_path)\n", " print(f\"特征缩放器 (Scaler) 已保存至: {scaler_path}\")\n", " model = xgb.XGBClassifier(eval_metric='logloss', random_state=42)\n", " model.fit(X_train_scaled, y_train)\n", " # joblib.dump(model, model_path)\n", " print(f\"训练好的模型已保存至: {model_path}\")\n", " print(\"\\n--- 模型评估 ---\")\n", " y_pred = model.predict(X_test_scaled)\n", " print(f\"测试集准确率 (Accuracy): {accuracy_score(y_test, y_pred):.4f}\")\n", " print(\"\\n分类报告 (Classification Report):\")\n", " print(classification_report(y_test, y_pred, target_names=[\"亏损(0)\", \"盈利(1)\"]))\n", "\n", " return model, scaler\n", "\n", "\n", "# ==============================================================================\n", "# 5. 主执行流程\n", "# ==============================================================================\n", "MODEL_SAVE_PATH = \"trade_filter_model_v2.joblib\"\n", "SCALER_SAVE_PATH = \"trade_filter_scaler_v2.joblib\"\n", "TRENDLINE_PERIOD = 50\n", "\n", "\n", "feature_columns = [\n", " 'roc',\n", " 'roc_ma',\n", " 'rsi',\n", " 'adx',\n", " 'trendline_slope',\n", " 'gap_from_prev_close'\n", "]\n", "\n", "# 加载数据并获取日期范围以生成匹配的交易\n", "ohlc_df = pd.read_csv(data_file_path, parse_dates=['datetime'])\n", "\n", "# --- 步骤 2: 特征工程 ---\n", "df_with_features = create_features_from_ohlc(ohlc_df, trendline_n=TRENDLINE_PERIOD)\n", "\n", "# --- 步骤 3: 构建训练集 ---\n", "X_features, y_labels = build_training_set(trade_history, df_with_features, feature_columns)\n", "# --- 在这里加入验证代码 ---\n", "print(\"\\n--- 验证标签集合 ---\")\n", "unique_labels_in_data = sorted(y_labels.unique())\n", "print(f\"数据集中实际存在的标签类别: {unique_labels_in_data}\")\n", "if len(unique_labels_in_data) < 4:\n", " print(\"警告:训练数据中未包含全部四种交易结果,模型将被训练为少于4类的分类器。\")\n", "# -------------------------\n", "# --- 步骤 4: 训练并保存模型 ---\n", "model, scaler = train_and_evaluate_filter_model(X_features, y_labels, MODEL_SAVE_PATH, SCALER_SAVE_PATH)\n", "\n", "print(f\"\\n训练流程完成!模型和Scaler已保存。\")" ], "id": "7aa58a71f10abb2d", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "开始计算特征...\n", "特征计算和清洗完成。\n", "\n", "开始构建训练集,共 987 对交易...\n", "训练集构建完成。生成了 987 个样本。\n", "盈利样本比例: 36.07%\n", "\n", "--- 验证标签集合 ---\n", "数据集中实际存在的标签类别: [np.int64(0), np.int64(1)]\n", "警告:训练数据中未包含全部四种交易结果,模型将被训练为少于4类的分类器。\n", "\n", "--- 开始模型训练流程 ---\n", "特征缩放器 (Scaler) 已保存至: trade_filter_scaler_v2.joblib\n", "训练好的模型已保存至: trade_filter_model_v2.joblib\n", "\n", "--- 模型评估 ---\n", "测试集准确率 (Accuracy): 0.6498\n", "\n", "分类报告 (Classification Report):\n", " precision recall f1-score support\n", "\n", " 亏损(0) 0.72 0.74 0.73 190\n", " 盈利(1) 0.51 0.49 0.50 107\n", "\n", " accuracy 0.65 297\n", " macro avg 0.62 0.61 0.62 297\n", "weighted avg 0.65 0.65 0.65 297\n", "\n", "\n", "训练流程完成!模型和Scaler已保存。\n" ] } ], "execution_count": 34 }, { "metadata": { "ExecuteTime": { "end_time": "2025-09-23T07:15:18.184361Z", "start_time": "2025-09-23T07:15:18.162545Z" } }, "cell_type": "code", "source": [ "# =-============================================================================\n", "# 【最终修正版 V2】机器学习过滤器指标\n", "# ==============================================================================\n", "class MLFilterIndicator(Indicator):\n", " \"\"\"\n", " 一个将【已加载的】机器学习模型封装为标准指标的过滤器。\n", " 它接收模型、scaler对象以及一个明确的特征列表。\n", " \"\"\"\n", "\n", " def __init__(self,\n", " model: xgb.XGBClassifier,\n", " scaler: StandardScaler,\n", " feature_names: List[str], # <-- 【新增】显式传入特征名称列表\n", " trendline_n: int = 50,\n", " down_bound: float = 0.5,\n", " up_bound: float = None,\n", " shift_window: int = 0):\n", "\n", " super().__init__(down_bound, up_bound, shift_window)\n", " self.trendline_n = trendline_n\n", "\n", " # --- 【修改】更稳健的初始化 ---\n", " # 不再使用try...except来隐藏问题,而是进行明确的检查\n", " if model is None or scaler is None:\n", " raise ValueError(\"传入的model或scaler对象不能为空。\")\n", " if not feature_names or not isinstance(feature_names, list):\n", " raise ValueError(\"必须传入一个包含特征名称的列表 (feature_names)。\")\n", "\n", " self.model = model\n", " self.scaler = scaler\n", " self.feature_names = feature_names # <-- 直接使用传入的列表\n", "\n", " print(\"ML过滤器已成功初始化。\")\n", " print(f\"将使用的特征列表: {self.feature_names}\")\n", "\n", " def get_name(self) -> str:\n", " return f\"MLFilter_TrendN{self.trendline_n}\"\n", "\n", " def get_values(self, close: np.array, open: np.array, high: np.array, low: np.array,\n", " volume: np.array) -> np.ndarray:\n", " # 【关键】现在 get_values 的实现变得非常简洁\n", " df = pd.DataFrame(\n", " {'datetime': pd.to_datetime(np.arange(len(close))), 'open': open, 'high': high, 'low': low, 'close': close,\n", " 'volume': volume})\n", "\n", " # 直接调用统一的特征计算函数\n", " df_with_features = calculate_features(df, trendline_n=self.trendline_n)\n", "\n", " # --- 后续的预测流程与之前相同 ---\n", " required_cols = self.feature_names\n", " df_filtered = df_with_features[required_cols].dropna()\n", "\n", " if df_filtered.empty:\n", " return np.full_like(close, np.nan, dtype=float)\n", "\n", " X = df_filtered[self.feature_names]\n", " X_scaled = self.scaler.transform(X)\n", "\n", " profit_proba = self.model.predict_proba(X_scaled)[:, 1]\n", "\n", " prediction_series = pd.Series(profit_proba, index=X.index)\n", " aligned_predictions = prediction_series.reindex(df.index)\n", "\n", " return aligned_predictions.values\n", "\n" ], "id": "bfd8ff1e602c6545", "outputs": [], "execution_count": 35 }, { "metadata": { "ExecuteTime": { "end_time": "2025-09-23T08:06:51.838537Z", "start_time": "2025-09-23T08:01:45.486079Z" } }, "cell_type": "code", "source": [ "from src.indicators.indicators import ROC_MA\n", "from src.strategies.TrendlineBreakoutStrategy.TrendlineBreakoutStrategy import TrendlineBreakoutStrategy\n", "\n", "start_time = datetime(2024, 1, 1)\n", "end_time = datetime(2025, 8, 1)\n", "\n", "\n", "# --- 1. 初始化数据管理器 ---\n", "print(\"初始化数据管理器...\")\n", "data_manager = DataManager(file_path=data_file_path, symbol=global_config['symbol'], start_time=start_time,\n", " end_time=end_time)\n", "\n", "strategy_parameters = {\n", " 'main_symbol': 'SA', # <-- 替换为你的交易品种代码,例如 'GC=F' (黄金期货), 'ZC=F' (玉米期货)\n", " 'trade_volume': 1,\n", " 'order_direction': ['BUY', 'SELL'],\n", " 'indicators': [MLFilterIndicator(model, scaler, feature_names), MLFilterIndicator(model, scaler, feature_columns)],\n", " 'enable_log': False\n", "}\n", "\n", "# --- 2. 初始化回测引擎并运行 ---\n", "print(\"\\n初始化回测引擎...\")\n", "engine = BacktestEngine(\n", " data_manager=data_manager,\n", " strategy_class=TrendlineBreakoutStrategy, # <--- 更改为您的 SMC 策略类\n", " # current_segment_symbol 参数已从 SMCPureH1LongStrategy 中移除,不需要设置\n", " strategy_params=strategy_parameters,\n", " initial_capital=initial_capital,\n", " slippage_rate=slippage_rate,\n", " commission_rate=commission_rate,\n", " roll_over_mode=True,\n", " start_time=start_time,\n", " end_time=end_time,\n", " indicators=indicators # 如果您的 SMC 策略不使用这些指标,也可以考虑移除\n", ")\n", "\n", "print(\"\\n开始运行回测...\")\n", "engine.run_backtest()\n", "print(\"\\n回测运行完毕。\")\n", "\n", "# --- 3. 获取回测结果 ---\n", "results = engine.get_backtest_results()\n", "portfolio_snapshots = results[\"portfolio_snapshots\"]\n", "trade_history = results[\"trade_history\"]\n", "initial_capital_result = results[\"initial_capital\"]\n", "bars = results[\"all_bars\"]\n", "\n", "# --- 4. 结果分析与可视化 ---\n", "if portfolio_snapshots:\n", " analyzer = ResultAnalyzer(portfolio_snapshots, trade_history, bars, initial_capital_result, INDICATOR_LIST)\n", "\n", " analyzer.generate_report()\n", " analyzer.plot_performance()\n", " metrics = analyzer.calculate_all_metrics()\n", " print(metrics)\n", "\n", " analyzer.analyze_indicators()\n", "else:\n", " print(\"\\n没有生成投资组合快照,无法进行结果分析。\")" ], "id": "c7452f42eb4e9345", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "初始化数据管理器...\n", "数据加载成功: /mnt/d/PyProject/NewQuant/data/data/KQ_m@CZCE_SA/KQ_m@CZCE_SA_min15.csv\n", "数据范围从 2020-12-31 14:45:00 到 2025-08-26 13:45:00\n", "总计 25662 条记录。\n", "ML过滤器已成功初始化。\n", "将使用的特征列表: ['roc', 'roc_ma', 'rsi', 'adx', 'trendline_slope', 'gap_from_prev_close']\n", "ML过滤器已成功初始化。\n", "将使用的特征列表: ['roc', 'roc_ma', 'rsi', 'adx', 'trendline_slope', 'gap_from_prev_close']\n", "\n", "初始化回测引擎...\n", "模拟器初始化:初始资金=100000.00, 滑点率=0.0, 佣金率=0.0\n", "\n", "--- 回测引擎初始化完成 ---\n", " 策略: TrendlineBreakoutStrategy\n", " 初始资金: 100000.00\n", " 换月模式: 启用\n", "\n", "开始运行回测...\n", "\n", "--- 回测开始 ---\n", "TrendlineBreakoutStrategy 策略初始化回调被调用。\n", "开始将 DataFrame 转换为 Bar 对象流...\n", "2024-01-04 10:30:00\n", "2024-01-04 10:45:00\n", "2024-01-04 11:00:00\n", "2024-01-04 11:15:00\n", "2024-01-04 13:30:00\n", "2024-01-04 13:45:00\n", "2024-01-04 14:00:00\n", "2024-01-04 14:15:00\n", "2024-01-04 14:30:00\n", "2024-01-04 14:45:00\n", "2024-01-04 21:00:00\n", "2024-01-04 21:15:00\n", "2024-01-04 21:30:00\n", "2024-01-04 21:45:00\n", "2024-01-04 22:00:00\n", "2024-01-04 22:15:00\n", "2024-01-04 22:30:00\n", "2024-01-04 22:45:00\n", "2024-01-05 09:00:00\n", "2024-01-05 09:15:00\n", "2024-01-05 09:30:00\n", "2024-01-05 09:45:00\n", "2024-01-05 10:00:00\n", "2024-01-05 10:30:00\n", "2024-01-05 10:45:00\n", "2024-01-05 11:00:00\n", "2024-01-05 11:15:00\n", "2024-01-05 13:30:00\n", "2024-01-05 13:45:00\n", "2024-01-05 14:00:00\n", "2024-01-05 14:15:00\n", "2024-01-05 14:30:00\n", "2024-01-05 14:45:00\n", "2024-01-05 21:00:00\n", "2024-01-05 21:15:00\n", "2024-01-05 21:30:00\n", "2024-01-05 21:45:00\n", "2024-01-05 22:00:00\n", "2024-01-05 22:15:00\n", "2024-01-05 22:30:00\n", "2024-01-05 22:45:00\n", "2024-01-08 09:00:00\n", "2024-01-08 09:15:00\n", "2024-01-08 09:30:00\n", "2024-01-08 09:45:00\n", "2024-01-08 10:00:00\n", "2024-01-08 10:30:00\n", "2024-01-08 10:45:00\n", "2024-01-08 11:00:00\n", "2024-01-08 11:15:00\n", "2024-01-08 13:30:00\n", "2024-01-08 13:45:00\n", "2024-01-08 14:00:00\n", "2024-01-08 14:15:00\n", "2024-01-08 14:30:00\n", "2024-01-08 14:45:00\n", "2024-01-08 21:00:00\n", "2024-01-08 21:15:00\n", "2024-01-08 21:30:00\n", "2024-01-08 21:45:00\n", "2024-01-08 22:00:00\n", "2024-01-08 22:15:00\n", "2024-01-08 22:30:00\n", "2024-01-08 22:45:00\n", "2024-01-09 09:00:00\n", "2024-01-09 09:15:00\n", "2024-01-09 09:30:00\n", "2024-01-09 09:45:00\n", "2024-01-09 10:00:00\n", "2024-01-09 10:30:00\n", "2024-01-09 10:45:00\n", "2024-01-09 11:00:00\n", "2024-01-09 11:15:00\n", "2024-01-09 13:30:00\n", "2024-01-09 13:45:00\n", "2024-01-09 14:00:00\n", "2024-01-09 14:15:00\n", "2024-01-09 14:30:00\n", "2024-01-09 14:45:00\n", "2024-01-09 21:00:00\n", "2024-01-09 21:15:00\n", "2024-01-09 21:30:00\n", "2024-01-09 21:45:00\n", "2024-01-09 22:00:00\n", "2024-01-09 22:15:00\n", "2024-01-09 22:30:00\n", "2024-01-09 22:45:00\n", "2024-01-10 09:00:00\n", "2024-01-10 09:15:00\n", "2024-01-10 09:30:00\n", "2024-01-10 09:45:00\n", "2024-01-10 10:00:00\n", "2024-01-10 10:30:00\n", "2024-01-10 10:45:00\n", "2024-01-10 11:00:00\n", "2024-01-10 11:15:00\n", "2024-01-10 13:30:00\n", "2024-01-10 13:45:00\n", "2024-01-10 14:00:00\n", "2024-01-10 14:15:00\n", "2024-01-10 14:30:00\n", "2024-01-10 14:45:00\n", "2024-01-10 21:00:00\n", "2024-01-10 21:15:00\n", "2024-01-10 21:30:00\n", "2024-01-10 21:45:00\n", "2024-01-10 22:00:00\n", "2024-01-10 22:15:00\n", "2024-01-10 22:30:00\n", "2024-01-10 22:45:00\n", "2024-01-11 09:00:00\n", "2024-01-11 09:15:00\n", "2024-01-11 09:30:00\n", "2024-01-11 09:45:00\n", "2024-01-11 10:00:00\n", "2024-01-11 10:30:00\n", "2024-01-11 10:45:00\n", "2024-01-11 11:00:00\n", "2024-01-11 11:15:00\n", "2024-01-11 13:30:00\n", "2024-01-11 13:45:00\n", "2024-01-11 14:00:00\n", "2024-01-11 14:15:00\n", "2024-01-11 14:30:00\n", "2024-01-11 14:45:00\n", "2024-01-11 21:00:00\n", "2024-01-11 21:15:00\n", "2024-01-11 21:30:00\n", "2024-01-11 21:45:00\n", "2024-01-11 22:00:00\n", "2024-01-11 22:15:00\n", "2024-01-11 22:30:00\n", "2024-01-11 22:45:00\n", "2024-01-12 09:00:00\n", "2024-01-12 09:15:00\n", "2024-01-12 09:30:00\n", "2024-01-12 09:45:00\n", "2024-01-12 10:00:00\n", "2024-01-12 10:30:00\n", "2024-01-12 10:45:00\n", "2024-01-12 11:00:00\n", "2024-01-12 11:15:00\n", "2024-01-12 13:30:00\n", "2024-01-12 13:45:00\n", "2024-01-12 14:00:00\n", "2024-01-12 14:15:00\n", "2024-01-12 14:30:00\n", "2024-01-12 14:45:00\n", "2024-01-12 21:00:00\n", "2024-01-12 21:15:00\n", "2024-01-12 21:30:00\n", "2024-01-12 21:45:00\n", "2024-01-12 22:00:00\n", "2024-01-12 22:15:00\n", "2024-01-12 22:30:00\n", "2024-01-12 22:45:00\n", "2024-01-15 09:00:00\n", "2024-01-15 09:15:00\n", "2024-01-15 09:30:00\n", "2024-01-15 09:45:00\n", "2024-01-15 10:00:00\n", "2024-01-15 10:30:00\n", "2024-01-15 10:45:00\n", "2024-01-15 11:00:00\n", "2024-01-15 11:15:00\n", "2024-01-15 13:30:00\n", "2024-01-15 13:45:00\n", "2024-01-15 14:00:00\n", "2024-01-15 14:15:00\n", "2024-01-15 14:30:00\n", "2024-01-15 14:45:00\n", "2024-01-15 21:00:00\n", "2024-01-15 21:15:00\n", "2024-01-15 21:30:00\n", "2024-01-15 21:45:00\n", "2024-01-15 22:00:00\n", "2024-01-15 22:15:00\n", "2024-01-15 22:30:00\n", "2024-01-15 22:45:00\n", "2024-01-16 09:00:00\n", "2024-01-16 09:15:00\n", "2024-01-16 09:30:00\n", "2024-01-16 09:45:00\n", "2024-01-16 10:00:00\n", "2024-01-16 10:30:00\n", "2024-01-16 10:45:00\n", "2024-01-16 11:00:00\n", "2024-01-16 11:15:00\n", "2024-01-16 13:30:00\n", "2024-01-16 13:45:00\n", "2024-01-16 14:00:00\n", "2024-01-16 14:15:00\n", "2024-01-16 14:30:00\n", "2024-01-16 14:45:00\n", "2024-01-16 21:00:00\n", "2024-01-16 21:15:00\n", "2024-01-16 21:30:00\n", "2024-01-16 21:45:00\n", "2024-01-16 22:00:00\n", "2024-01-16 22:15:00\n", "2024-01-16 22:30:00\n", "2024-01-16 22:45:00\n", "2024-01-17 09:00:00\n", "2024-01-17 09:15:00\n", "2024-01-17 09:30:00\n", "2024-01-17 09:45:00\n", "2024-01-17 10:00:00\n", "2024-01-17 10:30:00\n", "2024-01-17 10:45:00\n", "2024-01-17 11:00:00\n", "2024-01-17 11:15:00\n", "2024-01-17 13:30:00\n", "2024-01-17 13:45:00\n", "2024-01-17 14:00:00\n", "2024-01-17 14:15:00\n", "2024-01-17 14:30:00\n", "2024-01-17 14:45:00\n", "2024-01-17 21:00:00\n", "2024-01-17 21:15:00\n", "2024-01-17 21:30:00\n", "2024-01-17 21:45:00\n", "2024-01-17 22:00:00\n", "2024-01-17 22:15:00\n", "2024-01-17 22:30:00\n", "2024-01-17 22:45:00\n", "2024-01-18 09:00:00\n", "2024-01-18 09:15:00\n", "2024-01-18 09:30:00\n", "2024-01-18 09:45:00\n", "2024-01-18 10:00:00\n", "2024-01-18 10:30:00\n", "2024-01-18 10:45:00\n", "2024-01-18 11:00:00\n", "2024-01-18 11:15:00\n", "2024-01-18 13:30:00\n", "2024-01-18 13:45:00\n", "2024-01-18 14:00:00\n", "2024-01-18 14:15:00\n", "2024-01-18 14:30:00\n", "2024-01-18 14:45:00\n", "2024-01-18 21:00:00\n", "2024-01-18 21:15:00\n", "2024-01-18 21:30:00\n", "2024-01-18 21:45:00\n", "2024-01-18 22:00:00\n", "2024-01-18 22:15:00\n", "2024-01-18 22:30:00\n", "2024-01-18 22:45:00\n", "2024-01-19 09:00:00\n", "2024-01-19 09:15:00\n", "2024-01-19 09:30:00\n", "2024-01-19 09:45:00\n", "2024-01-19 10:00:00\n", "2024-01-19 10:30:00\n", "2024-01-19 10:45:00\n", "2024-01-19 11:00:00\n", "2024-01-19 11:15:00\n", "2024-01-19 13:30:00\n", "2024-01-19 13:45:00\n", "2024-01-19 14:00:00\n", "2024-01-19 14:15:00\n", "2024-01-19 14:30:00\n", "2024-01-19 14:45:00\n", "2024-01-19 21:00:00\n", "2024-01-19 21:15:00\n", "2024-01-19 21:30:00\n", "2024-01-19 21:45:00\n", "2024-01-19 22:00:00\n", "2024-01-19 22:15:00\n", "2024-01-19 22:30:00\n", "2024-01-19 22:45:00\n", "2024-01-22 09:00:00\n", "2024-01-22 09:15:00\n", "2024-01-22 09:30:00\n", "2024-01-22 09:45:00\n", "2024-01-22 10:00:00\n", "2024-01-22 10:30:00\n", "2024-01-22 10:45:00\n", "2024-01-22 11:00:00\n", "2024-01-22 11:15:00\n", "2024-01-22 13:30:00\n", "2024-01-22 13:45:00\n", "2024-01-22 14:00:00\n", "2024-01-22 14:15:00\n", "2024-01-22 14:30:00\n", "2024-01-22 14:45:00\n", "2024-01-22 21:00:00\n", "2024-01-22 21:15:00\n", "2024-01-22 21:30:00\n", "2024-01-22 21:45:00\n", "2024-01-22 22:00:00\n", "2024-01-22 22:15:00\n", "2024-01-22 22:30:00\n", "2024-01-22 22:45:00\n", "2024-01-23 09:00:00\n", "2024-01-23 09:15:00\n", "2024-01-23 09:30:00\n", "2024-01-23 09:45:00\n", "2024-01-23 10:00:00\n", "2024-01-23 10:30:00\n", "2024-01-23 10:45:00\n", "2024-01-23 11:00:00\n", "2024-01-23 11:15:00\n", "2024-01-23 13:30:00\n", "2024-01-23 13:45:00\n", "2024-01-23 14:00:00\n", "2024-01-23 14:15:00\n", "2024-01-23 14:30:00\n", "2024-01-23 14:45:00\n", "2024-01-23 21:00:00\n", "2024-01-23 21:15:00\n", "2024-01-23 21:30:00\n", "2024-01-23 21:45:00\n", "2024-01-23 22:00:00\n", "2024-01-23 22:15:00\n", "2024-01-23 22:30:00\n", "2024-01-23 22:45:00\n", "2024-01-24 09:00:00\n", "2024-01-24 09:15:00\n", "2024-01-24 09:30:00\n", "2024-01-24 09:45:00\n", "2024-01-24 10:00:00\n", "2024-01-24 10:30:00\n", "2024-01-24 10:45:00\n", "2024-01-24 11:00:00\n", "2024-01-24 11:15:00\n", "2024-01-24 13:30:00\n", "2024-01-24 13:45:00\n", "2024-01-24 14:00:00\n", "2024-01-24 14:15:00\n", "2024-01-24 14:30:00\n", "2024-01-24 14:45:00\n", "2024-01-24 21:00:00\n", "2024-01-24 21:15:00\n", "2024-01-24 21:30:00\n", "2024-01-24 21:45:00\n", "2024-01-24 22:00:00\n", "2024-01-24 22:15:00\n", "2024-01-24 22:30:00\n", "2024-01-24 22:45:00\n", "2024-01-25 09:00:00\n", "2024-01-25 09:15:00\n", "2024-01-25 09:30:00\n", "2024-01-25 09:45:00\n", "2024-01-25 10:00:00\n", "2024-01-25 10:30:00\n", "2024-01-25 10:45:00\n", "2024-01-25 11:00:00\n", "2024-01-25 11:15:00\n", "2024-01-25 13:30:00\n", "2024-01-25 13:45:00\n", "2024-01-25 14:00:00\n", "2024-01-25 14:15:00\n", "2024-01-25 14:30:00\n", "2024-01-25 14:45:00\n", "2024-01-25 21:00:00\n", "2024-01-25 21:15:00\n", "2024-01-25 21:30:00\n", "2024-01-25 21:45:00\n", "2024-01-25 22:00:00\n", "2024-01-25 22:15:00\n", "2024-01-25 22:30:00\n", "2024-01-25 22:45:00\n", "2024-01-26 09:00:00\n", "2024-01-26 09:15:00\n", "2024-01-26 09:30:00\n", "2024-01-26 09:45:00\n", "2024-01-26 10:00:00\n", "2024-01-26 10:30:00\n", "2024-01-26 10:45:00\n", "2024-01-26 11:00:00\n", "2024-01-26 11:15:00\n", "2024-01-26 13:30:00\n", "2024-01-26 13:45:00\n", "2024-01-26 14:00:00\n", "2024-01-26 14:15:00\n", "2024-01-26 14:30:00\n", "2024-01-26 14:45:00\n", "2024-01-26 21:00:00\n", "2024-01-26 21:15:00\n", "2024-01-26 21:30:00\n", "2024-01-26 21:45:00\n", "2024-01-26 22:00:00\n", "2024-01-26 22:15:00\n", "2024-01-26 22:30:00\n", "2024-01-26 22:45:00\n", "2024-01-29 09:00:00\n", "2024-01-29 09:15:00\n", "2024-01-29 09:30:00\n", "2024-01-29 09:45:00\n", "2024-01-29 10:00:00\n", "2024-01-29 10:30:00\n", "2024-01-29 10:45:00\n", "2024-01-29 11:00:00\n", "2024-01-29 11:15:00\n", "2024-01-29 13:30:00\n", "2024-01-29 13:45:00\n", "2024-01-29 14:00:00\n", "2024-01-29 14:15:00\n", "2024-01-29 14:30:00\n", "2024-01-29 14:45:00\n", "2024-01-29 21:00:00\n", "2024-01-29 21:15:00\n", "2024-01-29 21:30:00\n", "2024-01-29 21:45:00\n", "2024-01-29 22:00:00\n", "2024-01-29 22:15:00\n", "2024-01-29 22:30:00\n", "2024-01-29 22:45:00\n", "2024-01-30 09:00:00\n", "2024-01-30 09:15:00\n", "2024-01-30 09:30:00\n", "2024-01-30 09:45:00\n", "2024-01-30 10:00:00\n", "2024-01-30 10:30:00\n", "2024-01-30 10:45:00\n", "2024-01-30 11:00:00\n", "2024-01-30 11:15:00\n", "2024-01-30 13:30:00\n", "2024-01-30 13:45:00\n", "2024-01-30 14:00:00\n", "2024-01-30 14:15:00\n", "2024-01-30 14:30:00\n", "2024-01-30 14:45:00\n", "2024-01-30 21:00:00\n", "2024-01-30 21:15:00\n", "2024-01-30 21:30:00\n", "2024-01-30 21:45:00\n", "2024-01-30 22:00:00\n", "2024-01-30 22:15:00\n", "2024-01-30 22:30:00\n", "2024-01-30 22:45:00\n", "2024-01-31 09:00:00\n", "2024-01-31 09:15:00\n", "2024-01-31 09:30:00\n", "2024-01-31 09:45:00\n", "2024-01-31 10:00:00\n", "2024-01-31 10:30:00\n", "2024-01-31 10:45:00\n", "2024-01-31 11:00:00\n", "2024-01-31 11:15:00\n", "2024-01-31 13:30:00\n", "2024-01-31 13:45:00\n", "2024-01-31 14:00:00\n", "2024-01-31 14:15:00\n", "2024-01-31 14:30:00\n", "2024-01-31 14:45:00\n", "2024-01-31 21:00:00\n", "2024-01-31 21:15:00\n", "2024-01-31 21:30:00\n", "2024-01-31 21:45:00\n", "2024-01-31 22:00:00\n", "2024-01-31 22:15:00\n", "2024-01-31 22:30:00\n", "2024-01-31 22:45:00\n", "2024-02-01 09:00:00\n", "2024-02-01 09:15:00\n", "2024-02-01 09:30:00\n", "2024-02-01 09:45:00\n", "2024-02-01 10:00:00\n", "2024-02-01 10:30:00\n", "2024-02-01 10:45:00\n", "2024-02-01 11:00:00\n", "2024-02-01 11:15:00\n", "2024-02-01 13:30:00\n", "2024-02-01 13:45:00\n", "2024-02-01 14:00:00\n", "2024-02-01 14:15:00\n", "2024-02-01 14:30:00\n", "2024-02-01 14:45:00\n", "2024-02-01 21:00:00\n", "2024-02-01 21:15:00\n", "2024-02-01 21:30:00\n", "2024-02-01 21:45:00\n", "2024-02-01 22:00:00\n", "2024-02-01 22:15:00\n", "2024-02-01 22:30:00\n", "2024-02-01 22:45:00\n", "2024-02-02 09:00:00\n", "2024-02-02 09:15:00\n", "2024-02-02 09:30:00\n", "2024-02-02 09:45:00\n", "2024-02-02 10:00:00\n", "2024-02-02 10:30:00\n", "2024-02-02 10:45:00\n", "2024-02-02 11:00:00\n", "2024-02-02 11:15:00\n", "2024-02-02 13:30:00\n", "2024-02-02 13:45:00\n", "2024-02-02 14:00:00\n", "2024-02-02 14:15:00\n", "2024-02-02 14:30:00\n", "2024-02-02 14:45:00\n", "2024-02-02 21:00:00\n", "2024-02-02 21:15:00\n", "2024-02-02 21:30:00\n", "2024-02-02 21:45:00\n", "2024-02-02 22:00:00\n", "2024-02-02 22:15:00\n", "2024-02-02 22:30:00\n", "2024-02-02 22:45:00\n", "2024-02-05 09:00:00\n", "2024-02-05 09:15:00\n", "2024-02-05 09:30:00\n", "2024-02-05 09:45:00\n", "2024-02-05 10:00:00\n", "2024-02-05 10:30:00\n", "2024-02-05 10:45:00\n", "2024-02-05 11:00:00\n", "2024-02-05 11:15:00\n", "2024-02-05 13:30:00\n", "2024-02-05 13:45:00\n", "2024-02-05 14:00:00\n", "2024-02-05 14:15:00\n", "2024-02-05 14:30:00\n", "2024-02-05 14:45:00\n", "2024-02-05 21:00:00\n", "2024-02-05 21:15:00\n", "2024-02-05 21:30:00\n", "2024-02-05 21:45:00\n", "2024-02-05 22:00:00\n", "2024-02-05 22:15:00\n", "2024-02-05 22:30:00\n", "2024-02-05 22:45:00\n", "2024-02-06 09:00:00\n", "2024-02-06 09:15:00\n", "2024-02-06 09:30:00\n", "2024-02-06 09:45:00\n", "2024-02-06 10:00:00\n", "2024-02-06 10:30:00\n", "2024-02-06 10:45:00\n", "2024-02-06 11:00:00\n", "2024-02-06 11:15:00\n", "2024-02-06 13:30:00\n", "2024-02-06 13:45:00\n", "2024-02-06 14:00:00\n", "2024-02-06 14:15:00\n", "2024-02-06 14:30:00\n", "2024-02-06 14:45:00\n", "2024-02-06 21:00:00\n", "2024-02-06 21:15:00\n", "2024-02-06 21:30:00\n", "2024-02-06 21:45:00\n", "2024-02-06 22:00:00\n", "2024-02-06 22:15:00\n", "2024-02-06 22:30:00\n", "2024-02-06 22:45:00\n", "2024-02-07 09:00:00\n", "2024-02-07 09:15:00\n", "2024-02-07 09:30:00\n", "2024-02-07 09:45:00\n", "2024-02-07 10:00:00\n", "2024-02-07 10:30:00\n", "2024-02-07 10:45:00\n", "2024-02-07 11:00:00\n", "2024-02-07 11:15:00\n", "2024-02-07 13:30:00\n", "2024-02-07 13:45:00\n", "2024-02-07 14:00:00\n", "2024-02-07 14:15:00\n", "2024-02-07 14:30:00\n", "2024-02-07 14:45:00\n", "2024-02-07 21:00:00\n", "2024-02-07 21:15:00\n", "2024-02-07 21:30:00\n", "2024-02-07 21:45:00\n", "2024-02-07 22:00:00\n", "2024-02-07 22:15:00\n", "2024-02-07 22:30:00\n", "2024-02-07 22:45:00\n", "2024-02-08 09:00:00\n", "2024-02-08 09:15:00\n", "2024-02-08 09:30:00\n", "2024-02-08 09:45:00\n", "2024-02-08 10:00:00\n", "2024-02-08 10:30:00\n", "2024-02-08 10:45:00\n", "2024-02-08 11:00:00\n", "2024-02-08 11:15:00\n", "2024-02-08 13:30:00\n", "2024-02-08 13:45:00\n", "2024-02-08 14:00:00\n", "2024-02-08 14:15:00\n", "2024-02-08 14:30:00\n", "2024-02-08 14:45:00\n", "2024-02-19 09:00:00\n", "2024-02-19 09:15:00\n", "2024-02-19 09:30:00\n", "2024-02-19 09:45:00\n", "2024-02-19 10:00:00\n", "2024-02-19 10:30:00\n", "2024-02-19 10:45:00\n", "2024-02-19 11:00:00\n", "2024-02-19 11:15:00\n", "2024-02-19 13:30:00\n", "2024-02-19 13:45:00\n", "2024-02-19 14:00:00\n", "2024-02-19 14:15:00\n", "2024-02-19 14:30:00\n", "2024-02-19 14:45:00\n", "2024-02-19 21:00:00\n", "2024-02-19 21:15:00\n", "2024-02-19 21:30:00\n", "2024-02-19 21:45:00\n", "2024-02-19 22:00:00\n", "2024-02-19 22:15:00\n", "2024-02-19 22:30:00\n", "2024-02-19 22:45:00\n", "2024-02-20 09:00:00\n", "2024-02-20 09:15:00\n", "2024-02-20 09:30:00\n", "2024-02-20 09:45:00\n", "2024-02-20 10:00:00\n", "2024-02-20 10:30:00\n", "2024-02-20 10:45:00\n", "2024-02-20 11:00:00\n", "2024-02-20 11:15:00\n", "2024-02-20 13:30:00\n", "2024-02-20 13:45:00\n", "2024-02-20 14:00:00\n", "2024-02-20 14:15:00\n", "2024-02-20 14:30:00\n", "2024-02-20 14:45:00\n", "2024-02-20 21:00:00\n", "2024-02-20 21:15:00\n", "2024-02-20 21:30:00\n", "2024-02-20 21:45:00\n", "2024-02-20 22:00:00\n", "2024-02-20 22:15:00\n", "2024-02-20 22:30:00\n", "2024-02-20 22:45:00\n", "2024-02-21 09:00:00\n", "2024-02-21 09:15:00\n", "2024-02-21 09:30:00\n", "2024-02-21 09:45:00\n", "2024-02-21 10:00:00\n", "2024-02-21 10:30:00\n", "2024-02-21 10:45:00\n", "2024-02-21 11:00:00\n", "2024-02-21 11:15:00\n", "2024-02-21 13:30:00\n", "2024-02-21 13:45:00\n", "2024-02-21 14:00:00\n", "2024-02-21 14:15:00\n", "2024-02-21 14:30:00\n", "2024-02-21 14:45:00\n", "2024-02-21 21:00:00\n", "2024-02-21 21:15:00\n", "2024-02-21 21:30:00\n", "2024-02-21 21:45:00\n", "2024-02-21 22:00:00\n", "2024-02-21 22:15:00\n", "2024-02-21 22:30:00\n", "2024-02-21 22:45:00\n", "2024-02-22 09:00:00\n", "2024-02-22 09:15:00\n", "2024-02-22 09:30:00\n", "2024-02-22 09:45:00\n", "2024-02-22 10:00:00\n", "2024-02-22 10:30:00\n", "2024-02-22 10:45:00\n", "2024-02-22 11:00:00\n", "2024-02-22 11:15:00\n", "2024-02-22 13:30:00\n", "2024-02-22 13:45:00\n", "2024-02-22 14:00:00\n", "2024-02-22 14:15:00\n", "2024-02-22 14:30:00\n", "2024-02-22 14:45:00\n", "2024-02-22 21:00:00\n", "2024-02-22 21:15:00\n", "2024-02-22 21:30:00\n", "2024-02-22 21:45:00\n", "2024-02-22 22:00:00\n", "2024-02-22 22:15:00\n", "2024-02-22 22:30:00\n", "2024-02-22 22:45:00\n", "2024-02-23 09:00:00\n", "2024-02-23 09:15:00\n", "2024-02-23 09:30:00\n", "2024-02-23 09:45:00\n", "2024-02-23 10:00:00\n", "2024-02-23 10:30:00\n", "2024-02-23 10:45:00\n", "2024-02-23 11:00:00\n", "2024-02-23 11:15:00\n", "2024-02-23 13:30:00\n", "2024-02-23 13:45:00\n", "2024-02-23 14:00:00\n", "2024-02-23 14:15:00\n", "2024-02-23 14:30:00\n", "2024-02-23 14:45:00\n", "2024-02-23 21:00:00\n", "2024-02-23 21:15:00\n", "2024-02-23 21:30:00\n", "2024-02-23 21:45:00\n", "2024-02-23 22:00:00\n", "2024-02-23 22:15:00\n", "2024-02-23 22:30:00\n", "2024-02-23 22:45:00\n", "2024-02-26 09:00:00\n", "2024-02-26 09:15:00\n", "2024-02-26 09:30:00\n", "2024-02-26 09:45:00\n", "2024-02-26 10:00:00\n", "2024-02-26 10:30:00\n", "2024-02-26 10:45:00\n", "2024-02-26 11:00:00\n", "2024-02-26 11:15:00\n", "2024-02-26 13:30:00\n", "2024-02-26 13:45:00\n", "2024-02-26 14:00:00\n", "2024-02-26 14:15:00\n", "2024-02-26 14:30:00\n", "2024-02-26 14:45:00\n", "2024-02-26 21:00:00\n", "2024-02-26 21:15:00\n", "2024-02-26 21:30:00\n", "2024-02-26 21:45:00\n", "2024-02-26 22:00:00\n", "2024-02-26 22:15:00\n", "2024-02-26 22:30:00\n", "2024-02-26 22:45:00\n", "2024-02-27 09:00:00\n", "2024-02-27 09:15:00\n", "2024-02-27 09:30:00\n", "2024-02-27 09:45:00\n", "2024-02-27 10:00:00\n", "2024-02-27 10:30:00\n", "2024-02-27 10:45:00\n", "2024-02-27 11:00:00\n", "2024-02-27 11:15:00\n", "2024-02-27 13:30:00\n", "2024-02-27 13:45:00\n", "2024-02-27 14:00:00\n", "2024-02-27 14:15:00\n", "2024-02-27 14:30:00\n", "2024-02-27 14:45:00\n", "2024-02-27 21:00:00\n", "2024-02-27 21:15:00\n", "2024-02-27 21:30:00\n", "2024-02-27 21:45:00\n", "2024-02-27 22:00:00\n", "2024-02-27 22:15:00\n", "2024-02-27 22:30:00\n", "2024-02-27 22:45:00\n", "2024-02-28 09:00:00\n", "2024-02-28 09:15:00\n", "2024-02-28 09:30:00\n", "2024-02-28 09:45:00\n", "2024-02-28 10:00:00\n", "2024-02-28 10:30:00\n", "2024-02-28 10:45:00\n", "2024-02-28 11:00:00\n", "2024-02-28 11:15:00\n", "2024-02-28 13:30:00\n", "2024-02-28 13:45:00\n", "2024-02-28 14:00:00\n", "2024-02-28 14:15:00\n", "2024-02-28 14:30:00\n", "2024-02-28 14:45:00\n", "2024-02-28 21:00:00\n", "2024-02-28 21:15:00\n", "2024-02-28 21:30:00\n", "2024-02-28 21:45:00\n", "2024-02-28 22:00:00\n", "2024-02-28 22:15:00\n", "2024-02-28 22:30:00\n", "2024-02-28 22:45:00\n", "2024-02-29 09:00:00\n", "2024-02-29 09:15:00\n", "2024-02-29 09:30:00\n", "2024-02-29 09:45:00\n", "2024-02-29 10:00:00\n", "2024-02-29 10:30:00\n", "2024-02-29 10:45:00\n", "2024-02-29 11:00:00\n", "2024-02-29 11:15:00\n", "2024-02-29 13:30:00\n", "2024-02-29 13:45:00\n", "2024-02-29 14:00:00\n", "2024-02-29 14:15:00\n", "2024-02-29 14:30:00\n", "2024-02-29 14:45:00\n", "2024-02-29 21:00:00\n", "2024-02-29 21:15:00\n", "2024-02-29 21:30:00\n", "2024-02-29 21:45:00\n", "2024-02-29 22:00:00\n", "2024-02-29 22:15:00\n", "2024-02-29 22:30:00\n", "2024-02-29 22:45:00\n", "2024-03-01 09:00:00\n", "2024-03-01 09:15:00\n", "2024-03-01 09:30:00\n", "2024-03-01 09:45:00\n", "2024-03-01 10:00:00\n", "2024-03-01 10:30:00\n", "2024-03-01 10:45:00\n", "2024-03-01 11:00:00\n", "2024-03-01 11:15:00\n", "2024-03-01 13:30:00\n", "2024-03-01 13:45:00\n", "2024-03-01 14:00:00\n", "2024-03-01 14:15:00\n", "2024-03-01 14:30:00\n", "2024-03-01 14:45:00\n", "2024-03-01 21:00:00\n", "2024-03-01 21:15:00\n", "2024-03-01 21:30:00\n", "2024-03-01 21:45:00\n", "2024-03-01 22:00:00\n", "2024-03-01 22:15:00\n", "2024-03-01 22:30:00\n", "2024-03-01 22:45:00\n", "2024-03-04 09:00:00\n", "2024-03-04 09:15:00\n", "2024-03-04 09:30:00\n", "2024-03-04 09:45:00\n", "2024-03-04 10:00:00\n", "2024-03-04 10:30:00\n", "2024-03-04 10:45:00\n", "2024-03-04 11:00:00\n", "2024-03-04 11:15:00\n", "2024-03-04 13:30:00\n", "2024-03-04 13:45:00\n", "2024-03-04 14:00:00\n", "2024-03-04 14:15:00\n", "2024-03-04 14:30:00\n", "2024-03-04 14:45:00\n", "2024-03-04 21:00:00\n", "2024-03-04 21:15:00\n", "2024-03-04 21:30:00\n", "2024-03-04 21:45:00\n", "2024-03-04 22:00:00\n", "2024-03-04 22:15:00\n", "2024-03-04 22:30:00\n", "2024-03-04 22:45:00\n", "2024-03-05 09:00:00\n", "2024-03-05 09:15:00\n", "2024-03-05 09:30:00\n", "2024-03-05 09:45:00\n", "2024-03-05 10:00:00\n", "2024-03-05 10:30:00\n", "2024-03-05 10:45:00\n", "2024-03-05 11:00:00\n", "2024-03-05 11:15:00\n", "2024-03-05 13:30:00\n", "2024-03-05 13:45:00\n", "2024-03-05 14:00:00\n", "2024-03-05 14:15:00\n", "2024-03-05 14:30:00\n", "2024-03-05 14:45:00\n", "2024-03-05 21:00:00\n", "2024-03-05 21:15:00\n", "2024-03-05 21:30:00\n", "2024-03-05 21:45:00\n", "2024-03-05 22:00:00\n", "2024-03-05 22:15:00\n", "2024-03-05 22:30:00\n", "2024-03-05 22:45:00\n", "2024-03-06 09:00:00\n", "2024-03-06 09:15:00\n", "2024-03-06 09:30:00\n", "2024-03-06 09:45:00\n", "2024-03-06 10:00:00\n", "2024-03-06 10:30:00\n", "2024-03-06 10:45:00\n", "2024-03-06 11:00:00\n", "2024-03-06 11:15:00\n", "2024-03-06 13:30:00\n", "2024-03-06 13:45:00\n", "2024-03-06 14:00:00\n", "2024-03-06 14:15:00\n", "2024-03-06 14:30:00\n", "2024-03-06 14:45:00\n", "2024-03-06 21:00:00\n", "2024-03-06 21:15:00\n", "2024-03-06 21:30:00\n", "2024-03-06 21:45:00\n", "2024-03-06 22:00:00\n", "2024-03-06 22:15:00\n", "2024-03-06 22:30:00\n", "2024-03-06 22:45:00\n", "2024-03-07 09:00:00\n", "2024-03-07 09:15:00\n", "2024-03-07 09:30:00\n", "2024-03-07 09:45:00\n", "2024-03-07 10:00:00\n", "2024-03-07 10:30:00\n", "2024-03-07 10:45:00\n", "2024-03-07 11:00:00\n", "2024-03-07 11:15:00\n", "2024-03-07 13:30:00\n", "2024-03-07 13:45:00\n", "2024-03-07 14:00:00\n", "2024-03-07 14:15:00\n", "2024-03-07 14:30:00\n", "2024-03-07 14:45:00\n", "2024-03-07 21:00:00\n", "2024-03-07 21:15:00\n", "2024-03-07 21:30:00\n", "2024-03-07 21:45:00\n", "2024-03-07 22:00:00\n", "2024-03-07 22:15:00\n", "2024-03-07 22:30:00\n", "2024-03-07 22:45:00\n", "2024-03-08 09:00:00\n", "2024-03-08 09:15:00\n", "2024-03-08 09:30:00\n", "2024-03-08 09:45:00\n", "2024-03-08 10:00:00\n", "2024-03-08 10:30:00\n", "2024-03-08 10:45:00\n", "2024-03-08 11:00:00\n", "2024-03-08 11:15:00\n", "2024-03-08 13:30:00\n", "2024-03-08 13:45:00\n", "2024-03-08 14:00:00\n", "2024-03-08 14:15:00\n", "2024-03-08 14:30:00\n", "2024-03-08 14:45:00\n", "2024-03-08 21:00:00\n", "2024-03-08 21:15:00\n", "2024-03-08 21:30:00\n", "2024-03-08 21:45:00\n", "2024-03-08 22:00:00\n", "2024-03-08 22:15:00\n", "2024-03-08 22:30:00\n", "2024-03-08 22:45:00\n", "2024-03-11 09:00:00\n", "2024-03-11 09:15:00\n", "2024-03-11 09:30:00\n", "2024-03-11 09:45:00\n", "2024-03-11 10:00:00\n", "2024-03-11 10:30:00\n", "2024-03-11 10:45:00\n", "2024-03-11 11:00:00\n", "2024-03-11 11:15:00\n", "2024-03-11 13:30:00\n", "2024-03-11 13:45:00\n", "2024-03-11 14:00:00\n", "2024-03-11 14:15:00\n", "2024-03-11 14:30:00\n", "2024-03-11 14:45:00\n", "2024-03-11 21:00:00\n", "2024-03-11 21:15:00\n", "2024-03-11 21:30:00\n", "2024-03-11 21:45:00\n", "2024-03-11 22:00:00\n", "2024-03-11 22:15:00\n", "2024-03-11 22:30:00\n", "2024-03-11 22:45:00\n", "2024-03-12 09:00:00\n", "2024-03-12 09:15:00\n", "2024-03-12 09:30:00\n", "2024-03-12 09:45:00\n", "2024-03-12 10:00:00\n", "2024-03-12 10:30:00\n", "2024-03-12 10:45:00\n", "2024-03-12 11:00:00\n", "2024-03-12 11:15:00\n", "2024-03-12 13:30:00\n", "2024-03-12 13:45:00\n", "2024-03-12 14:00:00\n", "2024-03-12 14:15:00\n", "2024-03-12 14:30:00\n", "2024-03-12 14:45:00\n", "2024-03-12 21:00:00\n", "2024-03-12 21:15:00\n", "2024-03-12 21:30:00\n", "2024-03-12 21:45:00\n", "2024-03-12 22:00:00\n", "2024-03-12 22:15:00\n", "2024-03-12 22:30:00\n", "2024-03-12 22:45:00\n", "2024-03-13 09:00:00\n", "2024-03-13 09:15:00\n", "2024-03-13 09:30:00\n", "2024-03-13 09:45:00\n", "2024-03-13 10:00:00\n", "2024-03-13 10:30:00\n", "2024-03-13 10:45:00\n", "2024-03-13 11:00:00\n", "2024-03-13 11:15:00\n", "2024-03-13 13:30:00\n", "2024-03-13 13:45:00\n", "2024-03-13 14:00:00\n", "2024-03-13 14:15:00\n", "2024-03-13 14:30:00\n", "2024-03-13 14:45:00\n", "2024-03-13 21:00:00\n", "2024-03-13 21:15:00\n", "2024-03-13 21:30:00\n", "2024-03-13 21:45:00\n", "2024-03-13 22:00:00\n", "2024-03-13 22:15:00\n", "2024-03-13 22:30:00\n", "2024-03-13 22:45:00\n", "2024-03-14 09:00:00\n", "2024-03-14 09:15:00\n", "2024-03-14 09:30:00\n", "2024-03-14 09:45:00\n", "2024-03-14 10:00:00\n", "2024-03-14 10:30:00\n", "2024-03-14 10:45:00\n", "2024-03-14 11:00:00\n", "2024-03-14 11:15:00\n", "2024-03-14 13:30:00\n", "2024-03-14 13:45:00\n", "2024-03-14 14:00:00\n", "2024-03-14 14:15:00\n", "2024-03-14 14:30:00\n", "2024-03-14 14:45:00\n", "2024-03-14 21:00:00\n", "2024-03-14 21:15:00\n", "2024-03-14 21:30:00\n", "2024-03-14 21:45:00\n", "2024-03-14 22:00:00\n", "2024-03-14 22:15:00\n", "2024-03-14 22:30:00\n", "2024-03-14 22:45:00\n", "2024-03-15 09:00:00\n", "2024-03-15 09:15:00\n", "2024-03-15 09:30:00\n", "2024-03-15 09:45:00\n", "2024-03-15 10:00:00\n", "2024-03-15 10:30:00\n", "2024-03-15 10:45:00\n", "2024-03-15 11:00:00\n", "2024-03-15 11:15:00\n", "2024-03-15 13:30:00\n", "2024-03-15 13:45:00\n", "2024-03-15 14:00:00\n", "2024-03-15 14:15:00\n", "2024-03-15 14:30:00\n", "2024-03-15 14:45:00\n", "2024-03-15 21:00:00\n", "2024-03-15 21:15:00\n", "2024-03-15 21:30:00\n", "2024-03-15 21:45:00\n", "2024-03-15 22:00:00\n", "2024-03-15 22:15:00\n", "2024-03-15 22:30:00\n", "2024-03-15 22:45:00\n", "2024-03-18 09:00:00\n", "2024-03-18 09:15:00\n", "2024-03-18 09:30:00\n", "2024-03-18 09:45:00\n", "2024-03-18 10:00:00\n", "2024-03-18 10:30:00\n", "2024-03-18 10:45:00\n", "2024-03-18 11:00:00\n", "2024-03-18 11:15:00\n", "2024-03-18 13:30:00\n", "2024-03-18 13:45:00\n", "2024-03-18 14:00:00\n", "2024-03-18 14:15:00\n", "2024-03-18 14:30:00\n", "2024-03-18 14:45:00\n", "2024-03-18 21:00:00\n", "2024-03-18 21:15:00\n", "2024-03-18 21:30:00\n", "2024-03-18 21:45:00\n", "2024-03-18 22:00:00\n", "2024-03-18 22:15:00\n", "2024-03-18 22:30:00\n", "2024-03-18 22:45:00\n", "2024-03-19 09:00:00\n", "2024-03-19 09:15:00\n", "2024-03-19 09:30:00\n", "2024-03-19 09:45:00\n", "2024-03-19 10:00:00\n", "2024-03-19 10:30:00\n", "2024-03-19 10:45:00\n", "2024-03-19 11:00:00\n", "2024-03-19 11:15:00\n", "2024-03-19 13:30:00\n", "2024-03-19 13:45:00\n", "2024-03-19 14:00:00\n", "2024-03-19 14:15:00\n", "2024-03-19 14:30:00\n", "2024-03-19 14:45:00\n", "2024-03-19 21:00:00\n", "2024-03-19 21:15:00\n", "2024-03-19 21:30:00\n", "2024-03-19 21:45:00\n", "2024-03-19 22:00:00\n", "2024-03-19 22:15:00\n", "2024-03-19 22:30:00\n", "2024-03-19 22:45:00\n", "2024-03-20 09:00:00\n", "2024-03-20 09:15:00\n", "2024-03-20 09:30:00\n", "2024-03-20 09:45:00\n", "2024-03-20 10:00:00\n", "2024-03-20 10:30:00\n", "2024-03-20 10:45:00\n", "2024-03-20 11:00:00\n", "2024-03-20 11:15:00\n", "2024-03-20 13:30:00\n", "2024-03-20 13:45:00\n", "2024-03-20 14:00:00\n", "2024-03-20 14:15:00\n", "2024-03-20 14:30:00\n", "2024-03-20 14:45:00\n", "2024-03-20 21:00:00\n", "2024-03-20 21:15:00\n", "2024-03-20 21:30:00\n", "2024-03-20 21:45:00\n", "2024-03-20 22:00:00\n", "2024-03-20 22:15:00\n", "2024-03-20 22:30:00\n", "2024-03-20 22:45:00\n", "2024-03-21 09:00:00\n", "2024-03-21 09:15:00\n", "2024-03-21 09:30:00\n", "2024-03-21 09:45:00\n", "2024-03-21 10:00:00\n", "2024-03-21 10:30:00\n", "2024-03-21 10:45:00\n", "2024-03-21 11:00:00\n", "2024-03-21 11:15:00\n", "2024-03-21 13:30:00\n", "2024-03-21 13:45:00\n", "2024-03-21 14:00:00\n", "2024-03-21 14:15:00\n", "2024-03-21 14:30:00\n", "2024-03-21 14:45:00\n", "2024-03-21 21:00:00\n", "2024-03-21 21:15:00\n", "2024-03-21 21:30:00\n", "2024-03-21 21:45:00\n", "2024-03-21 22:00:00\n", "2024-03-21 22:15:00\n", "2024-03-21 22:30:00\n", "2024-03-21 22:45:00\n", "2024-03-22 09:00:00\n", "2024-03-22 09:15:00\n", "2024-03-22 09:30:00\n", "2024-03-22 09:45:00\n", "2024-03-22 10:00:00\n", "2024-03-22 10:30:00\n", "2024-03-22 10:45:00\n", "2024-03-22 11:00:00\n", "2024-03-22 11:15:00\n", "2024-03-22 13:30:00\n", "2024-03-22 13:45:00\n", "2024-03-22 14:00:00\n", "2024-03-22 14:15:00\n", "2024-03-22 14:30:00\n", "2024-03-22 14:45:00\n", "2024-03-22 21:00:00\n", "2024-03-22 21:15:00\n", "2024-03-22 21:30:00\n", "2024-03-22 21:45:00\n", "2024-03-22 22:00:00\n", "2024-03-22 22:15:00\n", "2024-03-22 22:30:00\n", "2024-03-22 22:45:00\n", "2024-03-25 09:00:00\n", "2024-03-25 09:15:00\n", "2024-03-25 09:30:00\n", "2024-03-25 09:45:00\n", "2024-03-25 10:00:00\n", "2024-03-25 10:30:00\n", "2024-03-25 10:45:00\n", "2024-03-25 11:00:00\n", "2024-03-25 11:15:00\n", "2024-03-25 13:30:00\n", "2024-03-25 13:45:00\n", "2024-03-25 14:00:00\n", "2024-03-25 14:15:00\n", "2024-03-25 14:30:00\n", "2024-03-25 14:45:00\n", "2024-03-25 21:00:00\n", "2024-03-25 21:15:00\n", "2024-03-25 21:30:00\n", "2024-03-25 21:45:00\n", "2024-03-25 22:00:00\n", "2024-03-25 22:15:00\n", "2024-03-25 22:30:00\n", "2024-03-25 22:45:00\n", "2024-03-26 09:00:00\n", "2024-03-26 09:15:00\n", "2024-03-26 09:30:00\n", "2024-03-26 09:45:00\n", "2024-03-26 10:00:00\n", "2024-03-26 10:30:00\n", "2024-03-26 10:45:00\n", "2024-03-26 11:00:00\n", "2024-03-26 11:15:00\n", "2024-03-26 13:30:00\n", "2024-03-26 13:45:00\n", "2024-03-26 14:00:00\n", "2024-03-26 14:15:00\n", "2024-03-26 14:30:00\n", "2024-03-26 14:45:00\n", "2024-03-26 21:00:00\n", "2024-03-26 21:15:00\n", "2024-03-26 21:30:00\n", "2024-03-26 21:45:00\n", "2024-03-26 22:00:00\n", "2024-03-26 22:15:00\n", "2024-03-26 22:30:00\n", "2024-03-26 22:45:00\n", "2024-03-27 09:00:00\n", "2024-03-27 09:15:00\n", "2024-03-27 09:30:00\n", "2024-03-27 09:45:00\n", "2024-03-27 10:00:00\n", "2024-03-27 10:30:00\n", "2024-03-27 10:45:00\n", "2024-03-27 11:00:00\n", "2024-03-27 11:15:00\n", "2024-03-27 13:30:00\n", "2024-03-27 13:45:00\n", "2024-03-27 14:00:00\n", "2024-03-27 14:15:00\n", "2024-03-27 14:30:00\n", "2024-03-27 14:45:00\n", "2024-03-27 21:00:00\n", "2024-03-27 21:15:00\n", "2024-03-27 21:30:00\n", "2024-03-27 21:45:00\n", "2024-03-27 22:00:00\n", "2024-03-27 22:15:00\n", "2024-03-27 22:30:00\n", "2024-03-27 22:45:00\n", "2024-03-28 09:00:00\n", "2024-03-28 09:15:00\n", "2024-03-28 09:30:00\n", "2024-03-28 09:45:00\n", "2024-03-28 10:00:00\n", "2024-03-28 10:30:00\n", "2024-03-28 10:45:00\n", "2024-03-28 11:00:00\n", "2024-03-28 11:15:00\n", "2024-03-28 13:30:00\n", "2024-03-28 13:45:00\n", "2024-03-28 14:00:00\n", "2024-03-28 14:15:00\n", "2024-03-28 14:30:00\n", "2024-03-28 14:45:00\n", "2024-03-28 21:00:00\n", "2024-03-28 21:15:00\n", "2024-03-28 21:30:00\n", "2024-03-28 21:45:00\n", "2024-03-28 22:00:00\n", "2024-03-28 22:15:00\n", "2024-03-28 22:30:00\n", "2024-03-28 22:45:00\n", "2024-03-29 09:00:00\n", "2024-03-29 09:15:00\n", "2024-03-29 09:30:00\n", "2024-03-29 09:45:00\n", "2024-03-29 10:00:00\n", "2024-03-29 10:30:00\n", "2024-03-29 10:45:00\n", "2024-03-29 11:00:00\n", "2024-03-29 11:15:00\n", "2024-03-29 13:30:00\n", "2024-03-29 13:45:00\n", "2024-03-29 14:00:00\n", "2024-03-29 14:15:00\n", "2024-03-29 14:30:00\n", "2024-03-29 14:45:00\n", "2024-03-29 21:00:00\n", "2024-03-29 21:15:00\n", "2024-03-29 21:30:00\n", "2024-03-29 21:45:00\n", "2024-03-29 22:00:00\n", "2024-03-29 22:15:00\n", "2024-03-29 22:30:00\n", "2024-03-29 22:45:00\n", "2024-04-01 09:00:00\n", "2024-04-01 09:15:00\n", "2024-04-01 09:30:00\n", "2024-04-01 09:45:00\n", "2024-04-01 10:00:00\n", "2024-04-01 10:30:00\n", "2024-04-01 10:45:00\n", "2024-04-01 11:00:00\n", "2024-04-01 11:15:00\n", "2024-04-01 13:30:00\n", "2024-04-01 13:45:00\n", "2024-04-01 14:00:00\n", "2024-04-01 14:15:00\n", "2024-04-01 14:30:00\n", "2024-04-01 14:45:00\n", "2024-04-01 21:00:00\n", "2024-04-01 21:15:00\n", "2024-04-01 21:30:00\n", "2024-04-01 21:45:00\n", "2024-04-01 22:00:00\n", "2024-04-01 22:15:00\n", "2024-04-01 22:30:00\n", "2024-04-01 22:45:00\n", "2024-04-02 09:00:00\n", "2024-04-02 09:15:00\n", "2024-04-02 09:30:00\n", "2024-04-02 09:45:00\n", "2024-04-02 10:00:00\n", "2024-04-02 10:30:00\n", "2024-04-02 10:45:00\n", "2024-04-02 11:00:00\n", "2024-04-02 11:15:00\n", "2024-04-02 13:30:00\n", "2024-04-02 13:45:00\n", "2024-04-02 14:00:00\n", "2024-04-02 14:15:00\n", "2024-04-02 14:30:00\n", "2024-04-02 14:45:00\n", "2024-04-02 21:00:00\n", "2024-04-02 21:15:00\n", "2024-04-02 21:30:00\n", "2024-04-02 21:45:00\n", "2024-04-02 22:00:00\n", "2024-04-02 22:15:00\n", "2024-04-02 22:30:00\n", "2024-04-02 22:45:00\n", "2024-04-03 09:00:00\n", "2024-04-03 09:15:00\n", "2024-04-03 09:30:00\n", "2024-04-03 09:45:00\n", "2024-04-03 10:00:00\n", "2024-04-03 10:30:00\n", "2024-04-03 10:45:00\n", "2024-04-03 11:00:00\n", "2024-04-03 11:15:00\n", "2024-04-03 13:30:00\n", "2024-04-03 13:45:00\n", "2024-04-03 14:00:00\n", "2024-04-03 14:15:00\n", "2024-04-03 14:30:00\n", "2024-04-03 14:45:00\n", "2024-04-08 09:00:00\n", "2024-04-08 09:15:00\n", "2024-04-08 09:30:00\n", "2024-04-08 09:45:00\n", "2024-04-08 10:00:00\n", "2024-04-08 10:30:00\n", "2024-04-08 10:45:00\n", "2024-04-08 11:00:00\n", "2024-04-08 11:15:00\n", "2024-04-08 13:30:00\n", "2024-04-08 13:45:00\n", "2024-04-08 14:00:00\n", "2024-04-08 14:15:00\n", "2024-04-08 14:30:00\n", "2024-04-08 14:45:00\n", "2024-04-08 21:00:00\n", "2024-04-08 21:15:00\n", "2024-04-08 21:30:00\n", "2024-04-08 21:45:00\n", "2024-04-08 22:00:00\n", "2024-04-08 22:15:00\n", "2024-04-08 22:30:00\n", "2024-04-08 22:45:00\n", "2024-04-09 09:00:00\n", "2024-04-09 09:15:00\n", "2024-04-09 09:30:00\n", "2024-04-09 09:45:00\n", "2024-04-09 10:00:00\n", "2024-04-09 10:30:00\n", "2024-04-09 10:45:00\n", "2024-04-09 11:00:00\n", "2024-04-09 11:15:00\n", "2024-04-09 13:30:00\n", "2024-04-09 13:45:00\n", "2024-04-09 14:00:00\n", "2024-04-09 14:15:00\n", "2024-04-09 14:30:00\n", "2024-04-09 14:45:00\n", "2024-04-09 21:00:00\n", "2024-04-09 21:15:00\n", "2024-04-09 21:30:00\n", "2024-04-09 21:45:00\n", "2024-04-09 22:00:00\n", "2024-04-09 22:15:00\n", "2024-04-09 22:30:00\n", "2024-04-09 22:45:00\n", "2024-04-10 09:00:00\n", "2024-04-10 09:15:00\n", "2024-04-10 09:30:00\n", "2024-04-10 09:45:00\n", "2024-04-10 10:00:00\n", "2024-04-10 10:30:00\n", "2024-04-10 10:45:00\n", "2024-04-10 11:00:00\n", "2024-04-10 11:15:00\n", "2024-04-10 13:30:00\n", "2024-04-10 13:45:00\n", "2024-04-10 14:00:00\n", "2024-04-10 14:15:00\n", "2024-04-10 14:30:00\n", "2024-04-10 14:45:00\n", "2024-04-10 21:00:00\n", "2024-04-10 21:15:00\n", "2024-04-10 21:30:00\n", "2024-04-10 21:45:00\n", "2024-04-10 22:00:00\n", "2024-04-10 22:15:00\n", "2024-04-10 22:30:00\n", "2024-04-10 22:45:00\n", "2024-04-11 09:00:00\n", "2024-04-11 09:15:00\n", "2024-04-11 09:30:00\n", "2024-04-11 09:45:00\n", "2024-04-11 10:00:00\n", "2024-04-11 10:30:00\n", "2024-04-11 10:45:00\n", "2024-04-11 11:00:00\n", "2024-04-11 11:15:00\n", "2024-04-11 13:30:00\n", "2024-04-11 13:45:00\n", "2024-04-11 14:00:00\n", "2024-04-11 14:15:00\n", "2024-04-11 14:30:00\n", "2024-04-11 14:45:00\n", "2024-04-11 21:00:00\n", "2024-04-11 21:15:00\n", "2024-04-11 21:30:00\n", "2024-04-11 21:45:00\n", "2024-04-11 22:00:00\n", "2024-04-11 22:15:00\n", "2024-04-11 22:30:00\n", "2024-04-11 22:45:00\n", "2024-04-12 09:00:00\n", "2024-04-12 09:15:00\n", "2024-04-12 09:30:00\n", "2024-04-12 09:45:00\n", "2024-04-12 10:00:00\n", "2024-04-12 10:30:00\n", "2024-04-12 10:45:00\n", "2024-04-12 11:00:00\n", "2024-04-12 11:15:00\n", "2024-04-12 13:30:00\n", "2024-04-12 13:45:00\n", "2024-04-12 14:00:00\n", "2024-04-12 14:15:00\n", "2024-04-12 14:30:00\n", "2024-04-12 14:45:00\n", "2024-04-12 21:00:00\n", "2024-04-12 21:15:00\n", "2024-04-12 21:30:00\n", "2024-04-12 21:45:00\n", "2024-04-12 22:00:00\n", "2024-04-12 22:15:00\n", "2024-04-12 22:30:00\n", "2024-04-12 22:45:00\n", "2024-04-15 09:00:00\n", "2024-04-15 09:15:00\n", "2024-04-15 09:30:00\n", "2024-04-15 09:45:00\n", "2024-04-15 10:00:00\n", "2024-04-15 10:30:00\n", "2024-04-15 10:45:00\n", "2024-04-15 11:00:00\n", "2024-04-15 11:15:00\n", "2024-04-15 13:30:00\n", "2024-04-15 13:45:00\n", "2024-04-15 14:00:00\n", "2024-04-15 14:15:00\n", "2024-04-15 14:30:00\n", "2024-04-15 14:45:00\n", "2024-04-15 21:00:00\n", "2024-04-15 21:15:00\n", "2024-04-15 21:30:00\n", "2024-04-15 21:45:00\n", "2024-04-15 22:00:00\n", "2024-04-15 22:15:00\n", "2024-04-15 22:30:00\n", "2024-04-15 22:45:00\n", "2024-04-16 09:00:00\n", "2024-04-16 09:15:00\n", "2024-04-16 09:30:00\n", "2024-04-16 09:45:00\n", "2024-04-16 10:00:00\n", "2024-04-16 10:30:00\n", "2024-04-16 10:45:00\n", "2024-04-16 11:00:00\n", "2024-04-16 11:15:00\n", "2024-04-16 13:30:00\n", "2024-04-16 13:45:00\n", "2024-04-16 14:00:00\n", "2024-04-16 14:15:00\n", "2024-04-16 14:30:00\n", "2024-04-16 14:45:00\n", "2024-04-16 21:00:00\n", "2024-04-16 21:15:00\n", "2024-04-16 21:30:00\n", "2024-04-16 21:45:00\n", "2024-04-16 22:00:00\n", "2024-04-16 22:15:00\n", "2024-04-16 22:30:00\n", "2024-04-16 22:45:00\n", "2024-04-17 09:00:00\n", "2024-04-17 09:15:00\n", "2024-04-17 09:30:00\n", "2024-04-17 09:45:00\n", "2024-04-17 10:00:00\n", "2024-04-17 10:30:00\n", "2024-04-17 10:45:00\n", "2024-04-17 11:00:00\n", "2024-04-17 11:15:00\n", "2024-04-17 13:30:00\n", "2024-04-17 13:45:00\n", "2024-04-17 14:00:00\n", "2024-04-17 14:15:00\n", "2024-04-17 14:30:00\n", "2024-04-17 14:45:00\n", "2024-04-17 21:00:00\n", "2024-04-17 21:15:00\n", "2024-04-17 21:30:00\n", "2024-04-17 21:45:00\n", "2024-04-17 22:00:00\n", "2024-04-17 22:15:00\n", "2024-04-17 22:30:00\n", "2024-04-17 22:45:00\n", "2024-04-18 09:00:00\n", "2024-04-18 09:15:00\n", "2024-04-18 09:30:00\n", "2024-04-18 09:45:00\n", "2024-04-18 10:00:00\n", "2024-04-18 10:30:00\n", "2024-04-18 10:45:00\n", "2024-04-18 11:00:00\n", "2024-04-18 11:15:00\n", "2024-04-18 13:30:00\n", "2024-04-18 13:45:00\n", "2024-04-18 14:00:00\n", "2024-04-18 14:15:00\n", "2024-04-18 14:30:00\n", "2024-04-18 14:45:00\n", "2024-04-18 21:00:00\n", "2024-04-18 21:15:00\n", "2024-04-18 21:30:00\n", "2024-04-18 21:45:00\n", "2024-04-18 22:00:00\n", "2024-04-18 22:15:00\n", "2024-04-18 22:30:00\n", "2024-04-18 22:45:00\n", "2024-04-19 09:00:00\n", "2024-04-19 09:15:00\n", "2024-04-19 09:30:00\n", "2024-04-19 09:45:00\n", "2024-04-19 10:00:00\n", "2024-04-19 10:30:00\n", "2024-04-19 10:45:00\n", "2024-04-19 11:00:00\n", "2024-04-19 11:15:00\n", "2024-04-19 13:30:00\n", "2024-04-19 13:45:00\n", "2024-04-19 14:00:00\n", "2024-04-19 14:15:00\n", "2024-04-19 14:30:00\n", "2024-04-19 14:45:00\n", "2024-04-19 21:00:00\n", "2024-04-19 21:15:00\n", "2024-04-19 21:30:00\n", "2024-04-19 21:45:00\n", "2024-04-19 22:00:00\n", "2024-04-19 22:15:00\n", "2024-04-19 22:30:00\n", "2024-04-19 22:45:00\n", "2024-04-22 09:00:00\n", "2024-04-22 09:15:00\n", "2024-04-22 09:30:00\n", "2024-04-22 09:45:00\n", "2024-04-22 10:00:00\n", "2024-04-22 10:30:00\n", "2024-04-22 10:45:00\n", "2024-04-22 11:00:00\n", "2024-04-22 11:15:00\n", "2024-04-22 13:30:00\n", "2024-04-22 13:45:00\n", "2024-04-22 14:00:00\n", "2024-04-22 14:15:00\n", "2024-04-22 14:30:00\n", "2024-04-22 14:45:00\n", "2024-04-22 21:00:00\n", "2024-04-22 21:15:00\n", "2024-04-22 21:30:00\n", "2024-04-22 21:45:00\n", "2024-04-22 22:00:00\n", "2024-04-22 22:15:00\n", "2024-04-22 22:30:00\n", "2024-04-22 22:45:00\n", "2024-04-23 09:00:00\n", "2024-04-23 09:15:00\n", "2024-04-23 09:30:00\n", "2024-04-23 09:45:00\n", "2024-04-23 10:00:00\n", "2024-04-23 10:30:00\n", "2024-04-23 10:45:00\n", "2024-04-23 11:00:00\n", "2024-04-23 11:15:00\n", "2024-04-23 13:30:00\n", "2024-04-23 13:45:00\n", "2024-04-23 14:00:00\n", "2024-04-23 14:15:00\n", "2024-04-23 14:30:00\n", "2024-04-23 14:45:00\n", "2024-04-23 21:00:00\n", "2024-04-23 21:15:00\n", "2024-04-23 21:30:00\n", "2024-04-23 21:45:00\n", "2024-04-23 22:00:00\n", "2024-04-23 22:15:00\n", "2024-04-23 22:30:00\n", "2024-04-23 22:45:00\n", "2024-04-24 09:00:00\n", "2024-04-24 09:15:00\n", "2024-04-24 09:30:00\n", "2024-04-24 09:45:00\n", "2024-04-24 10:00:00\n", "2024-04-24 10:30:00\n", "2024-04-24 10:45:00\n", "2024-04-24 11:00:00\n", "2024-04-24 11:15:00\n", "2024-04-24 13:30:00\n", "2024-04-24 13:45:00\n", "2024-04-24 14:00:00\n", "2024-04-24 14:15:00\n", "2024-04-24 14:30:00\n", "2024-04-24 14:45:00\n", "2024-04-24 21:00:00\n", "2024-04-24 21:15:00\n", "2024-04-24 21:30:00\n", "2024-04-24 21:45:00\n", "2024-04-24 22:00:00\n", "2024-04-24 22:15:00\n", "2024-04-24 22:30:00\n", "2024-04-24 22:45:00\n", "2024-04-25 09:00:00\n", "2024-04-25 09:15:00\n", "2024-04-25 09:30:00\n", "2024-04-25 09:45:00\n", "2024-04-25 10:00:00\n", "2024-04-25 10:30:00\n", "2024-04-25 10:45:00\n", "2024-04-25 11:00:00\n", "2024-04-25 11:15:00\n", "2024-04-25 13:30:00\n", "2024-04-25 13:45:00\n", "2024-04-25 14:00:00\n", "2024-04-25 14:15:00\n", "2024-04-25 14:30:00\n", "2024-04-25 14:45:00\n", "2024-04-25 21:00:00\n", "2024-04-25 21:15:00\n", "2024-04-25 21:30:00\n", "2024-04-25 21:45:00\n", "2024-04-25 22:00:00\n", "2024-04-25 22:15:00\n", "2024-04-25 22:30:00\n", "2024-04-25 22:45:00\n", "2024-04-26 09:00:00\n", "2024-04-26 09:15:00\n", "2024-04-26 09:30:00\n", "2024-04-26 09:45:00\n", "2024-04-26 10:00:00\n", "2024-04-26 10:30:00\n", "2024-04-26 10:45:00\n", "2024-04-26 11:00:00\n", "2024-04-26 11:15:00\n", "2024-04-26 13:30:00\n", "2024-04-26 13:45:00\n", "2024-04-26 14:00:00\n", "2024-04-26 14:15:00\n", "2024-04-26 14:30:00\n", "2024-04-26 14:45:00\n", "2024-04-26 21:00:00\n", "2024-04-26 21:15:00\n", "2024-04-26 21:30:00\n", "2024-04-26 21:45:00\n", "2024-04-26 22:00:00\n", "2024-04-26 22:15:00\n", "2024-04-26 22:30:00\n", "2024-04-26 22:45:00\n", "2024-04-29 09:00:00\n", "2024-04-29 09:15:00\n", "2024-04-29 09:30:00\n", "2024-04-29 09:45:00\n", "2024-04-29 10:00:00\n", "2024-04-29 10:30:00\n", "2024-04-29 10:45:00\n", "2024-04-29 11:00:00\n", "2024-04-29 11:15:00\n", "2024-04-29 13:30:00\n", "2024-04-29 13:45:00\n", "2024-04-29 14:00:00\n", "2024-04-29 14:15:00\n", "2024-04-29 14:30:00\n", "2024-04-29 14:45:00\n", "2024-04-29 21:00:00\n", "2024-04-29 21:15:00\n", "2024-04-29 21:30:00\n", "2024-04-29 21:45:00\n", "2024-04-29 22:00:00\n", "2024-04-29 22:15:00\n", "2024-04-29 22:30:00\n", "2024-04-29 22:45:00\n", "2024-04-30 09:00:00\n", "2024-04-30 09:15:00\n", "2024-04-30 09:30:00\n", "2024-04-30 09:45:00\n", "2024-04-30 10:00:00\n", "2024-04-30 10:30:00\n", "2024-04-30 10:45:00\n", "2024-04-30 11:00:00\n", "2024-04-30 11:15:00\n", "2024-04-30 13:30:00\n", "2024-04-30 13:45:00\n", "2024-04-30 14:00:00\n", "2024-04-30 14:15:00\n", "2024-04-30 14:30:00\n", "2024-04-30 14:45:00\n", "2024-05-06 09:00:00\n", "2024-05-06 09:15:00\n", "2024-05-06 09:30:00\n", "2024-05-06 09:45:00\n", "2024-05-06 10:00:00\n", "2024-05-06 10:30:00\n", "2024-05-06 10:45:00\n", "2024-05-06 11:00:00\n", "2024-05-06 11:15:00\n", "2024-05-06 13:30:00\n", "2024-05-06 13:45:00\n", "2024-05-06 14:00:00\n", "2024-05-06 14:15:00\n", "2024-05-06 14:30:00\n", "2024-05-06 14:45:00\n", "2024-05-06 21:00:00\n", "2024-05-06 21:15:00\n", "2024-05-06 21:30:00\n", "2024-05-06 21:45:00\n", "2024-05-06 22:00:00\n", "2024-05-06 22:15:00\n", "2024-05-06 22:30:00\n", "2024-05-06 22:45:00\n", "2024-05-07 09:00:00\n", "2024-05-07 09:15:00\n", "2024-05-07 09:30:00\n", "2024-05-07 09:45:00\n", "2024-05-07 10:00:00\n", "2024-05-07 10:30:00\n", "2024-05-07 10:45:00\n", "2024-05-07 11:00:00\n", "2024-05-07 11:15:00\n", "2024-05-07 13:30:00\n", "2024-05-07 13:45:00\n", "2024-05-07 14:00:00\n", "2024-05-07 14:15:00\n", "2024-05-07 14:30:00\n", "2024-05-07 14:45:00\n", "2024-05-07 21:00:00\n", "2024-05-07 21:15:00\n", "2024-05-07 21:30:00\n", "2024-05-07 21:45:00\n", "2024-05-07 22:00:00\n", "2024-05-07 22:15:00\n", "2024-05-07 22:30:00\n", "2024-05-07 22:45:00\n", "2024-05-08 09:00:00\n", "2024-05-08 09:15:00\n", "2024-05-08 09:30:00\n", "2024-05-08 09:45:00\n", "2024-05-08 10:00:00\n", "2024-05-08 10:30:00\n", "2024-05-08 10:45:00\n", "2024-05-08 11:00:00\n", "2024-05-08 11:15:00\n", "2024-05-08 13:30:00\n", "2024-05-08 13:45:00\n", "2024-05-08 14:00:00\n", "2024-05-08 14:15:00\n", "2024-05-08 14:30:00\n", "2024-05-08 14:45:00\n", "2024-05-08 21:00:00\n", "2024-05-08 21:15:00\n", "2024-05-08 21:30:00\n", "2024-05-08 21:45:00\n", "2024-05-08 22:00:00\n", "2024-05-08 22:15:00\n", "2024-05-08 22:30:00\n", "2024-05-08 22:45:00\n", "2024-05-09 09:00:00\n", "2024-05-09 09:15:00\n", "2024-05-09 09:30:00\n", "2024-05-09 09:45:00\n", "2024-05-09 10:00:00\n", "2024-05-09 10:30:00\n" ] }, { "ename": "KeyboardInterrupt", "evalue": "", "output_type": "error", "traceback": [ "\u001B[31m---------------------------------------------------------------------------\u001B[39m", "\u001B[31mKeyboardInterrupt\u001B[39m Traceback (most recent call last)", "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[38]\u001B[39m\u001B[32m, line 38\u001B[39m\n\u001B[32m 23\u001B[39m engine = BacktestEngine(\n\u001B[32m 24\u001B[39m data_manager=data_manager,\n\u001B[32m 25\u001B[39m strategy_class=TrendlineBreakoutStrategy, \u001B[38;5;66;03m# <--- 更改为您的 SMC 策略类\u001B[39;00m\n\u001B[32m (...)\u001B[39m\u001B[32m 34\u001B[39m indicators=indicators \u001B[38;5;66;03m# 如果您的 SMC 策略不使用这些指标,也可以考虑移除\u001B[39;00m\n\u001B[32m 35\u001B[39m )\n\u001B[32m 37\u001B[39m \u001B[38;5;28mprint\u001B[39m(\u001B[33m\"\u001B[39m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[33m开始运行回测...\u001B[39m\u001B[33m\"\u001B[39m)\n\u001B[32m---> \u001B[39m\u001B[32m38\u001B[39m \u001B[43mengine\u001B[49m\u001B[43m.\u001B[49m\u001B[43mrun_backtest\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 39\u001B[39m \u001B[38;5;28mprint\u001B[39m(\u001B[33m\"\u001B[39m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[33m回测运行完毕。\u001B[39m\u001B[33m\"\u001B[39m)\n\u001B[32m 41\u001B[39m \u001B[38;5;66;03m# --- 3. 获取回测结果 ---\u001B[39;00m\n", "\u001B[36mFile \u001B[39m\u001B[32m/mnt/d/PyProject/NewQuant/src/backtest_engine.py:160\u001B[39m, in \u001B[36mBacktestEngine.run_backtest\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m 157\u001B[39m \u001B[38;5;66;03m# 3. 更新策略关注的当前合约 symbol\u001B[39;00m\n\u001B[32m 158\u001B[39m \u001B[38;5;28mself\u001B[39m.strategy.symbol = current_bar.symbol\n\u001B[32m--> \u001B[39m\u001B[32m160\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mstrategy\u001B[49m\u001B[43m.\u001B[49m\u001B[43mon_open_bar\u001B[49m\u001B[43m(\u001B[49m\u001B[43mcurrent_bar\u001B[49m\u001B[43m.\u001B[49m\u001B[43mopen\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcurrent_bar\u001B[49m\u001B[43m.\u001B[49m\u001B[43msymbol\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 162\u001B[39m current_indicator_dict = {}\n\u001B[32m 163\u001B[39m close_array = np.array(\u001B[38;5;28mself\u001B[39m.close_list)\n", "\u001B[36mFile \u001B[39m\u001B[32m:39\u001B[39m, in \u001B[36mon_open_bar\u001B[39m\u001B[34m(self, open_price, symbol)\u001B[39m\n", "\u001B[36mFile \u001B[39m\u001B[32m/mnt/d/PyProject/NewQuant/src/indicators/base_indicators.py:32\u001B[39m, in \u001B[36mIndicator.is_condition_met\u001B[39m\u001B[34m(self, close, open, high, low, volume)\u001B[39m\n\u001B[32m 26\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34mis_condition_met\u001B[39m(\u001B[38;5;28mself\u001B[39m,\n\u001B[32m 27\u001B[39m close: np.array,\n\u001B[32m 28\u001B[39m \u001B[38;5;28mopen\u001B[39m: np.array,\n\u001B[32m 29\u001B[39m high: np.array,\n\u001B[32m 30\u001B[39m low: np.array,\n\u001B[32m 31\u001B[39m volume: np.array):\n\u001B[32m---> \u001B[39m\u001B[32m32\u001B[39m value = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mget_latest_value\u001B[49m\u001B[43m(\u001B[49m\u001B[43mclose\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mopen\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mhigh\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mlow\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mvolume\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 33\u001B[39m condition_met = \u001B[38;5;28;01mTrue\u001B[39;00m\n\u001B[32m 34\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m value \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n", "\u001B[36mFile \u001B[39m\u001B[32m/mnt/d/PyProject/NewQuant/src/indicators/base_indicators.py:22\u001B[39m, in \u001B[36mIndicator.get_latest_value\u001B[39m\u001B[34m(self, close, open, high, low, volume)\u001B[39m\n\u001B[32m 21\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34mget_latest_value\u001B[39m(\u001B[38;5;28mself\u001B[39m, close: np.array, \u001B[38;5;28mopen\u001B[39m: np.array, high: np.array, low: np.array, volume: np.array):\n\u001B[32m---> \u001B[39m\u001B[32m22\u001B[39m values = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mget_values\u001B[49m\u001B[43m(\u001B[49m\u001B[43mclose\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mopen\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mhigh\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mlow\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mvolume\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 23\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m values[-(\u001B[38;5;28mself\u001B[39m.shift_window + \u001B[32m1\u001B[39m)].item() \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mlen\u001B[39m(values) > \u001B[38;5;28mself\u001B[39m.shift_window + \u001B[32m1\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m\n", "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[35]\u001B[39m\u001B[32m, line 47\u001B[39m, in \u001B[36mMLFilterIndicator.get_values\u001B[39m\u001B[34m(self, close, open, high, low, volume)\u001B[39m\n\u001B[32m 42\u001B[39m df = pd.DataFrame(\n\u001B[32m 43\u001B[39m {\u001B[33m'\u001B[39m\u001B[33mdatetime\u001B[39m\u001B[33m'\u001B[39m: pd.to_datetime(np.arange(\u001B[38;5;28mlen\u001B[39m(close))), \u001B[33m'\u001B[39m\u001B[33mopen\u001B[39m\u001B[33m'\u001B[39m: \u001B[38;5;28mopen\u001B[39m, \u001B[33m'\u001B[39m\u001B[33mhigh\u001B[39m\u001B[33m'\u001B[39m: high, \u001B[33m'\u001B[39m\u001B[33mlow\u001B[39m\u001B[33m'\u001B[39m: low, \u001B[33m'\u001B[39m\u001B[33mclose\u001B[39m\u001B[33m'\u001B[39m: close,\n\u001B[32m 44\u001B[39m \u001B[33m'\u001B[39m\u001B[33mvolume\u001B[39m\u001B[33m'\u001B[39m: volume})\n\u001B[32m 46\u001B[39m \u001B[38;5;66;03m# 直接调用统一的特征计算函数\u001B[39;00m\n\u001B[32m---> \u001B[39m\u001B[32m47\u001B[39m df_with_features = \u001B[43mcalculate_features\u001B[49m\u001B[43m(\u001B[49m\u001B[43mdf\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtrendline_n\u001B[49m\u001B[43m=\u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mtrendline_n\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 49\u001B[39m \u001B[38;5;66;03m# --- 后续的预测流程与之前相同 ---\u001B[39;00m\n\u001B[32m 50\u001B[39m required_cols = \u001B[38;5;28mself\u001B[39m.feature_names\n", "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[34]\u001B[39m\u001B[32m, line 79\u001B[39m, in \u001B[36mcalculate_features\u001B[39m\u001B[34m(df, trendline_n)\u001B[39m\n\u001B[32m 76\u001B[39m \u001B[38;5;66;03m# --- 【修正】统一的趋势线和价差计算 ---\u001B[39;00m\n\u001B[32m 77\u001B[39m close_prices = df[\u001B[33m'\u001B[39m\u001B[33mclose\u001B[39m\u001B[33m'\u001B[39m].values\n\u001B[32m 78\u001B[39m trend_results = [\n\u001B[32m---> \u001B[39m\u001B[32m79\u001B[39m \u001B[43m_calculate_latest_trendline_values\u001B[49m\u001B[43m(\u001B[49m\u001B[43mclose_prices\u001B[49m\u001B[43m[\u001B[49m\u001B[43mi\u001B[49m\u001B[43m \u001B[49m\u001B[43m-\u001B[49m\u001B[43m \u001B[49m\u001B[43mtrendline_n\u001B[49m\u001B[43m:\u001B[49m\u001B[43mi\u001B[49m\u001B[43m]\u001B[49m\u001B[43m)\u001B[49m \u001B[38;5;28;01mif\u001B[39;00m i >= trendline_n \u001B[38;5;28;01melse\u001B[39;00m (np.nan, np.nan)\n\u001B[32m 80\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m i \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(\u001B[38;5;28mlen\u001B[39m(close_prices))\n\u001B[32m 81\u001B[39m ]\n\u001B[32m 82\u001B[39m trend_df = pd.DataFrame(trend_results, index=df.index, columns=[\u001B[33m'\u001B[39m\u001B[33mupper_trendline\u001B[39m\u001B[33m'\u001B[39m, \u001B[33m'\u001B[39m\u001B[33mlower_trendline\u001B[39m\u001B[33m'\u001B[39m])\n\u001B[32m 84\u001B[39m df[\u001B[33m'\u001B[39m\u001B[33mtrendline_slope\u001B[39m\u001B[33m'\u001B[39m] = (trend_df[\u001B[33m'\u001B[39m\u001B[33mupper_trendline\u001B[39m\u001B[33m'\u001B[39m] - trend_df[\u001B[33m'\u001B[39m\u001B[33mlower_trendline\u001B[39m\u001B[33m'\u001B[39m]) / trendline_n\n", "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[34]\u001B[39m\u001B[32m, line 50\u001B[39m, in \u001B[36m_calculate_latest_trendline_values\u001B[39m\u001B[34m(prices)\u001B[39m\n\u001B[32m 48\u001B[39m intercept = low_point_price - candidate_slope * low_point_idx\n\u001B[32m 49\u001B[39m candidate_line = candidate_slope * x + intercept\n\u001B[32m---> \u001B[39m\u001B[32m50\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[43mnp\u001B[49m\u001B[43m.\u001B[49m\u001B[43mall\u001B[49m\u001B[43m(\u001B[49m\u001B[43mcandidate_line\u001B[49m\u001B[43m \u001B[49m\u001B[43m<\u001B[49m\u001B[43m=\u001B[49m\u001B[43m \u001B[49m\u001B[43mprices\u001B[49m\u001B[43m \u001B[49m\u001B[43m+\u001B[49m\u001B[43m \u001B[49m\u001B[32;43m1e-9\u001B[39;49m\u001B[43m)\u001B[49m:\n\u001B[32m 51\u001B[39m distance_sum = np.sum(prices - candidate_line)\n\u001B[32m 52\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m distance_sum < min_lower_distance_sum:\n", "\u001B[36mFile \u001B[39m\u001B[32m~/miniconda3/envs/quant/lib/python3.12/site-packages/numpy/_core/fromnumeric.py:2584\u001B[39m, in \u001B[36m_all_dispatcher\u001B[39m\u001B[34m(a, axis, out, keepdims, where)\u001B[39m\n\u001B[32m 2479\u001B[39m \u001B[38;5;250m \u001B[39m\u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 2480\u001B[39m \u001B[33;03m Test whether any array element along a given axis evaluates to True.\u001B[39;00m\n\u001B[32m 2481\u001B[39m \n\u001B[32m (...)\u001B[39m\u001B[32m 2578\u001B[39m \n\u001B[32m 2579\u001B[39m \u001B[33;03m \"\"\"\u001B[39;00m\n\u001B[32m 2580\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m _wrapreduction_any_all(a, np.logical_or, \u001B[33m'\u001B[39m\u001B[33many\u001B[39m\u001B[33m'\u001B[39m, axis, out,\n\u001B[32m 2581\u001B[39m keepdims=keepdims, where=where)\n\u001B[32m-> \u001B[39m\u001B[32m2584\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34m_all_dispatcher\u001B[39m(a, axis=\u001B[38;5;28;01mNone\u001B[39;00m, out=\u001B[38;5;28;01mNone\u001B[39;00m, keepdims=\u001B[38;5;28;01mNone\u001B[39;00m, *,\n\u001B[32m 2585\u001B[39m where=\u001B[38;5;28;01mNone\u001B[39;00m):\n\u001B[32m 2586\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m (a, where, out)\n\u001B[32m 2589\u001B[39m \u001B[38;5;129m@array_function_dispatch\u001B[39m(_all_dispatcher)\n\u001B[32m 2590\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34mall\u001B[39m(a, axis=\u001B[38;5;28;01mNone\u001B[39;00m, out=\u001B[38;5;28;01mNone\u001B[39;00m, keepdims=np._NoValue, *, where=np._NoValue):\n", "\u001B[31mKeyboardInterrupt\u001B[39m: " ] } ], "execution_count": 38 } ], "metadata": { "kernelspec": { "display_name": "quant", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.11" } }, "nbformat": 4, "nbformat_minor": 5 }