From 283a7c89f85b1584fde8ff429028506dc00e53d7 Mon Sep 17 00:00:00 2001
From: Administrator <admin@example.com>
Date: 星期二, 08 七月 2025 14:17:47 +0800
Subject: [PATCH] bug修复/策略完善

---
 strategy/time_series_backtest.py | 1063 +++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 705 insertions(+), 358 deletions(-)

diff --git a/strategy/time_series_backtest.py b/strategy/time_series_backtest.py
index d9f007a..4a14f4c 100644
--- a/strategy/time_series_backtest.py
+++ b/strategy/time_series_backtest.py
@@ -1,19 +1,21 @@
+import logging
+
 import constant
 from code_attribute import gpcode_manager, code_nature_analyse
-from strategy.data_analyzer import KPLLimitUpDataAnalyzer
-from strategy.data_downloader import DataDownloader
-from strategy.low_suction_strategy import LowSuctionOriginDataExportManager
-from strategy.strategy_params_settings import StrategyParamsSettings, StrategyParamsSettingsManager
+from strategy.data.data_analyzer import KPLLimitUpDataAnalyzer
+from strategy.data.data_downloader import DataDownloader
+from strategy.data.data_manager import LowSuctionOriginDataExportManager
+from strategy.strategy_params_settings import StrategyParamsSettingsManager
 from strategy.strategy_variable import StockVariables
 from strategy.strategy_variable_factory import DataLoader, StrategyVariableFactory
 from third_data import kpl_util
-from third_data.third_blocks_manager import BlockMapManager
 from utils import tool, huaxin_util
 
 
 class BackTest:
 
-    def __init__(self, day, script_name="浣庡惛鑴氭湰_杈ㄨ瘑搴v3.py", settings=StrategyParamsSettingsManager().get_settings()):
+    def __init__(self, day, script_name="浣庡惛鑴氭湰_杈ㄨ瘑搴v3.py", settings=StrategyParamsSettingsManager().get_settings(),
+                 target_codes=set()):
         self.day = day
         scripts = ""
         with open(script_name, mode='r', encoding='utf-8') as f:
@@ -26,7 +28,7 @@
         self.settings = settings
         self.scripts = scripts
         self.RANGE_TIMES = ("09:25:00", "11:30:00")
-        self.current_time = '09:25:00'
+        self.current_time = self.RANGE_TIMES[0]
 
         self.stock_variables_dict = {}
         self.data_loader: DataLoader = None
@@ -40,6 +42,9 @@
         self.deal_codes = set()
         # 鏉垮潡宸茬粡鎴愪氦鐨勪唬鐮�
         self.deal_block_codes = {}
+        self.target_codes = target_codes
+        self.backtest_results = []
+        self.finish = False
 
     def set_script(self, script):
         self.scripts = script
@@ -120,15 +125,16 @@
         :return: 鎸夋椂闂存帓搴忕殑鏁版嵁鍒楄〃
         """
         if self.day >= '2025-05-26':
-            IS_BY_BIG_ORDER = True
-        else:
             IS_BY_BIG_ORDER = False
+        else:
+            IS_BY_BIG_ORDER = True
         day = self.day
         fdata = {}
         __LowSuctionOriginDataExportManager = LowSuctionOriginDataExportManager(day)
         all_limit_up_list = __LowSuctionOriginDataExportManager.export_limit_up_list()
         fdata["limit_up_list"] = {d[0][:8]: d[1] for d in all_limit_up_list}
-        big_order_deals = __LowSuctionOriginDataExportManager.export_big_order_deal(BIG_ORDER_MONEY_THRESHOLD)
+        big_order_deals = __LowSuctionOriginDataExportManager.export_big_order_deal(BIG_ORDER_MONEY_THRESHOLD,
+                                                                                    max_deal_space=3)
         if not big_order_deals or IS_BY_BIG_ORDER:
             big_order_deals = __LowSuctionOriginDataExportManager.export_big_order_deal_by(BIG_ORDER_MONEY_THRESHOLD)
         # 杞崲鏍煎紡涓猴細{鏃堕棿: [("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))]
@@ -170,7 +176,8 @@
 
         code_plates_dict_for_refer = self.data_loader.load_code_plates_for_refer()
 
-        plate_codes = self.data_loader.load_target_plate_and_codes()
+        # TODO 蹇�熸媺浼搁┍鍔�
+        plate_codes = self.data_loader.load_target_plate_and_codes_v2()
         code_plates_dict_for_buy = {}
         for p in plate_codes:
             for code in plate_codes.get(p):
@@ -248,43 +255,6 @@
         exec(self.scripts, global_dict)
         return global_dict["compute_result"]
 
-    def __filter_codes(self, current_data, timeline_data):
-        code_plates = current_data["code_plates"]
-        start_time, end_time = self.RANGE_TIMES[0], self.RANGE_TIMES[1]
-        fplates = set()
-        for i in range(60 * 60 * 5):
-            time_str = tool.trade_time_add_second(start_time, i)
-            if time_str > end_time:
-                break
-            self.current_time = time_str
-            # 缁熻褰撳墠娑ㄥ仠鏁版嵁
-            current_limit_up_list = current_data["limit_up_list"].get(time_str)
-            if current_limit_up_list:
-                # 缁熻鏉垮潡娑ㄥ仠
-                plate_codes_info = {}
-                for x in current_limit_up_list:
-                    plates = code_plates.get(x[0])
-                    if plates:
-                        for p in plates:
-                            if p not in plate_codes_info:
-                                plate_codes_info[p] = []
-                            plate_codes_info[p].append((x[0], x[2]))
-                # print(time_str, "姹借溅闆堕儴浠�", plate_codes_info.get("姹借溅闆堕儴浠�"))
-                # 鏈夋晥鐨勬澘鍧�
-                valid_plates = set([p for p in plate_codes_info if len(plate_codes_info[p]) >= 2])
-                fplates |= valid_plates
-        codes = set([code for code in code_plates if code_plates[code] & fplates])
-        fcodes = set()
-        for c in codes:
-            if c not in timeline_data["kline_data"]:
-                continue
-            # 鑷敱娴侀�氬競鍊�30-300浜�
-            pre_close = timeline_data["kline_data"].get(c)[0]["close"]
-            if 30e8 <= current_data["zylt_volume"].get(c) * pre_close <= 300e8:
-                fcodes.add(c)
-
-        return fcodes
-
     def __get_target_codes_v4(self):
         valid_codes = self.timeline_data["valid_codes"]
         return set(self.current_data["code_plates_for_buy"].keys()) & valid_codes
@@ -297,6 +267,9 @@
         """
         if code_ in self.stock_variables_dict:
             return
+
+        if code_ == '002907':
+            print("")
 
         stock_variables = StrategyVariableFactory.create_from_history_data(
             timeline_data["kline_data"].get(code_), timeline_data["minute_data"].get(code_),
@@ -316,8 +289,6 @@
         stock_variables.鏂颁唬鐮佹澘鍧� = timeline_data["code_blocks"].get(code_)
         stock_variables.杈ㄨ瘑搴︿唬鐮� = self.fcodes
         stock_variables.棰嗘定鏉垮潡淇℃伅 = self.head_rise_code_blocks.get(code_)
-        if code_ in DEBUG_CODES:
-            print(code_, stock_variables.棰嗘定鏉垮潡淇℃伅)
 
         for day in [2, 5, 10, 30, 60, 120]:
             days = timeline_data["trade_days"][:day]
@@ -327,7 +298,7 @@
                                             max_day=days[0]))
         stock_variables.杩炵画鑰侀鏉� = KPLLimitUpDataAnalyzer.get_continuous_limit_up_reasons(
             timeline_data["limit_up_record_data_list"], self.data_loader.trade_days[:2])
-
+        stock_variables.杩炵画鑰侀鏉�.clear()
         self.stock_variables_dict[code_] = stock_variables
 
     def load_data(self):
@@ -353,7 +324,7 @@
             # self.fcodes, self.head_rise_code_blocks = self.__get_target_codes_v3()  # __filter_codes(current_data, timeline_data)
             self.fcodes, self.head_rise_code_blocks = self.__get_target_codes_v4(), {}
 
-        print(len(self.fcodes), self.fcodes)
+        print(len(self.fcodes))
         if not self.current_tick_data:
             try:
                 self.current_tick_data = self.load_current_tick_datas(self.data_loader)
@@ -411,363 +382,731 @@
         return ";".join([f"{x[0]}==鍑�棰�:{x[1]},涔板崟锛歿x[2]},鍗栧崟锛歿x[3]}" for x in infos])
 
     def run(self):
