From ab662be5c523b75c1bd28fc6bfcab2872b9623b3 Mon Sep 17 00:00:00 2001
From: Administrator <admin@example.com>
Date: 星期四, 12 六月 2025 15:22:06 +0800
Subject: [PATCH] bug修复

---
 strategy/strategy_manager.py |  387 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 387 insertions(+), 0 deletions(-)

diff --git a/strategy/strategy_manager.py b/strategy/strategy_manager.py
new file mode 100644
index 0000000..c2c8ca5
--- /dev/null
+++ b/strategy/strategy_manager.py
@@ -0,0 +1,387 @@
+"""
+绛栫暐绠$悊
+"""
+import json
+
+from code_attribute import gpcode_manager, code_nature_analyse
+from db import redis_manager_delegate as redis_manager
+from db.mysql_data_delegate import Mysqldb
+from db.redis_manager_delegate import RedisUtils
+from strategy.data_analyzer import KPLLimitUpDataAnalyzer
+from strategy.low_suction_strategy import LowSuctionOriginDataExportManager
+from strategy.strategy_params_settings import StrategyParamsSettingsManager
+from strategy.strategy_variable import StockVariables
+from strategy.strategy_variable_factory import DataLoader, StrategyVariableFactory
+import constant
+from third_data import kpl_util
+from trade.trade_manager import DealCodesManager
+from utils import huaxin_util, tool
+
+
+@tool.singleton
+class TickSummaryDataManager:
+    """
+    Tick姒傝鏁版嵁
+    """
+    __db = 13
+
+    # 鎴愪氦浠g爜鐨勮鍗曚俊鎭細{浠g爜:{浜ゆ槗id:(閲忥紝浠锋牸锛岀郴缁熻鍗曞彿)}}
+
+    def __init__(self):
+        # 寮�鐩樹环淇℃伅
+        self.open_price_info_dict = {}
+        # 鏈�浣庝环
+        self.low_price_dict = {}
+        # 鏈�楂樹环
+        self.high_price_info_dict = {}
+
+        self.musql = Mysqldb()
+        self.redis_manager = redis_manager.RedisManager(self.__db)
+        self.__load_data()
+
+    def __get_redis(self):
+        return self.redis_manager.getRedis()
+
+    def __load_data(self):
+        keys = RedisUtils.keys(self.__get_redis(), "tick_open_price_info-*")
+        if keys:
+            for k in keys:
+                code = k.split("-")[1]
+                val = RedisUtils.get(self.__get_redis(), k)
+                if val:
+                    self.open_price_info_dict[code] = json.loads(val)
+        keys = RedisUtils.keys(self.__get_redis(), "tick_high_price-*")
+        if keys:
+            for k in keys:
+                code = k.split("-")[1]
+                val = RedisUtils.get(self.__get_redis(), k)
+                if val:
+                    self.high_price_info_dict[code] = json.loads(val)
+
+        keys = RedisUtils.keys(self.__get_redis(), "tick_low_price-*")
+        if keys:
+            for k in keys:
+                code = k.split("-")[1]
+                val = RedisUtils.get(self.__get_redis(), k)
+                if val:
+                    self.low_price_dict[code] = round(float(val))
+
+    def set_open_price_info(self, code, info):
+        """
+        璁剧疆寮�鐩樹俊鎭�
+        @param code:
+        @param info:
+        @return:
+        """
+        self.open_price_info_dict[code] = info
+        RedisUtils.setex_async(self.__db, f"tick_open_price_info-{code}", tool.get_expire(), json.dumps(info))
+
+    def set_high_price_info(self, code, info):
+        """
+        璁剧疆鏈�楂樹环
+        @param code:
+        @param info:(浠锋牸, 鏃堕棿)
+        @return:
+        """
+        self.high_price_info_dict[code] = info
+        RedisUtils.setex_async(self.__db, f"tick_high_price-{code}", tool.get_expire(), json.dumps(info))
+
+    def set_low_price(self, code, price):
+        """
+        璁剧疆鏈�浣庝环
+        @param code:
+        @param price:
+        @return:
+        """
+        self.low_price_dict[code] = price
+        RedisUtils.setex_async(self.__db, f"tick_low_price-{code}", tool.get_expire(), price)
+
+
+class LowSuctionStrategy:
+    """
+    浣庡惛绛栫暐
+    """
+    def __init__(self, day, script_name="strategy_script_v6.py", settings=StrategyParamsSettingsManager().get_settings()):
+        self.now_day = day
+        # 涔板ぇ鍗曪細{浠g爜:[澶у崟鏁版嵁]}
+        self.big_order_buy = {}
+        # 鍗栧ぇ鍗�
+        self.big_order_sell = {}
+        # 鑷敱娴侀�氶噺
+        self.zylt_volume_dict = {}
+        # 鍘嗗彶鏃鏁版嵁
+        self.kline_data = {}
+        # 鍘嗗彶娑ㄥ仠鏁版嵁
+        self.limit_up_record_data = {}
+        # 鍘嗗彶鏁版嵁
+        self.timeline_data = {}
+        # 浠婃棩鏁版嵁
+        self.current_data = {}
+        # 鐩爣浠g爜鐨勬澘鍧�
+        self.code_plates_for_buy = {}
+        # 浠g爜鐨勬澘鍧楋紙甯歌锛�
+        self.code_plates = {}
+        # 涓嬩竴涓氦鏄撴棩
+        self.next_trade_day = None
+        # 鐩爣浠g爜
+        self.fcodes = set()
+        # 鍙橀噺瀵硅薄
+        self.stock_variables_dict = {}
+        # 褰撳墠娑ㄥ仠鍒楄〃
+        self.current_limit_up_list = []
+        # 褰撳墠娑ㄥ仠鐨勬澘鍧楁墍鍖呭惈鐨勪唬鐮�
+        self.current_limit_up_plate_codes = {}
+        # 褰撳墠鏉垮潡鍑�娴佸叆
+        self.current_block_in_datas = []
+
+        # 鍔犺浇绛栫暐鑴氭湰鏂囦欢
+        with open(script_name if constant.is_windows() else f'{constant.get_path_prefix()}/{script_name}', mode='r', encoding='utf-8') as f:
+            lines = f.readlines()
+            scripts = "\n".join(lines)
+            # 娉ㄩ噴鎺夐噷闈㈢殑import涓庡彉閲�
+            scripts = scripts.replace("from ", "#from ").replace("sv = ", "#sv =  ").replace("settings = ",
+                                                                                             "#settings =  ").replace(
+                "target_code = ", "#target_code =  ")
+
+            self.scripts = scripts
+        self.settings = settings
+
+        self.data_loader = DataLoader(self.now_day, cache_path=f"{constant.get_path_prefix()}/datas")
+        self.__LowSuctionOriginDataExportManager = LowSuctionOriginDataExportManager(self.now_day)
+        self.load_data()
+
+    def load_data(self):
+        # 鍔犺浇鍘嗗彶鏁版嵁
+        self.__load_before_date_data_by_timeline()
+        self.__load_current_date_data_by_timeline()
+        self.fcodes = set(self.code_plates_for_buy.keys()) & set(self.kline_data.keys())
+
+    def __load_before_date_data_by_timeline(self):
+        """
+        鍔犺浇鍥炴祴鏃ユ湡涔嬪墠鐨凨绾挎暟鎹笌鍘嗗彶娑ㄥ仠鏁版嵁
+        :return: 鎸夋椂闂存帓搴忕殑鏁版嵁鍒楄〃
+        """
+        trade_days = self.data_loader.trade_days
+        # 鍔犺浇鍘嗗彶鏁版嵁
+        self.kline_data = self.data_loader.load_kline_data()
+        self.limit_up_record_data = self.data_loader.load_limit_up_data()
+        self.next_trade_day = self.data_loader.load_next_trade_day()
+        if not trade_days:
+            raise Exception("浜ゆ槗鏃ュ巻鑾峰彇澶辫触")
+        if not self.kline_data:
+            raise Exception("鍘嗗彶鏃鑾峰彇澶辫触")
+        if not self.limit_up_record_data:
+            raise Exception("鍘嗗彶娑ㄥ仠鑾峰彇澶辫触")
+
+    def __load_current_date_data_by_timeline(self):
+        """
+        鍔犺浇鍥炴祴鏃ユ湡褰撳ぉ鐨勬暟鎹紝灏嗚繖浜涙暟鎹牴鎹鍒囩墖
+        :param day: 鏃ユ湡锛屾牸寮忎负"YYYY-MM-DD
+        :return: 鎸夋椂闂存帓搴忕殑鏁版嵁鍒楄〃
+        """
+        IS_BY_BIG_ORDER = False
+        BIG_ORDER_MONEY_THRESHOLD = 200e4
+        big_order_deals = self.__LowSuctionOriginDataExportManager.export_big_order_deal(BIG_ORDER_MONEY_THRESHOLD)
+        if not big_order_deals or IS_BY_BIG_ORDER:
+            big_order_deals = self.__LowSuctionOriginDataExportManager.export_big_order_deal_by(
+                BIG_ORDER_MONEY_THRESHOLD)
+        self.big_order_buy = big_order_deals
+        # 杞崲鏍煎紡涓猴細{鏃堕棿: [("浠g爜", (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环))]
+
+        big_sell_order_deals = self.__LowSuctionOriginDataExportManager.export_big_sell_order_deal(
+            BIG_ORDER_MONEY_THRESHOLD)
+        if not big_sell_order_deals or IS_BY_BIG_ORDER:
+            big_sell_order_deals = self.__LowSuctionOriginDataExportManager.export_big_sell_order_deal_by(
+                BIG_ORDER_MONEY_THRESHOLD)
+        self.big_order_sell = big_sell_order_deals
+        # 鍔犺浇鑷敱娴侀�氶噺
+        self.zylt_volume_dict = self.__LowSuctionOriginDataExportManager.export_zylt_volume()
+
+        # 鍔犺浇鏉垮潡浠g爜
+        code_plates_dict = self.__LowSuctionOriginDataExportManager.export_code_plates()
+
+        plate_codes = self.data_loader.load_target_plate_and_codes()
+        code_plates_dict_for_buy = {}
+        for p in plate_codes:
+            for code in plate_codes.get(p):
+                if code not in code_plates_dict_for_buy:
+                    code_plates_dict_for_buy[code] = set()
+                code_plates_dict_for_buy[code].add(p)
+        self.code_plates_for_buy = code_plates_dict_for_buy
+        self.code_plates = code_plates_dict
+
+        if not self.zylt_volume_dict:
+            raise Exception("鏃犺嚜鐢辨祦閫氭暟鎹�")
+        if not self.code_plates:
+            raise Exception("鏃犳澘鍧楁暟鎹�")
+        if not self.code_plates_for_buy:
+            raise Exception("鏃犵洰鏍囩エ鐨勪拱鍏ユ暟鎹�")
+
+    def __init_stock_variables(self, code_):
+        """
+        鍒濆鍖栧彉閲�
+        @param code_:
+        @return:
+        """
+        if code_ in self.stock_variables_dict:
+            return
+
+        stock_variables = StrategyVariableFactory.create_from_history_data(
+            self.kline_data.get(code_), None,
+            self.limit_up_record_data.get(code_), self.data_loader.trade_days)
+
+        # 鍔犺浇浠婃棩娑ㄥ仠浠�
+        pre_close = self.kline_data.get(code_)[0]["close"]
+        stock_variables.浠婃棩娑ㄥ仠浠� = round(float(gpcode_manager.get_limit_up_price_by_preprice(code_, pre_close)), 2)
+        stock_variables.鑷敱娴侀�氬競鍊� = self.zylt_volume_dict.get(code_) * pre_close
+        # 鑾峰彇浠g爜鏉垮潡
+        stock_variables.浠g爜鏉垮潡 = self.code_plates_for_buy.get(code_)
+        is_price_too_high = code_nature_analyse.is_price_too_high_in_days(code_, self.kline_data.get(code_),
+                                                                          stock_variables.浠婃棩娑ㄥ仠浠�)
+        stock_variables.鍏釜浜ゆ槗鏃ユ定骞呰繃楂� = is_price_too_high[0]
+        stock_variables.杈ㄨ瘑搴︿唬鐮� = self.fcodes
+        for day in [2, 5, 10, 30, 60, 120]:
+            days = self.data_loader.trade_days[:day]
+            stock_variables.__setattr__(f"鏃ュ嚭鐜扮殑鏉垮潡_{day}",
+                                        KPLLimitUpDataAnalyzer.get_limit_up_reasons(
+                                            self.limit_up_record_data, min_day=days[-1],
+                                            max_day=days[0]))
+        stock_variables.杩炵画鑰侀鏉� = KPLLimitUpDataAnalyzer.get_continuous_limit_up_reasons(
+            self.limit_up_record_data, self.data_loader.trade_days[:2])
+
+        # 鍔犺浇Tick淇℃伅
+        open_price_info = TickSummaryDataManager().open_price_info_dict.get(code_)
+        if open_price_info:
+            stock_variables.浠婃棩寮�鐩樹环 = open_price_info[0]
+            stock_variables.浠婃棩寮�鐩樻定骞� = open_price_info[1]
+        high_price_info = TickSummaryDataManager().high_price_info_dict.get(code_)
+        if high_price_info:
+            stock_variables.浠婃棩鏈�楂樹环淇℃伅 = high_price_info
+
+        low_price = TickSummaryDataManager().low_price_dict.get(code_)
+        if low_price:
+            stock_variables.浠婃棩鏈�浣庝环 = low_price
+        self.stock_variables_dict[code_] = stock_variables
+
+    def add_big_orders(self, big_orders):
+        """
+        娣诲姞澶у崟
+        @param big_orders: [(浠g爜, 涔�/鍗�, [璁㈠崟鍙�,閲�,閲戦,鏈�鍚庢椂闂存埑,鏈�鍚庝环鏍�, 鍒濆鏃堕棿鎴�, 鍒濆浠锋牸])] 濡傦細[ ('002741', 0, [475820, 91600, 1610328, 92500000, 17.58, 92500000, 17.58])]
+        @return:
+        """
+        for d in big_orders:
+            code = d[0]
+            if d[1] == 0:
+                # 涔板崟
+                if code not in self.big_order_buy:
+                    self.big_order_buy[code] = []
+                self.big_order_buy[code].append(d[2])
+            else:
+                # 鍗栧崟
+                if code not in self.big_order_sell:
+                    self.big_order_sell[code] = []
+                self.big_order_sell[code].append(d[2])
+        # 椹卞姩涓嬪崟
+
+    def add_ticks(self, ticks):
+        """
+        娣诲姞tick鏁版嵁
+        @param ticks:
+        @return:
+        """
+        fticks = [tick for tick in ticks if tick[0] in self.fcodes]
+        # 鍒濆鍖栧璞�
+        for tick in fticks:
+            code = tick[0]
+            self.__init_stock_variables(code)
+            stock_variables = self.stock_variables_dict.get(code)
+
+            # (浠g爜, 鏃堕棿鎴�, 浠锋牸, 鎬讳氦鏄撻噺, 鎬讳氦鏄撻, 涔�5, 鍗�5)
+            code, time_str, price, cum_volume, cum_amount, buy_5 = tick[0], huaxin_util.convert_time(tick[1]), tick[2], \
+                                                                   tick[
+                                                                       3], tick[4], tick[5]
+
+            # 璁$畻tick鏁版嵁鐨勫��
+            if time_str < '09:30:00':
+                if price > 0:
+                    stock_variables.浠婃棩寮�鐩樹环 = price
+                else:
+                    stock_variables.浠婃棩寮�鐩樹环 = buy_5[0][0]
+                    # 浠婃棩寮�鐩樻定骞�
+                stock_variables.浠婃棩寮�鐩樻定骞� = round((stock_variables.浠婃棩寮�鐩樹环 - stock_variables.鏄ㄦ棩鏀剁洏浠�) / stock_variables.鏄ㄦ棩鏀剁洏浠�,
+                                               4)
+                TickSummaryDataManager().set_open_price_info(code, (stock_variables.浠婃棩寮�鐩樹环, stock_variables.浠婃棩寮�鐩樻定骞�))
+            stock_variables.浠婃棩鎴愪氦閲� = cum_volume
+            stock_variables.浠婃棩鎴愪氦棰� = cum_amount
+            stock_variables.褰撳墠浠� = price
+            if not stock_variables.浠婃棩鏈�楂樹环淇℃伅 or price > stock_variables.浠婃棩鏈�楂樹环淇℃伅[0]:
+                stock_variables.浠婃棩鏈�楂樹环淇℃伅 = (price, time_str)
+                TickSummaryDataManager().set_high_price_info(code, stock_variables.浠婃棩鏈�楂樹环淇℃伅)
+            if not stock_variables.浠婃棩鏈�浣庝环 or price < stock_variables.浠婃棩鏈�浣庝环:
+                stock_variables.浠婃棩鏈�浣庝环 = price
+                TickSummaryDataManager().set_low_price(code, stock_variables.浠婃棩鏈�浣庝环)
+
+    def add_limit_up_list(self, limit_up_list):
+        """
+        娑ㄥ仠鍒楄〃鏁版嵁
+        @param limit_up_list:
+        @return:
+        """
+        self.current_limit_up_list = limit_up_list
+        current_limit_up_list = [x for x in limit_up_list if kpl_util.get_high_level_count(x[4]) < 3]
+        most_real_kpl_plate_limit_up_codes_info = {}
+        current_limit_up_dict = {x[0]: x for x in current_limit_up_list}
+        codes = set(current_limit_up_dict.keys())
+        for code in codes:
+            plates = self.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)
+        self.current_limit_up_plate_codes = most_real_kpl_plate_limit_up_codes_info
+
+    def add_block_in(self, block_in_datas):
+        """
+        娣诲姞鏉垮潡鍑�娴佸叆
+        @param block_in_datas:
+        @return:
+        """
+        blocks = [x[0] for x in block_in_datas if x[1] > 0]
+        _block_in_datas = blocks[:20]
+        self.current_block_in_datas = _block_in_datas
+
+    def __run(self, code, sv: StockVariables):
+        # 杩愯浠g爜
+        # 娉ㄥ叆澶у崟
+        sv.浠婃棩澶у崟鏁版嵁 = self.big_order_buy.get(code)
+        sv.浠婃棩鍗栧ぇ鍗曟暟鎹� = self.big_order_sell.get(code)
+        # 娉ㄥ叆鏉垮潡娑ㄥ仠浠g爜
+        sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = self.current_limit_up_plate_codes
+        # 娉ㄥ叆鏉垮潡娴佸叆淇℃伅
+        if self.current_block_in_datas:
+            sv.璧勯噾娴佸叆鏉垮潡 = self.current_block_in_datas
+        # 娉ㄥ叆宸叉垚浜や唬鐮�
+        place_order_plate_codes = DealCodesManager().get_place_order_plate_codes()
+        sv.鏉垮潡鎴愪氦浠g爜 = place_order_plate_codes
+        sv.鎴愪氦浠g爜 = DealCodesManager().get_deal_codes()
+        global_dict = {
+            "sv": sv,
+            "target_code": code,
+            "settings": self.settings
+        }
+        exec(self.scripts, global_dict)
+        compute_result = global_dict["compute_result"]
+        if compute_result[0]:
+            if code in sv.鎴愪氦浠g爜:
+                return
+            # 鍙互涓嬪崟
+            # 鍒ゆ柇鏄惁鍙互涔�
+            for b in compute_result[3]:
+                DealCodesManager().place_order(b, code)
+
+# 褰撳墠鐨勪綆鍚哥瓥鐣ュ璞�
+low_suction_strtegy = None
\ No newline at end of file

--
Gitblit v1.8.0