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