-        self.load_data()
-        # print(self.fcodes)
-        limit_up_record_data_dict = {}
-        for limit_up_item in self.timeline_data["limit_up_record_data"]:
-            if limit_up_item[0] not in limit_up_record_data_dict:
-                limit_up_record_data_dict[limit_up_item[0]] = []
-            limit_up_record_data_dict[limit_up_item[0]].append(limit_up_item)
-        self.timeline_data["limit_up_record_data"] = limit_up_record_data_dict
-        next_trade_day = self.timeline_data["next_trade_day"]
-        start_time, end_time = "09:25:00", "12:00:00"
-        # 鍒嗛挓K绾�
-        minute_bars_dict = {}
-        code_plates = self.current_data["code_plates"]
-        code_plates_for_refer = self.current_data["code_plates_for_refer"]
+        try:
+            self.load_data()
+            # print(self.fcodes)
+            limit_up_record_data_dict = {}
+            for limit_up_item in self.timeline_data["limit_up_record_data"]:
+                if limit_up_item[0] not in limit_up_record_data_dict:
+                    limit_up_record_data_dict[limit_up_item[0]] = []
+                limit_up_record_data_dict[limit_up_item[0]].append(limit_up_item)
+            self.timeline_data["limit_up_record_data"] = limit_up_record_data_dict
+            next_trade_day = self.timeline_data["next_trade_day"]
+            start_time, end_time = "09:25:00", "12:00:00"
+            # 鍒嗛挓K绾�
+            minute_bars_dict = {}
+            code_plates = self.current_data["code_plates"]
+            code_plates_for_refer = self.current_data["code_plates_for_refer"]
 
-        # 鏉垮潡娑ㄥ仠浠g爜淇℃伅
-        kpl_plate_limit_up_codes_info = None
-        plate_limit_up_codes_info = None
-        kpl_head_plate_limit_up_codes_info = None
+            # 鏉垮潡娑ㄥ仠浠g爜淇℃伅
+            kpl_plate_limit_up_codes_info = None
+            plate_limit_up_codes_info = None
+            kpl_head_plate_limit_up_codes_info = None
 
-        latest_current_limit_up_list = None
+            latest_current_limit_up_list = None
 
-        latest_block_in_datas = None
+            latest_block_in_datas = None
 
-        # 鏍规嵁鏉垮潡鑾峰彇鐩爣绁�
-        target_plate_codes_infos = {}
-        for code in self.head_rise_code_blocks:
-            for p in self.head_rise_code_blocks[code]:
-                if p not in target_plate_codes_infos:
-                    target_plate_codes_infos[p] = []
-                target_plate_codes_infos[p].append(self.head_rise_code_blocks[code][p])
-        for p in target_plate_codes_infos:
-            target_plate_codes_infos[p].sort(key=lambda x: x[1], reverse=True)
+            # 鏍规嵁鏉垮潡鑾峰彇鐩爣绁�
+            target_plate_codes_infos = {}
+            for code in self.head_rise_code_blocks:
+                for p in self.head_rise_code_blocks[code]:
+                    if p not in target_plate_codes_infos:
+                        target_plate_codes_infos[p] = []
+                    target_plate_codes_infos[p].append(self.head_rise_code_blocks[code][p])
+            for p in target_plate_codes_infos:
+                target_plate_codes_infos[p].sort(key=lambda x: x[1], reverse=True)
 
-        all_new_plates = set()
+            all_new_plates = set()
 
-        for i in range(60 * 60 * 5):
-            time_str = tool.trade_time_add_second(start_time, i)
-            # print(f"[{tool.get_now_time_str()}]", time_str)
-            if time_str > end_time:
-                break
-            ticks = self.current_tick_data.get(time_str) if self.current_tick_data else None
-            # ===============缁熻褰撳墠娑ㄥ仠鏁版嵁
-            origin_current_limit_up_list = self.current_data["limit_up_list"].get(time_str, [])
-            current_limit_up_list = [x for x in origin_current_limit_up_list if kpl_util.get_high_level_count(x[4]) < 3]
+            for i in range(60 * 60 * 5):
+                if self.finish:
+                    break
+                time_str = tool.trade_time_add_second(start_time, i)
+                # print(f"[{tool.get_now_time_str()}]", time_str)
+                if time_str > end_time:
+                    break
+                self.current_time = time_str
+                ticks = self.current_tick_data.get(time_str) if self.current_tick_data else None
+                # ===============缁熻褰撳墠娑ㄥ仠鏁版嵁
+                origin_current_limit_up_list = self.current_data["limit_up_list"].get(time_str, [])
+                current_limit_up_list = [x for x in origin_current_limit_up_list if
+                                         kpl_util.get_high_level_count(x[4]) < 3]
 
-            if current_limit_up_list:
-                latest_current_limit_up_list = current_limit_up_list
+                if current_limit_up_list:
+                    latest_current_limit_up_list = current_limit_up_list
 
-            if current_limit_up_list:
-                plate_codes_info = {}
-                # 缁熻鏉垮潡娑ㄥ仠
-                for x in current_limit_up_list:
-                    # 鎸変唬鐮佺殑鏉垮潡缁熻娑ㄥ仠鏉垮潡涓殑浠g爜鏁伴噺
-                    # 娑ㄥ仠杩�1鍒嗛挓鎵嶇畻鏈夋晥娑ㄥ仠
-                    if tool.trade_time_sub(time_str, tool.timestamp_format(x[2], "%H:%M:%S")) < 60:
-                        continue
-                    plates = code_plates.get(x[0])
-                    if plates:
+                if current_limit_up_list:
+                    plate_codes_info = {}
+                    # 缁熻鏉垮潡娑ㄥ仠
+                    for x in current_limit_up_list:
+                        # 鎸変唬鐮佺殑鏉垮潡缁熻娑ㄥ仠鏉垮潡涓殑浠g爜鏁伴噺
+                        # 娑ㄥ仠杩�1鍒嗛挓鎵嶇畻鏈夋晥娑ㄥ仠
+                        if tool.trade_time_sub(time_str, tool.timestamp_format(x[2], "%H:%M:%S")) < 60:
+                            continue
+                        plates = code_plates.get(x[0])
+                        if plates:
+                            for p in plates:
+                                if p not in plate_codes_info:
+                                    plate_codes_info[p] = []
+                                plate_codes_info[p].append((x[0], x[2]))
+                    plate_limit_up_codes_info = plate_codes_info
+
+                    plate_codes_info = {}
+                    for x in current_limit_up_list:
+                        # 鎸夊紑鐩樺暒娑ㄥ仠鍘熷洜缁熻
+                        p = x[5]
+                        if p in constant.KPL_INVALID_BLOCKS:
+                            continue
+                        if p not in plate_codes_info:
+                            plate_codes_info[p] = []
+                        # 濡傛灉棰嗘定浠g爜閲岄潰娌℃湁褰撳墠绁ㄥ氨涓嶇畻杩欎釜鏉垮潡鐨勬定鍋滃師鍥�
+                        # 鑾峰彇棰嗘定鏁版嵁
+                        # head_plate_codes_info = self.data_loader.load_plate_codes(x[9], p)
+                        # if head_plate_codes_info:
+                        #     plate_codes = set([x[0] for x in head_plate_codes_info])
+                        # else:
+                        #     plate_codes = set()
+                        # if x[0] not in plate_codes:
+                        #     continue
+                        plate_codes_info[p].append((x[0], x[2], x[4]))
+                    kpl_plate_limit_up_codes_info = plate_codes_info
+
+                    # {"浠g爜":[(鏉垮潡浠g爜, 鏉垮潡鍚嶇О)]}
+                    limit_up_plate_names_of_refer_code = self.current_data["limit_up_plate_names_of_refer_code"]
+                    plate_codes_info = {}
+                    for x in current_limit_up_list:
+                        # 鎸夊紑鐩樺暒娑ㄥ仠鍘熷洜缁熻
+                        code = x[0]
+                        # if code not in limit_up_plate_names_of_refer_code:
+                        #     continue
+                        # 濡傛灉璁板綍娑ㄥ仠鏃堕棿杩囧幓20鍒嗛挓灏遍噰鐢ㄦ定鍋滈槦鍒楃殑娑ㄥ仠鍘熷洜
+                        if tool.trade_time_sub(time_str, tool.timestamp_format(x[2], "%H:%M:%S")) < 60 * 20 or True:
+                            plates_infos = limit_up_plate_names_of_refer_code.get(code)
+                            plates = set([d[1] for d in plates_infos if d[1] == x[5]]) if plates_infos else set()
+                        else:
+                            plates = {x[5]}
+
+                        new_plates = set()
                         for p in plates:
+                            if p in constant.KPL_INVALID_BLOCKS:
+                                continue
+                            new_plates.add(p)
+                        for p in new_plates:
                             if p not in plate_codes_info:
                                 plate_codes_info[p] = []
                             plate_codes_info[p].append((x[0], x[2]))
-                plate_limit_up_codes_info = plate_codes_info
+                    kpl_head_plate_limit_up_codes_info = plate_codes_info
 
-                plate_codes_info = {}
-                for x in current_limit_up_list:
-                    # 鎸夊紑鐩樺暒娑ㄥ仠鍘熷洜缁熻
-                    p = x[5]
-                    if p in constant.KPL_INVALID_BLOCKS:
-                        continue
-                    if p not in plate_codes_info:
-                        plate_codes_info[p] = []
-                    # 濡傛灉棰嗘定浠g爜閲岄潰娌℃湁褰撳墠绁ㄥ氨涓嶇畻杩欎釜鏉垮潡鐨勬定鍋滃師鍥�
-                    # 鑾峰彇棰嗘定鏁版嵁
-                    # head_plate_codes_info = self.data_loader.load_plate_codes(x[9], p)
-                    # if head_plate_codes_info:
-                    #     plate_codes = set([x[0] for x in head_plate_codes_info])
-                    # else:
-                    #     plate_codes = set()
-                    # if x[0] not in plate_codes:
-                    #     continue
-                    plate_codes_info[p].append((x[0], x[2], x[4]))
-                kpl_plate_limit_up_codes_info = plate_codes_info
+                # ==================娉ㄥ叆鏉垮潡娴佸叆
+                block_in_datas = self.current_data["block_in"].get(time_str)
+                if block_in_datas:
+                    blocks = [x[0] for x in block_in_datas if x[1] > 0]
+                    block_in_datas = blocks[:20]
+                    latest_block_in_datas = block_in_datas
 
-                # {"浠g爜":[(鏉垮潡浠g爜, 鏉垮潡鍚嶇О)]}
-                limit_up_plate_names_of_refer_code = self.current_data["limit_up_plate_names_of_refer_code"]
-                plate_codes_info = {}
-                for x in current_limit_up_list:
-                    # 鎸夊紑鐩樺暒娑ㄥ仠鍘熷洜缁熻
-                    code = x[0]
-                    # if code not in limit_up_plate_names_of_refer_code:
-                    #     continue
-                    # 濡傛灉璁板綍娑ㄥ仠鏃堕棿杩囧幓20鍒嗛挓灏遍噰鐢ㄦ定鍋滈槦鍒楃殑娑ㄥ仠鍘熷洜
-                    if tool.trade_time_sub(time_str, tool.timestamp_format(x[2], "%H:%M:%S")) < 60 * 20 or True:
-                        plates_infos = limit_up_plate_names_of_refer_code.get(code)
-                        plates = set([d[1] for d in plates_infos if d[1] == x[5]]) if plates_infos else set()
-                    else:
-                        plates = {x[5]}
+                # ================褰撳墠鏃跺埢澶у崟
+                current_big_orders = self.current_data["big_order"].get(time_str)
+                if current_big_orders:
+                    for big_order in current_big_orders:
+                        # 鏍煎紡 ("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))
+                        self.init_stock_variables(big_order[0], self.timeline_data, self.current_data)
+                        stock_variables: StockVariables = self.stock_variables_dict.get(big_order[0])
+                        if stock_variables.浠婃棩澶у崟鏁版嵁 is None:
+                            stock_variables.浠婃棩澶у崟鏁版嵁 = []
+                        stock_variables.浠婃棩澶у崟鏁版嵁.append(big_order[1])
+                        # 缁熻澶у崟鍧囦环
+                        order_ids = set()
+                        total_money = 0
+                        total_volume = 0
+                        for order in reversed(stock_variables.浠婃棩澶у崟鏁版嵁):
+                            if order[0] in order_ids:
+                                continue
+                            order_ids.add(order[0])
+                            total_money += order[2]
+                            total_volume += order[1]
+                        if total_volume > 0:
+                            stock_variables.浠婃棩澶у崟鍧囦环 = round(total_money / total_volume, 2)
+                        else:
+                            stock_variables.浠婃棩澶у崟鍧囦环 = 0
+                current_big_sell_orders = self.current_data["big_sell_order"].get(time_str)
+                if current_big_sell_orders:
+                    for big_order in current_big_sell_orders:
+                        # 鏍煎紡 ("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))
+                        self.init_stock_variables(big_order[0], self.timeline_data, self.current_data)
+                        stock_variables: StockVariables = self.stock_variables_dict.get(big_order[0])
+                        if stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹� is None:
+                            stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹� = []
+                        stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹�.append(big_order[1])
 
-                    new_plates = set()
+                # 寮�鐩樺暒鏈�姝f定鍋滃師鍥�
+                most_real_kpl_plate_limit_up_codes_info = {}
+                # 鑾峰彇杩欎釜鏉垮潡鐨勭洰鏍囩エ
+                if kpl_plate_limit_up_codes_info:
+                    current_limit_up_dict = {x[0]: x for x in latest_current_limit_up_list}
+                    codes = set()
+                    for plate in kpl_plate_limit_up_codes_info:
+                        kpl_plate_codes = kpl_plate_limit_up_codes_info.get(plate)
+                        codes |= set([x[0] for x in kpl_plate_codes])
+                    for code in codes:
+                        plates = code_plates.get(code)
+                        if not plates:
+                            plates = {current_limit_up_dict.get(code)[5]}
+                        plates -= constant.KPL_INVALID_BLOCKS
+                        if plates:
+                            for p in plates:
+                                if p not in most_real_kpl_plate_limit_up_codes_info:
+                                    most_real_kpl_plate_limit_up_codes_info[p] = []
+                                most_real_kpl_plate_limit_up_codes_info[p].append(code)
+                    # print(time_str, "娑ㄥ仠鏁板ぇ浜�3涓�", [p for p in most_real_kpl_plate_limit_up_codes_info if
+                    #                             len(most_real_kpl_plate_limit_up_codes_info[p]) >= 3])
+
+                    # ---------娴嬭瘯--------
+                    # test_plate = "鍖栧伐"
+                    # if len(most_real_kpl_plate_limit_up_codes_info.get(test_plate, [])) >= 3:
+                    #     print("娴嬭瘯寮�濮�=========")
+                    #     code_plates_for_buy = self.current_data["code_plates_for_buy"]
+                    #     plate_codes = [c for c in code_plates_for_buy if test_plate in code_plates_for_buy[c]]
+                    #     print(f"{test_plate}婊¤冻", time_str, plate_codes)
+                    #     for c in plate_codes:
+                    #         sv: StockVariables = self.stock_variables_dict.get(c)
+                    #         if sv and sv.褰撳墠浠� > sv.鏄ㄦ棩鏀剁洏浠�:
+                    #             print(c)
+                    #     print("娴嬭瘯瀹屾瘯=========")
+
+                if ticks:
+                    for tick in ticks:
+                        code = tick["symbol"][-6:]
+                        if code not in self.fcodes:
+                            continue
+                        if self.target_codes and code not in self.target_codes:
+                            continue
+
+                        if code not in self.stock_variables_dict:
+                            # 鍔犺浇鍩虹鏁版嵁
+                            self.init_stock_variables(code, self.timeline_data, self.current_data)
+                        stock_variables: StockVariables = self.stock_variables_dict.get(code)
+                        if plate_limit_up_codes_info is not None:
+                            stock_variables.鏉垮潡娑ㄥ仠 = plate_limit_up_codes_info
+
+                        if kpl_plate_limit_up_codes_info is not None:
+                            stock_variables.寮�鐩樺暒鏉垮潡娑ㄥ仠 = kpl_plate_limit_up_codes_info
+
+                        if kpl_head_plate_limit_up_codes_info is not None:
+                            stock_variables.寮�鐩樺暒棰嗘定鏉垮潡娑ㄥ仠 = kpl_head_plate_limit_up_codes_info
+
+                        stock_variables.鏉垮潡鎴愪氦浠g爜 = self.deal_block_codes
+                        # 鏉垮潡娴佸叆鏁版嵁
+                        if latest_block_in_datas:
+                            stock_variables.璧勯噾娴佸叆鏉垮潡 = latest_block_in_datas
+                        # 鏆傛椂涓嶇敤鍒嗛挓K绾�
+                        # if code not in minute_bars_dict:
+                        #     minute_bars_dict[code] = [tick]
+                        # if minute_bars_dict[code][-1]["created_at"][:-2] == tick["created_at"][:-2]:
+                        #     # 缁熻鍒嗛挓K绾�
+                        #     minute_bars_dict[code][-1] = tick
+                        # else:
+                        #     # 淇濆瓨鍒嗛挓K绾挎渶楂樹环
+                        #     if not stock_variables.浠婃棩鏈�楂樹环:
+                        #         stock_variables.浠婃棩鏈�楂樹环 = minute_bars_dict[code][-1]["price"]
+                        #     if minute_bars_dict[code][-1]["price"] > stock_variables.浠婃棩鏈�楂樹环:
+                        #         stock_variables.浠婃棩鏈�楂樹环 = minute_bars_dict[code][-1]["price"]
+
+                        # 淇濆瓨寮�鐩樹环
+                        if tick["created_at"][-8:] < '09:30:00':
+                            stock_variables.浠婃棩寮�鐩樹环 = tick["price"]
+                            # 浠婃棩寮�鐩樻定骞�
+                            stock_variables.浠婃棩寮�鐩樻定骞� = round(
+                                (tick["price"] - stock_variables.鏄ㄦ棩鏀剁洏浠�) / stock_variables.鏄ㄦ棩鏀剁洏浠�,
+                                4)
+                        stock_variables.浠婃棩鎴愪氦閲� = tick["cum_volume"]
+                        stock_variables.浠婃棩鎴愪氦棰� = tick["cum_amount"]
+                        stock_variables.褰撳墠浠� = tick["price"]
+                        if not stock_variables.浠婃棩閲忓淇℃伅:
+                            if stock_variables.浠婃棩鎴愪氦閲� > stock_variables.鏄ㄦ棩鎴愪氦閲� * 0.8:
+                                stock_variables.浠婃棩閲忓淇℃伅 = (time_str, stock_variables.褰撳墠浠�, round(
+                                    (stock_variables.褰撳墠浠� - stock_variables.鏄ㄦ棩鏀剁洏浠�) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2),
+                                                          self.__statistic_big_order_info(stock_variables))
+                                if VOLUME_LOG_ENABLE:
+                                    # 缁熻澶у崟鍑�棰濓紝(50w浠ヤ笂,鍑�棰�,涔板崟涓暟/涔板崟鎬婚噾棰�,鍗栧崟涓暟/鍗栧崟鎬婚噾棰�)
+                                    print("****閲忓", code, stock_variables.浠婃棩閲忓淇℃伅)
+
+                        # 缁熻浠婃棩鏈�楂樹环
+                        # if stock_variables.浠婃棩鏈�楂樹环 and tick["price"] > stock_variables.浠婃棩鏈�楂樹环:
+                        #     print(code, "====绐佺牬鍒嗘椂鏈�楂樹环锛�", tick["created_at"], tick["price"])
+
+                        if not stock_variables.浠婃棩鏈�楂樹环淇℃伅 or tick["price"] > stock_variables.浠婃棩鏈�楂樹环淇℃伅[0]:
+                            stock_variables.浠婃棩鏈�楂樹环淇℃伅 = (tick["price"], time_str)
+
+                        if not stock_variables.浠婃棩鏈�浣庝环 or tick["price"] < stock_variables.浠婃棩鏈�浣庝环:
+                            stock_variables.浠婃棩鏈�浣庝环 = tick["price"]
+                        if most_real_kpl_plate_limit_up_codes_info:
+                            stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = most_real_kpl_plate_limit_up_codes_info
+
+                        # if time_str >= '09:30:00':
+                        #     if stock_variables.浠婃棩澶у崟鏁版嵁 and stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� and max(
+                        #             [len(stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(x, [])) for x in stock_variables.浠g爜鏉垮潡]) >= 3:
+                        #         compute_result = self.__run_backtest(code, stock_variables)
+                        #         self.__process_test_result(code, stock_variables, next_trade_day, stock_variables.褰撳墠浠�,
+                        #                                    time_str, compute_result)
+
+                        # if len(real_codes) >= 2 and time_str > '09:30:00':
+                        #     # print(time_str, plate)
+                        #     # 鎵捐繖涓澘鍧楅娑ㄦ鏁版渶澶氱殑绁�
+                        #     codes_infos = target_plate_codes_infos.get(plate)
+                        #     if codes_infos:
+                        #         for code_info in codes_infos:
+                        #             code = code_info[0]
+                        #             self.init_stock_variables(code, self.timeline_data, self.current_data)
+                        #             stock_variables: StockVariables = self.stock_variables_dict.get(code)
+                        #             compute_result = self.__run_backtest(code, stock_variables)
+                        #             if compute_result[0] and plate not in all_new_plates:
+                        #                 all_new_plates.add(plate)
+                        #                 print(plate, time_str, code_info, real_codes)
+                        #             else:
+                        #                 pass
+
+                # 澶у崟椹卞姩
+                if current_big_orders and time_str >= '09:30:00':
+                    for big_order in current_big_orders:
+                        code = big_order[0]
+                        if code not in self.fcodes:
+                            continue
+                        if self.target_codes and code not in self.target_codes:
+                            continue
+                        self.init_stock_variables(code, self.timeline_data, self.current_data)
+                        stock_variables: StockVariables = self.stock_variables_dict.get(code)
+                        if plate_limit_up_codes_info is not None:
+                            stock_variables.鏉垮潡娑ㄥ仠 = plate_limit_up_codes_info
+
+                        if kpl_plate_limit_up_codes_info is not None:
+                            stock_variables.寮�鐩樺暒鏉垮潡娑ㄥ仠 = kpl_plate_limit_up_codes_info
+
+                        if kpl_head_plate_limit_up_codes_info is not None:
+                            stock_variables.寮�鐩樺暒棰嗘定鏉垮潡娑ㄥ仠 = kpl_head_plate_limit_up_codes_info
+
+                        if most_real_kpl_plate_limit_up_codes_info is not None:
+                            stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = most_real_kpl_plate_limit_up_codes_info
+
+                        if block_in_datas:
+                            stock_variables.璧勯噾娴佸叆鏉垮潡 = block_in_datas
+
+                        stock_variables.褰撳墠浠� = big_order[1][4]
+                        try:
+                            compute_result = self.__run_backtest(code, stock_variables)
+                            # print(compute_result)
+                            self.__process_test_result(code, stock_variables, next_trade_day, big_order[1][4],
+                                                       huaxin_util.convert_time(big_order[1][3]), compute_result)
+                        except Exception as e:
+                            print(time_str)
+                            logging.exception(e)
+
+            print("鍙拱棰樻潗锛�", all_new_plates)
+        finally:
+            self.finish = True
+
+    def run_v2(self):
+        def __compute_can_buy_plates(_current_limit_up_list):
+            # 缁熻浠g爜寮�1鏁伴噺:(娑ㄥ仠鏃堕棿,娑ㄥ仠鍘熷洜, 鏄惁浜屾澘, 鏄惁涓�鏉�)
+            code_info_dict = {x[0]: (tool.to_time_str(x[2]), x[5], 1 if kpl_util.get_high_level_count(x[4]) == 2 else 0,
+                                     1 if kpl_util.get_high_level_count(x[4]) == 1 else 0) for x in
+                              _current_limit_up_list}
+            plate_codes_dict = {}
+            # 鎸夋澘鍧楀垎绫�
+            for code in code_info_dict.keys():
+                plates = code_plates.get(code)
+                if not plates:
+                    plates = {code_info_dict.get(code)[1]}
+                plates -= constant.KPL_INVALID_BLOCKS
+                if plates:
                     for p in plates:
+                        if p not in plate_codes_dict:
+                            plate_codes_dict[p] = set()
+                        plate_codes_dict[p].add(code)
+            valid_plates = set()
+            for p in plate_codes_dict:
+                codes = list(plate_codes_dict[p])
+                codes.sort(key=lambda x: code_info_dict[x][0])
+                # 寮�1 浜屾澘鏁伴噺
+                open_continue_2_count = sum(
+                    [v[2] for k, v in code_info_dict.items() if k in codes and v[0] < '09:30:00'])
+                # 寮�1 棣栨澘鏁伴噺
+                open_continue_1_count = sum(
+                    [v[3] for k, v in code_info_dict.items() if k in codes and v[0] < '09:30:00'])
+                if open_continue_2_count >= 1 or open_continue_1_count >= 2:
+                    valid_plates.add(p)
+                    continue
+                if len(codes) >= 2 and tool.trade_time_sub(code_info_dict[codes[1]][0],
+                                                           code_info_dict[codes[0]][0]) < 10 * 60:
+                    # 鏈夆墺2涓定鍋滐紝涓斾袱涓定鍋滀箣闂撮棿闅斺墹10鍒嗛挓
+                    valid_plates.add(p)
+                    continue
+            return valid_plates
+
+        # 蹇�熸媺鍗囬┍鍔�
+        try:
+            self.load_data()
+            # print(self.fcodes)
+            limit_up_record_data_dict = {}
+            for limit_up_item in self.timeline_data["limit_up_record_data"]:
+                if limit_up_item[0] not in limit_up_record_data_dict:
+                    limit_up_record_data_dict[limit_up_item[0]] = []
+                limit_up_record_data_dict[limit_up_item[0]].append(limit_up_item)
+            self.timeline_data["limit_up_record_data"] = limit_up_record_data_dict
+            next_trade_day = self.timeline_data["next_trade_day"]
+            start_time, end_time = "09:25:00", "12:00:00"
+            # 鍒嗛挓K绾�
+            minute_bars_dict = {}
+            code_plates = self.current_data["code_plates"]
+            code_plates_for_refer = self.current_data["code_plates_for_refer"]
+
+            # 鏉垮潡娑ㄥ仠浠g爜淇℃伅
+            kpl_plate_limit_up_codes_info = None
+            plate_limit_up_codes_info = None
+            kpl_head_plate_limit_up_codes_info = None
+
+            latest_current_limit_up_list = None
+
+            latest_block_in_datas = None
+
+            latest_can_buy_plates = set()
+
+            # 鏍规嵁鏉垮潡鑾峰彇鐩爣绁�
+            target_plate_codes_infos = {}
+            for code in self.head_rise_code_blocks:
+                for p in self.head_rise_code_blocks[code]:
+                    if p not in target_plate_codes_infos:
+                        target_plate_codes_infos[p] = []
+                    target_plate_codes_infos[p].append(self.head_rise_code_blocks[code][p])
+            for p in target_plate_codes_infos:
+                target_plate_codes_infos[p].sort(key=lambda x: x[1], reverse=True)
+
+            all_new_plates = set()
+
+            for i in range(60 * 60 * 5):
+                if self.finish:
+                    break
+                time_str = tool.trade_time_add_second(start_time, i)
+                # print(f"[{tool.get_now_time_str()}]", time_str)
+                if time_str > end_time:
+                    break
+                self.current_time = time_str
+                ticks = self.current_tick_data.get(time_str) if self.current_tick_data else None
+                # ===============缁熻褰撳墠娑ㄥ仠鏁版嵁
+                origin_current_limit_up_list = self.current_data["limit_up_list"].get(time_str, [])
+                current_limit_up_list = [x for x in origin_current_limit_up_list if
+                                         kpl_util.get_high_level_count(x[4]) < 3]
+
+                if current_limit_up_list:
+                    latest_current_limit_up_list = current_limit_up_list
+
+                if current_limit_up_list:
+                    latest_can_buy_plates = __compute_can_buy_plates(current_limit_up_list)
+                    plate_codes_info = {}
+                    # 缁熻鏉垮潡娑ㄥ仠
+                    for x in current_limit_up_list:
+                        # 鎸変唬鐮佺殑鏉垮潡缁熻娑ㄥ仠鏉垮潡涓殑浠g爜鏁伴噺
+                        # 娑ㄥ仠杩�1鍒嗛挓鎵嶇畻鏈夋晥娑ㄥ仠
+                        if tool.trade_time_sub(time_str, tool.timestamp_format(x[2], "%H:%M:%S")) < 60:
+                            continue
+                        plates = code_plates.get(x[0])
+                        if plates:
+                            for p in plates:
+                                if p not in plate_codes_info:
+                                    plate_codes_info[p] = []
+                                plate_codes_info[p].append((x[0], x[2]))
+                    plate_limit_up_codes_info = plate_codes_info
+
+                    plate_codes_info = {}
+                    for x in current_limit_up_list:
+                        # 鎸夊紑鐩樺暒娑ㄥ仠鍘熷洜缁熻
+                        p = x[5]
                         if p in constant.KPL_INVALID_BLOCKS:
                             continue
-                        new_plates.add(p)
-                    for p in new_plates:
                         if p not in plate_codes_info:
                             plate_codes_info[p] = []
-                        plate_codes_info[p].append((x[0], x[2]))
-                kpl_head_plate_limit_up_codes_info = plate_codes_info
+                        plate_codes_info[p].append((x[0], x[2], x[4]))
+                    kpl_plate_limit_up_codes_info = plate_codes_info
 
-            # ==================娉ㄥ叆鏉垮潡娴佸叆
-            block_in_datas = self.current_data["block_in"].get(time_str)
-            if block_in_datas:
-                blocks = [x[0] for x in block_in_datas if x[1] > 0]
-                block_in_datas = blocks[:20]
-                latest_block_in_datas = block_in_datas
+                    # {"浠g爜":[(鏉垮潡浠g爜, 鏉垮潡鍚嶇О)]}
+                    limit_up_plate_names_of_refer_code = self.current_data["limit_up_plate_names_of_refer_code"]
+                    plate_codes_info = {}
+                    for x in current_limit_up_list:
+                        # 鎸夊紑鐩樺暒娑ㄥ仠鍘熷洜缁熻
+                        code = x[0]
+                        # if code not in limit_up_plate_names_of_refer_code:
+                        #     continue
+                        # 濡傛灉璁板綍娑ㄥ仠鏃堕棿杩囧幓20鍒嗛挓灏遍噰鐢ㄦ定鍋滈槦鍒楃殑娑ㄥ仠鍘熷洜
+                        if tool.trade_time_sub(time_str, tool.timestamp_format(x[2], "%H:%M:%S")) < 60 * 20 or True:
+                            plates_infos = limit_up_plate_names_of_refer_code.get(code)
+                            plates = set([d[1] for d in plates_infos if d[1] == x[5]]) if plates_infos else set()
+                        else:
+                            plates = {x[5]}
 
-            # ================褰撳墠鏃跺埢澶у崟
-            current_big_orders = self.current_data["big_order"].get(time_str)
-            if current_big_orders:
-                for big_order in current_big_orders:
-                    # 鏍煎紡 ("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))
-                    self.init_stock_variables(big_order[0], self.timeline_data, self.current_data)
-                    stock_variables: StockVariables = self.stock_variables_dict.get(big_order[0])
-                    if stock_variables.浠婃棩澶у崟鏁版嵁 is None:
-                        stock_variables.浠婃棩澶у崟鏁版嵁 = []
-                    stock_variables.浠婃棩澶у崟鏁版嵁.append(big_order[1])
-                    # 缁熻澶у崟鍧囦环
-                    order_ids = set()
-                    total_money = 0
-                    total_volume = 0
-                    for order in reversed(stock_variables.浠婃棩澶у崟鏁版嵁):
-                        if order[0] in order_ids:
-                            continue
-                        order_ids.add(order[0])
-                        total_money += order[2]
-                        total_volume += order[1]
-                    if total_volume > 0:
-                        stock_variables.浠婃棩澶у崟鍧囦环 = round(total_money / total_volume, 2)
-                    else:
-                        stock_variables.浠婃棩澶у崟鍧囦环 = 0
-            current_big_sell_orders = self.current_data["big_sell_order"].get(time_str)
-            if current_big_sell_orders:
-                for big_order in current_big_sell_orders:
-                    # 鏍煎紡 ("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))
-                    self.init_stock_variables(big_order[0], self.timeline_data, self.current_data)
-                    stock_variables: StockVariables = self.stock_variables_dict.get(big_order[0])
-                    if stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹� is None:
-                        stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹� = []
-                    stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹�.append(big_order[1])
-
-            # 寮�鐩樺暒鏈�姝f定鍋滃師鍥�
-            most_real_kpl_plate_limit_up_codes_info = {}
-            # 鑾峰彇杩欎釜鏉垮潡鐨勭洰鏍囩エ
-            if kpl_plate_limit_up_codes_info:
-                current_limit_up_dict = {x[0]: x for x in latest_current_limit_up_list}
-                codes = set()
-                for plate in kpl_plate_limit_up_codes_info:
-                    kpl_plate_codes = kpl_plate_limit_up_codes_info.get(plate)
-                    codes |= set([x[0] for x in kpl_plate_codes])
-                for code in codes:
-                    plates = code_plates.get(code)
-                    if not plates:
-                        plates = {current_limit_up_dict.get(code)[5]}
-                    plates -= constant.KPL_INVALID_BLOCKS
-                    if plates:
+                        new_plates = set()
                         for p in plates:
-                            if p not in most_real_kpl_plate_limit_up_codes_info:
-                                most_real_kpl_plate_limit_up_codes_info[p] = []
-                            most_real_kpl_plate_limit_up_codes_info[p].append(code)
+                            if p in constant.KPL_INVALID_BLOCKS:
+                                continue
+                            new_plates.add(p)
+                        for p in new_plates:
+                            if p not in plate_codes_info:
+                                plate_codes_info[p] = []
+                            plate_codes_info[p].append((x[0], x[2]))
+                    kpl_head_plate_limit_up_codes_info = plate_codes_info
 
-            if ticks:
-                for tick in ticks:
-                    code = tick["symbol"][-6:]
-                    # if code not in self.fcodes:
-                    #     continue
-                    if DEBUG_CODES and code not in DEBUG_CODES:
-                        continue
+                # ==================娉ㄥ叆鏉垮潡娴佸叆
+                block_in_datas = self.current_data["block_in"].get(time_str)
+                if block_in_datas:
+                    blocks = [x[0] for x in block_in_datas if x[1] > 0]
+                    block_in_datas = blocks[:20]
+                    latest_block_in_datas = block_in_datas
 
-                    if code not in self.stock_variables_dict:
-                        # 鍔犺浇鍩虹鏁版嵁
-                        self.init_stock_variables(code, self.timeline_data, self.current_data)
-                    stock_variables: StockVariables = self.stock_variables_dict.get(code)
-                    if plate_limit_up_codes_info is not None:
-                        stock_variables.鏉垮潡娑ㄥ仠 = plate_limit_up_codes_info
+                # ================褰撳墠鏃跺埢澶у崟
+                current_big_orders = self.current_data["big_order"].get(time_str)
+                if current_big_orders:
+                    for big_order in current_big_orders:
+                        # 鏍煎紡 ("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))
+                        self.init_stock_variables(big_order[0], self.timeline_data, self.current_data)
+                        stock_variables: StockVariables = self.stock_variables_dict.get(big_order[0])
+                        if stock_variables.浠婃棩澶у崟鏁版嵁 is None:
+                            stock_variables.浠婃棩澶у崟鏁版嵁 = []
+                        stock_variables.浠婃棩澶у崟鏁版嵁.append(big_order[1])
+                        # 缁熻澶у崟鍧囦环
+                        order_ids = set()
+                        total_money = 0
+                        total_volume = 0
+                        for order in reversed(stock_variables.浠婃棩澶у崟鏁版嵁):
+                            if order[0] in order_ids:
+                                continue
+                            order_ids.add(order[0])
+                            total_money += order[2]
+                            total_volume += order[1]
+                        if total_volume > 0:
+                            stock_variables.浠婃棩澶у崟鍧囦环 = round(total_money / total_volume, 2)
+                        else:
+                            stock_variables.浠婃棩澶у崟鍧囦环 = 0
+                current_big_sell_orders = self.current_data["big_sell_order"].get(time_str)
+                if current_big_sell_orders:
+                    for big_order in current_big_sell_orders:
+                        # 鏍煎紡 ("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))
+                        self.init_stock_variables(big_order[0], self.timeline_data, self.current_data)
+                        stock_variables: StockVariables = self.stock_variables_dict.get(big_order[0])
+                        if stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹� is None:
+                            stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹� = []
+                        stock_variables.浠婃棩鍗栧ぇ鍗曟暟鎹�.append(big_order[1])
 
-                    if kpl_plate_limit_up_codes_info is not None:
-                        stock_variables.寮�鐩樺暒鏉垮潡娑ㄥ仠 = kpl_plate_limit_up_codes_info
+                # 寮�鐩樺暒鏈�姝f定鍋滃師鍥�
+                most_real_kpl_plate_limit_up_codes_info = {}
+                # 鑾峰彇杩欎釜鏉垮潡鐨勭洰鏍囩エ
+                if kpl_plate_limit_up_codes_info:
+                    current_limit_up_dict = {x[0]: x for x in latest_current_limit_up_list}
+                    codes = set()
+                    for plate in kpl_plate_limit_up_codes_info:
+                        kpl_plate_codes = kpl_plate_limit_up_codes_info.get(plate)
+                        codes |= set([x[0] for x in kpl_plate_codes])
+                    for code in codes:
+                        plates = code_plates.get(code)
+                        if not plates:
+                            plates = {current_limit_up_dict.get(code)[5]}
+                        plates -= constant.KPL_INVALID_BLOCKS
+                        if plates:
+                            for p in plates:
+                                if p not in most_real_kpl_plate_limit_up_codes_info:
+                                    most_real_kpl_plate_limit_up_codes_info[p] = []
+                                most_real_kpl_plate_limit_up_codes_info[p].append(code)
+                if ticks:
+                    for tick in ticks:
+                        code = tick["symbol"][-6:]
+                        if code not in self.fcodes:
+                            continue
+                        if self.target_codes and code not in self.target_codes:
+                            continue
 
-                    if kpl_head_plate_limit_up_codes_info is not None:
-                        stock_variables.寮�鐩樺暒棰嗘定鏉垮潡娑ㄥ仠 = kpl_head_plate_limit_up_codes_info
+                        if code not in self.stock_variables_dict:
+                            # 鍔犺浇鍩虹鏁版嵁
+                            self.init_stock_variables(code, self.timeline_data, self.current_data)
+                        stock_variables: StockVariables = self.stock_variables_dict.get(code)
+                        if plate_limit_up_codes_info is not None:
+                            stock_variables.鏉垮潡娑ㄥ仠 = plate_limit_up_codes_info
 
-                    stock_variables.鏉垮潡鎴愪氦浠g爜 = self.deal_block_codes
-                    # 鏉垮潡娴佸叆鏁版嵁
-                    if latest_block_in_datas:
-                        stock_variables.璧勯噾娴佸叆鏉垮潡 = latest_block_in_datas
-                    # 鏆傛椂涓嶇敤鍒嗛挓K绾�
-                    # if code not in minute_bars_dict:
-                    #     minute_bars_dict[code] = [tick]
-                    # if minute_bars_dict[code][-1]["created_at"][:-2] == tick["created_at"][:-2]:
-                    #     # 缁熻鍒嗛挓K绾�
-                    #     minute_bars_dict[code][-1] = tick
-                    # else:
-                    #     # 淇濆瓨鍒嗛挓K绾挎渶楂樹环
-                    #     if not stock_variables.浠婃棩鏈�楂樹环:
-                    #         stock_variables.浠婃棩鏈�楂樹环 = minute_bars_dict[code][-1]["price"]
-                    #     if minute_bars_dict[code][-1]["price"] > stock_variables.浠婃棩鏈�楂樹环:
-                    #         stock_variables.浠婃棩鏈�楂樹环 = minute_bars_dict[code][-1]["price"]
+                        if kpl_plate_limit_up_codes_info is not None:
+                            stock_variables.寮�鐩樺暒鏉垮潡娑ㄥ仠 = kpl_plate_limit_up_codes_info
 
-                    # 淇濆瓨寮�鐩樹环
-                    if tick["created_at"][-8:] < '09:30:00':
-                        stock_variables.浠婃棩寮�鐩樹环 = tick["price"]
-                        # 浠婃棩寮�鐩樻定骞�
-                        stock_variables.浠婃棩寮�鐩樻定骞� = round((tick["price"] - stock_variables.鏄ㄦ棩鏀剁洏浠�) / stock_variables.鏄ㄦ棩鏀剁洏浠�,
-                                                       4)
-                    stock_variables.浠婃棩鎴愪氦閲� = tick["cum_volume"]
-                    stock_variables.浠婃棩鎴愪氦棰� = tick["cum_amount"]
-                    stock_variables.褰撳墠浠� = tick["price"]
-                    if not stock_variables.浠婃棩閲忓淇℃伅:
-                        if stock_variables.浠婃棩鎴愪氦閲� > stock_variables.鏄ㄦ棩鎴愪氦閲� * 0.8:
-                            stock_variables.浠婃棩閲忓淇℃伅 = (time_str, stock_variables.褰撳墠浠�, round(
-                                (stock_variables.褰撳墠浠� - stock_variables.鏄ㄦ棩鏀剁洏浠�) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2),
-                                                      self.__statistic_big_order_info(stock_variables))
-                            if VOLUME_LOG_ENABLE:
-                                # 缁熻澶у崟鍑�棰濓紝(50w浠ヤ笂,鍑�棰�,涔板崟涓暟/涔板崟鎬婚噾棰�,鍗栧崟涓暟/鍗栧崟鎬婚噾棰�)
-                                print("****閲忓", code, stock_variables.浠婃棩閲忓淇℃伅)
+                        if kpl_head_plate_limit_up_codes_info is not None:
+                            stock_variables.寮�鐩樺暒棰嗘定鏉垮潡娑ㄥ仠 = kpl_head_plate_limit_up_codes_info
 
-                    # 缁熻浠婃棩鏈�楂樹环
-                    # if stock_variables.浠婃棩鏈�楂樹环 and tick["price"] > stock_variables.浠婃棩鏈�楂樹环:
-                    #     print(code, "====绐佺牬鍒嗘椂鏈�楂樹环锛�", tick["created_at"], tick["price"])
+                        stock_variables.鏉垮潡鎴愪氦浠g爜 = self.deal_block_codes
+                        # 鏉垮潡娴佸叆鏁版嵁
+                        if latest_block_in_datas:
+                            stock_variables.璧勯噾娴佸叆鏉垮潡 = latest_block_in_datas
+                        # 鏆傛椂涓嶇敤鍒嗛挓K绾�
+                        # if code not in minute_bars_dict:
+                        #     minute_bars_dict[code] = [tick]
+                        # if minute_bars_dict[code][-1]["created_at"][:-2] == tick["created_at"][:-2]:
+                        #     # 缁熻鍒嗛挓K绾�
+                        #     minute_bars_dict[code][-1] = tick
+                        # else:
+                        #     # 淇濆瓨鍒嗛挓K绾挎渶楂樹环
+                        #     if not stock_variables.浠婃棩鏈�楂樹环:
+                        #         stock_variables.浠婃棩鏈�楂樹环 = minute_bars_dict[code][-1]["price"]
+                        #     if minute_bars_dict[code][-1]["price"] > stock_variables.浠婃棩鏈�楂樹环:
+                        #         stock_variables.浠婃棩鏈�楂樹环 = minute_bars_dict[code][-1]["price"]
 
-                    if not stock_variables.浠婃棩鏈�楂樹环淇℃伅 or tick["price"] > stock_variables.浠婃棩鏈�楂樹环淇℃伅[0]:
-                        stock_variables.浠婃棩鏈�楂樹环淇℃伅 = (tick["price"], time_str)
+                        # 淇濆瓨寮�鐩樹环
+                        if tick["created_at"][-8:] < '09:30:00':
+                            stock_variables.浠婃棩寮�鐩樹环 = tick["price"]
+                            # 浠婃棩寮�鐩樻定骞�
+                            stock_variables.浠婃棩寮�鐩樻定骞� = round(
+                                (tick["price"] - stock_variables.鏄ㄦ棩鏀剁洏浠�) / stock_variables.鏄ㄦ棩鏀剁洏浠�,
+                                4)
+                        stock_variables.浠婃棩鎴愪氦閲� = tick["cum_volume"]
+                        stock_variables.浠婃棩鎴愪氦棰� = tick["cum_amount"]
+                        stock_variables.褰撳墠浠� = tick["price"]
+                        if not stock_variables.浠婃棩閲忓淇℃伅:
+                            if stock_variables.浠婃棩鎴愪氦閲� > stock_variables.鏄ㄦ棩鎴愪氦閲� * 0.8:
+                                stock_variables.浠婃棩閲忓淇℃伅 = (time_str, stock_variables.褰撳墠浠�, round(
+                                    (stock_variables.褰撳墠浠� - stock_variables.鏄ㄦ棩鏀剁洏浠�) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2),
+                                                          self.__statistic_big_order_info(stock_variables))
+                                if VOLUME_LOG_ENABLE:
+                                    # 缁熻澶у崟鍑�棰濓紝(50w浠ヤ笂,鍑�棰�,涔板崟涓暟/涔板崟鎬婚噾棰�,鍗栧崟涓暟/鍗栧崟鎬婚噾棰�)
+                                    print("****閲忓", code, stock_variables.浠婃棩閲忓淇℃伅)
 
-                    if not stock_variables.浠婃棩鏈�浣庝环 or tick["price"] < stock_variables.浠婃棩鏈�浣庝环:
-                        stock_variables.浠婃棩鏈�浣庝环 = tick["price"]
+                        # 缁熻浠婃棩鏈�楂樹环
+                        # if stock_variables.浠婃棩鏈�楂樹环 and tick["price"] > stock_variables.浠婃棩鏈�楂樹环:
+                        #     print(code, "====绐佺牬鍒嗘椂鏈�楂樹环锛�", tick["created_at"], tick["price"])
 
-                    stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = most_real_kpl_plate_limit_up_codes_info
+                        if not stock_variables.浠婃棩鏈�楂樹环淇℃伅 or tick["price"] > stock_variables.浠婃棩鏈�楂樹环淇℃伅[0]:
+                            stock_variables.浠婃棩鏈�楂樹环淇℃伅 = (tick["price"], time_str)
 
-                    # compute_result = self.__run_backtest(code, stock_variables)
-                    # self.__process_test_result(code, stock_variables, next_trade_day, stock_variables.褰撳墠浠�,
-                    #                            time_str, compute_result)
+                        if not stock_variables.浠婃棩鏈�浣庝环 or tick["price"] < stock_variables.浠婃棩鏈�浣庝环:
+                            stock_variables.浠婃棩鏈�浣庝环 = tick["price"]
+                        if most_real_kpl_plate_limit_up_codes_info:
+                            stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = most_real_kpl_plate_limit_up_codes_info
 
-                    # if len(real_codes) >= 2 and time_str > '09:30:00':
-                    #     # print(time_str, plate)
-                    #     # 鎵捐繖涓澘鍧楅娑ㄦ鏁版渶澶氱殑绁�
-                    #     codes_infos = target_plate_codes_infos.get(plate)
-                    #     if codes_infos:
-                    #         for code_info in codes_infos:
-                    #             code = code_info[0]
-                    #             self.init_stock_variables(code, self.timeline_data, self.current_data)
-                    #             stock_variables: StockVariables = self.stock_variables_dict.get(code)
-                    #             compute_result = self.__run_backtest(code, stock_variables)
-                    #             if compute_result[0] and plate not in all_new_plates:
-                    #                 all_new_plates.add(plate)
-                    #                 print(plate, time_str, code_info, real_codes)
-                    #             else:
-                    #                 pass
+                        # 璁$畻娑ㄩ��, 涓婁竴涓猼ick
+                        if stock_variables.涓婁釜tick and stock_variables.涓婁釜tick['price'] > 0:
+                            try:
+                                time_space = tool.trade_time_sub(time_str,
+                                                                 stock_variables.涓婁釜tick["created_at"][-8:]) // 3
+                                if time_space > 0:
+                                    rate = (tick['price'] - stock_variables.涓婁釜tick[
+                                        'price']) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠� / time_space
+                                    stock_variables.娑ㄩ�� = round(rate, 2)
+                            except:
+                                print("")
 
-            # 澶у崟椹卞姩
-            if current_big_orders and time_str >= '09:30:00':
-                for big_order in current_big_orders:
-                    code = big_order[0]
-                    if code not in self.fcodes:
-                        continue
-                    self.init_stock_variables(code, self.timeline_data, self.current_data)
-                    stock_variables: StockVariables = self.stock_variables_dict.get(code)
-                    if plate_limit_up_codes_info is not None:
-                        stock_variables.鏉垮潡娑ㄥ仠 = plate_limit_up_codes_info
+                        if stock_variables.娑ㄩ�� >= 0.8:
+                            if code in self.target_codes:
+                                print(time_str, code, f"蹇�熸媺鍗囷細{stock_variables.娑ㄩ�焳",f"浠g爜鏉垮潡锛歿stock_variables.浠g爜鏉垮潡}", f"鍙拱鏉垮潡锛歿latest_can_buy_plates}")
+                            # 鍑嗗鏁版嵁
+                            if plate_limit_up_codes_info is not None:
+                                stock_variables.鏉垮潡娑ㄥ仠 = plate_limit_up_codes_info
 
-                    if kpl_plate_limit_up_codes_info is not None:
-                        stock_variables.寮�鐩樺暒鏉垮潡娑ㄥ仠 = kpl_plate_limit_up_codes_info
+                            if kpl_plate_limit_up_codes_info is not None:
+                                stock_variables.寮�鐩樺暒鏉垮潡娑ㄥ仠 = kpl_plate_limit_up_codes_info
 
-                    if kpl_head_plate_limit_up_codes_info is not None:
-                        stock_variables.寮�鐩樺暒棰嗘定鏉垮潡娑ㄥ仠 = kpl_head_plate_limit_up_codes_info
+                            if kpl_head_plate_limit_up_codes_info is not None:
+                                stock_variables.寮�鐩樺暒棰嗘定鏉垮潡娑ㄥ仠 = kpl_head_plate_limit_up_codes_info
 
-                    if most_real_kpl_plate_limit_up_codes_info is not None:
-                        stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = most_real_kpl_plate_limit_up_codes_info
+                            if most_real_kpl_plate_limit_up_codes_info is not None:
+                                stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = most_real_kpl_plate_limit_up_codes_info
 
-                    if block_in_datas:
-                        stock_variables.璧勯噾娴佸叆鏉垮潡 = block_in_datas
-                    compute_result = self.__run_backtest(code, stock_variables)
-                    # print(compute_result)
-                    self.__process_test_result(code, stock_variables, next_trade_day, big_order[1][4],
-                                               huaxin_util.convert_time(big_order[1][3]), compute_result)
+                            if block_in_datas:
+                                stock_variables.璧勯噾娴佸叆鏉垮潡 = block_in_datas
 
-        print("鍙拱棰樻潗锛�", all_new_plates)
+                            stock_variables.鍙互涔扮殑鏉垮潡 = latest_can_buy_plates
+                            try:
+                                compute_result = self.__run_backtest(code, stock_variables)
+                                # print(compute_result)
+                                self.__process_test_result(code, stock_variables, next_trade_day, stock_variables.褰撳墠浠�,
+                                                           time_str, compute_result)
+                            except Exception as e:
+                                print(time_str)
+                                logging.exception(e)
+                        stock_variables.涓婁釜tick = tick
+
+            print("鍙拱棰樻潗锛�", all_new_plates)
+        finally:
+            self.finish = True
 
     def __process_test_result(self, code, stock_variables: StockVariables, next_trade_day, buy_price, time_str,
                               compute_result):
 
         # if code == '000628':
         #     print(time_str, code, compute_result)
+        # (鏃堕棿,(浠g爜,浠g爜鍚嶇О), 娑ㄥ箙 , 涔板叆缁撴灉)
+        backtest_result = [time_str, (code, gpcode_manager.get_code_name(code)),
+                           round((buy_price - stock_variables.鏄ㄦ棩鏀剁洏浠�) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2),
+                           compute_result]
 
-        if not compute_result[0]:
-            if code in DEBUG_CODES:
-                print(time_str, code, compute_result[1])
-            # if compute_result[1].find("澶у崟") >= 0 or compute_result[1].find("浠锋牸瓒呰繃鏄ㄦ棩鏈�浣庝环") >= 0:
-            pass
+        try:
+            if not compute_result[0]:
+                if code in self.target_codes:
+                    print(time_str, code, compute_result[1])
+                # if compute_result[1].find("澶у崟") >= 0 or compute_result[1].find("浠锋牸瓒呰繃鏄ㄦ棩鏈�浣庝环") >= 0:
+                pass
 
-        # print(code, time_str,stock_variables.浠g爜鏉垮潡, compute_result)
+            # print(code, time_str,stock_variables.浠g爜鏉垮潡, compute_result)
 
-        if compute_result[0] and code not in self.deal_codes:
-            # 鏈�澶氫拱5涓�
-            if len(self.deal_codes) >= 100:
-                return
-            # if huaxin_util.convert_time(big_order[1][3]) >= "10:30:00" and len(deal_codes) > 0:
-            #     break
-            self.deal_codes.add(code)
-            next_k_bars = self.data_loader.load_kline_data_by_day_and_code(next_trade_day, code)
-            current_k_bars = self.data_loader.load_kline_data_by_day_and_code(self.data_loader.now_day,
-                                                                              code)
-            if next_k_bars and buy_price:
-                t_rate = round((next_k_bars[0]["open"] - buy_price) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)
-                t_rate = f"{t_rate}%"
-            else:
-                # 鑾峰彇褰撳墠鐨則ick绾�
-                if self.data_loader.now_day >= next_trade_day:
-                    ticks = self.data_loader.jueJinLocalApi.get_history_tick_n(code, 1, frequency='tick',
-                                                                               end_date=f"{next_trade_day} 09:30:03")
-                else:
-                    ticks = None
-                if ticks:
-                    t_rate = round((ticks[-1]["price"] - buy_price) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)
+            if compute_result[0] and code not in self.deal_codes:
+                # 鏈�澶氫拱5涓�
+                if len(self.deal_codes) >= 100:
+                    return
+                # if huaxin_util.convert_time(big_order[1][3]) >= "10:30:00" and len(deal_codes) > 0:
+                #     break
+                self.deal_codes.add(code)
+                next_k_bars = self.data_loader.load_kline_data_by_day_and_code(next_trade_day, code)
+                current_k_bars = self.data_loader.load_kline_data_by_day_and_code(self.data_loader.now_day,
+                                                                                  code)
+                if next_k_bars and buy_price:
+                    t_rate = round((next_k_bars[0]["open"] - buy_price) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)
                     t_rate = f"{t_rate}%"
                 else:
-                    t_rate = "鏈煡"
-            if current_k_bars and buy_price:
-                c_rate = round((current_k_bars[0]["close"] - buy_price) * 100 / current_k_bars[0]["pre_close"], 2)
-                c_rate = f"{c_rate}%"
-            else:
-                # 鎷夊彇褰撴棩K绾�
-                if tool.get_now_date_str() == self.data_loader.now_day and buy_price:
-                    tick = self.data_loader.jueJinLocalApi.get_history_tick_n(code, 1, frequency='tick',
-                                                                              end_date=f"{self.data_loader.now_day} {tool.get_now_time_str()}")
-                    c_rate = round((tick[0]["price"] - buy_price) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)
-                else:
-                    bar = self.data_loader.jueJinLocalApi.get_history_tick_n(code, 1,
-                                                                             end_date=f"{self.data_loader.now_day} 15:00:00")
-                    if bar:
-                        c_rate = round((bar[0]["close"] - buy_price) * 100 / bar[0]["pre_close"], 2)
+                    # 鑾峰彇褰撳墠鐨則ick绾�
+                    if self.data_loader.now_day >= next_trade_day:
+                        ticks = self.data_loader.jueJinLocalApi.get_history_tick_n(code, 1, frequency='tick',
+                                                                                   end_date=f"{next_trade_day} 09:30:03")
                     else:
-                        c_rate = "鏈煡"
-            print(f"{len(self.deal_codes)}==鍥炴祴缁撴灉锛�", code, gpcode_manager.CodesNameManager().get_code_name(code),
-                  f"婧环鐜囷細{t_rate},褰撴棩鐩堜簭锛歿c_rate}锛屼笅鍗曟椂闂达細{time_str}锛屾定骞咃細{round((buy_price - stock_variables.鏄ㄦ棩鏀剁洏浠�) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)}",
-                  compute_result[1],
-                  compute_result[2])
-            for b in compute_result[3]:
-                if b not in self.deal_block_codes:
-                    self.deal_block_codes[b] = set()
-                self.deal_block_codes[b].add(code)
-            stock_variables.鏉垮潡鎴愪氦浠g爜 = self.deal_block_codes
+                        ticks = None
+                    if ticks:
+                        t_rate = round((ticks[-1]["price"] - buy_price) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)
+                        t_rate = f"{t_rate}%"
+                    else:
+                        t_rate = "鏈煡"
+                if current_k_bars and buy_price:
+                    c_rate = round((current_k_bars[0]["close"] - buy_price) * 100 / current_k_bars[0]["pre_close"], 2)
+                    c_rate = f"{c_rate}%"
+                else:
+                    # 鎷夊彇褰撴棩K绾�
+                    if tool.get_now_date_str() == self.data_loader.now_day and buy_price:
+                        tick = self.data_loader.jueJinLocalApi.get_history_tick_n(code, 1, frequency='tick',
+                                                                                  end_date=f"{self.data_loader.now_day} {tool.get_now_time_str()}")
+                        c_rate = round((tick[0]["price"] - buy_price) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)
+                    else:
+                        bar = self.data_loader.jueJinLocalApi.get_history_tick_n(code, 1,
+                                                                                 end_date=f"{self.data_loader.now_day} 15:00:00")
+                        if bar:
+                            c_rate = round((bar[0]["close"] - buy_price) * 100 / bar[0]["pre_close"], 2)
+                        else:
+                            c_rate = "鏈煡"
+                backtest_result.append(c_rate)
+                backtest_result.append(t_rate)
+                print(f"{len(self.deal_codes)}==鍥炴祴缁撴灉锛�", code, gpcode_manager.CodesNameManager().get_code_name(code),
+                      f"婧环鐜囷細{t_rate},褰撴棩鐩堜簭锛歿c_rate}锛屼笅鍗曟椂闂达細{time_str}锛屾定骞咃細{round((buy_price - stock_variables.鏄ㄦ棩鏀剁洏浠�) * 100 / stock_variables.鏄ㄦ棩鏀剁洏浠�, 2)}",
+                      compute_result[1],
+                      compute_result[2])
+                for b in compute_result[3]:
+                    if b not in self.deal_block_codes:
+                        self.deal_block_codes[b] = set()
+                    self.deal_block_codes[b].add(code)
+                stock_variables.鏉垮潡鎴愪氦浠g爜 = self.deal_block_codes
+
+        finally:
+            self.backtest_results.append(backtest_result)
 
 
-# DEBUG_CODES = ['002365', '000953', '002907', '002688', '003020', '002900', '002082', '000566', '300204', '002317']
-DEBUG_CODES = []
+# 閿傜數姹� ['002882', '002667', '002846', '300530', '002074', '301662', '002580', '300584', '603399', '601515']
+# 鍖栧伐 ['600610', '002427', '002165', '002809', '000565', '002365', '603192', '600370', '600800', '603188']
 
 VOLUME_LOG_ENABLE = False
 # 澶囩敤澶у崟
@@ -779,16 +1118,24 @@
 
 if __name__ == "__main__":
     back_test_dict = {}
-    # days = ["2025-05-06", "2025-05-07", "2025-05-08", "2025-05-09", "2025-05-12", "2025-05-13", "2025-05-14",
-    #         "2025-05-15", "2025-05-16", "2025-05-19", "2025-05-20",  "2025-05-21", "2025-05-22"]
     days = ["2025-05-12", "2025-05-13", "2025-05-14", "2025-05-15", "2025-05-16", "2025-05-19", "2025-05-20",
             "2025-05-21", "2025-05-22", "2025-05-23", "2025-05-26", "2025-05-27", "2025-05-28", "2025-05-29",
             "2025-05-30", "2025-06-03", "2025-06-04", "2025-06-05", "2025-06-06", "2025-06-09", "2025-06-10"]
+    days = ["2025-06-03", "2025-06-04", "2025-06-05", "2025-06-06", "2025-06-09", "2025-06-10",
+            "2025-06-11", "2025-06-12", "2025-06-13", "2025-06-16", "2025-06-17", "2025-06-18", "2025-06-19",
+            "2025-06-20", "2025-06-23", "2025-06-24", "2025-06-25", "2025-06-26", "2025-06-27", "2025-06-30",
+            "2025-07-01", "2025-07-02", "2025-07-03", "2025-07-04"]
+
+    days = ["2025-07-04"]
+    #
+    # days = ["2025-05-12", "2025-05-13", "2025-05-14", "2025-05-15", "2025-05-16", "2025-05-19", "2025-05-20",
+    #         "2025-05-21", "2025-05-22", "2025-05-23", "2025-05-26"]
+
     days.reverse()
     for day in days:
         if day not in back_test_dict:
             # back_test_dict[day] = BackTest(day, "浠婃棩閲忔槸鍚﹁冻澶�.py")
-            back_test_dict[day] = BackTest(day, "浣庡惛鑴氭湰_杈ㄨ瘑搴v6.py")
+            back_test_dict[day] = BackTest(day, "strategy_script_v7.py", target_codes={})
         print("=========================", day)
         # back_test_dict[day].run_volume()
-        back_test_dict[day].run()
+        back_test_dict[day].run_v2()

--
Gitblit v1.8.0