Administrator
2023-08-28 ba52d7ac92a36f413eacaa686f8535e859664ec6
third_data/code_plate_key_manager.py
@@ -6,11 +6,11 @@
import json
import constant
from db.redis_manager import RedisUtils
from db.redis_manager_delegate import RedisUtils
from third_data import kpl_block_util
from utils import global_util, tool
from log_module import log
from db import redis_manager
from db import redis_manager_delegate as redis_manager
from log_module.log import logger_kpl_limit_up, logger_kpl_block_can_buy, logger_kpl_debug
from third_data.kpl_util import KPLPlatManager
@@ -21,43 +21,91 @@
class KPLCodeJXBlockManager:
    __redisManager = redis_manager.RedisManager(3)
    __code_blocks = {}
    # 备用
    __code_by_blocks = {}
    def __get_redis(self):
        return self.__redisManager.getRedis()
    def save_jx_blocks(self, code, blocks):
    def save_jx_blocks(self, code, blocks, by=False):
        if blocks is None:
            return
        if len(blocks) > 2:
            blocks = blocks[:2]
        # 保存前2条数据
        RedisUtils.setex(self.__get_redis(), f"kpl_jx_blocks-{code}", tool.get_expire(), json.dumps(blocks))
        self.__code_blocks[code] = blocks
        if by:
            RedisUtils.setex(self.__get_redis(), f"kpl_jx_blocks_by-{code}", tool.get_expire(), json.dumps(blocks))
            self.__code_by_blocks[code] = blocks
        else:
            RedisUtils.setex(self.__get_redis(), f"kpl_jx_blocks-{code}", tool.get_expire(), json.dumps(blocks))
            self.__code_blocks[code] = blocks
    # 获取精选板块
    def get_jx_blocks(self, code):
        if code in self.__code_blocks:
            return self.__code_blocks[code]
        val = RedisUtils.get(self.__get_redis(), f"kpl_jx_blocks-{code}")
        if val is None:
            return None
    def get_jx_blocks(self, code, by=False):
        if by:
            if code in self.__code_by_blocks:
                return self.__code_by_blocks[code]
            val = RedisUtils.get(self.__get_redis(), f"kpl_jx_blocks_by-{code}")
            if val is None:
                return None
            else:
                val = json.loads(val)
                self.__code_by_blocks[code] = val
            return self.__code_by_blocks[code]
        else:
            val = json.loads(val)
            self.__code_blocks[code] = val
        return self.__code_blocks[code]
            if code in self.__code_blocks:
                return self.__code_blocks[code]
            val = RedisUtils.get(self.__get_redis(), f"kpl_jx_blocks-{code}")
            if val is None:
                return None
            else:
                val = json.loads(val)
                self.__code_blocks[code] = val
            return self.__code_blocks[code]
    def get_jx_blocks_cache(self, code, by=False):
        if by:
            return self.__code_by_blocks.get(code)
        else:
            return self.__code_blocks.get(code)
# 开盘啦禁止交易板块管理
class KPLPlateForbiddenManager:
    __redisManager = redis_manager.RedisManager(3)
    __kpl_forbidden_plates_cache = set()
    def __get_redis(self):
        return self.__redisManager.getRedis()
    __instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = super(KPLPlateForbiddenManager, cls).__new__(cls, *args, **kwargs)
            cls.__load_datas()
        return cls.__instance
    @classmethod
    def __load_datas(cls):
        __redis = cls.__get_redis()
        try:
            __kpl_forbidden_plates_cache = RedisUtils.smembers(__redis, "kpl_forbidden_plates")
        finally:
            RedisUtils.realse(__redis)
    @classmethod
    def __get_redis(cls):
        return cls.__redisManager.getRedis()
    def save_plate(self, plate):
        self.__kpl_forbidden_plates_cache.add(plate)
        RedisUtils.sadd(self.__get_redis(), "kpl_forbidden_plates", plate)
        RedisUtils.expire(self.__get_redis(), "kpl_forbidden_plates", tool.get_expire())
    def list_all(self):
        return RedisUtils.smembers(self.__get_redis(), "kpl_forbidden_plates")
    def list_all_cache(self):
        return self.__kpl_forbidden_plates_cache
class LimitUpCodesPlateKeyManager:
@@ -217,7 +265,7 @@
            # 后排才能挂单
            return 0, "身位不为后排"
        forbidden_plates = cls.__KPLPlateForbiddenManager.list_all()
        forbidden_plates = cls.__KPLPlateForbiddenManager.list_all_cache()
        if key in forbidden_plates:
            return 0, "不买该板块"
@@ -236,7 +284,7 @@
    def is_in_top(cls, keys):
        reasons = cls.get_can_buy_key_set()
        log.logger_kpl_debug.debug("市场流入前5:{}", reasons)
        forbidden_plates = cls.__KPLPlateForbiddenManager.list_all()
        forbidden_plates = cls.__KPLPlateForbiddenManager.list_all_cache()
        reasons = reasons - forbidden_plates
        temp_set = keys & reasons
        log.logger_kpl_debug.debug("市场流入前5匹配结果:{}", temp_set)
@@ -278,6 +326,10 @@
                return None
        else:
            return reasons
    def get_history_limit_up_reason_cache(self, code):
        reasons = self.__history_limit_up_reason_dict.get(code)
        return reasons
    def set_blocks(self, code, blocks):
        self.__blocks_dict[code] = set(blocks)
@@ -323,9 +375,9 @@
        k1 = set()
        if code in LimitUpCodesPlateKeyManager.today_total_limit_up_reason_dict:
            k1 = {LimitUpCodesPlateKeyManager.today_total_limit_up_reason_dict[code]}
        # 加载今日历史原因
        k11 = RedisUtils.smembers(self.__get_redis(), f"kpl_limit_up_reason_his-{code}")
        k2 = self.__CodesPlateKeysManager.get_history_limit_up_reason(code)
        # 加载今日历史原因,暂时不需要历史原因了
        k11 = set()  # RedisUtils.smembers(self.__get_redis(), f"kpl_limit_up_reason_his-{code}")
        k2 = self.__CodesPlateKeysManager.get_history_limit_up_reason_cache(code)
        if k2 is None:
            k2 = set()
        k3 = set()
@@ -334,8 +386,11 @@
            k3 = {industry}
        k4 = set()
        jingxuan_blocks = self.__KPLCodeJXBlockManager.get_jx_blocks(code)
        jingxuan_blocks = self.__KPLCodeJXBlockManager.get_jx_blocks_cache(code)
        if not jingxuan_blocks:
            jingxuan_blocks = self.__KPLCodeJXBlockManager.get_jx_blocks_cache(code, by=True)
        if jingxuan_blocks:
            jingxuan_blocks = jingxuan_blocks[:2]
            k4 |= set([x[1] for x in jingxuan_blocks])
        for k in [k1, k11, k2, k3, k4]:
            keys |= k
@@ -361,7 +416,8 @@
    __TargetCodePlateKeyManager = TargetCodePlateKeyManager()
    __LimitUpCodesPlateKeyManager = LimitUpCodesPlateKeyManager()
    __CodesHisReasonAndBlocksManager = CodesHisReasonAndBlocksManager()
    __CodesTradeStateManager = trade_manager.CodesTradeStateManager()
    __can_buy_compute_result_dict = {}
    # 获取可以买的板块
    # current_limit_up_datas: 今日实时涨停
@@ -396,15 +452,13 @@
            for k in k1:
                if k not in constant.KPL_INVALID_BLOCKS:
                    keys.add(k)
        if not keys:
            for k in k2:
                if k not in constant.KPL_INVALID_BLOCKS:
                    keys.add(k)
        # 始终获取精选板块
        if True:
            # 获取
            if k4:
                keys |= k4
                keys = keys - constant.KPL_INVALID_BLOCKS
        log.logger_kpl_debug.info("{}最终关键词:{}", code, keys)
        # 涨停列表中匹配关键词,返回(板块:代码集合),代码集合中已经排除自身
@@ -416,21 +470,24 @@
        can_buy_blocks = []
        for block in keys:
            is_top_8_record, top_8_record = kpl_block_util.is_record_top_block(code, block, limit_up_record_datas,
                                                                               yesterday_current_limit_up_codes, 20)
            is_top_4_current, top_4_current = kpl_block_util.is_current_top_block(code, block, current_limit_up_datas,
                                                                                  yesterday_current_limit_up_codes, 10)
            is_top_4 = is_top_8_record and is_top_4_current
            msg_list.append(f"\n实时top10: {top_4_current}(涨停数量:{len(current_limit_up_datas)})")
            msg_list.append(f"历史top20: {top_8_record}")
            log.logger_kpl_debug.info(f"判断板块是否可买:{block}")
            # is_top_8_record, top_8_record = kpl_block_util.is_record_top_block(code, block, limit_up_record_datas,
            #                                                                    yesterday_current_limit_up_codes, 50)
            # is_top_4_current, top_4_current = kpl_block_util.is_current_top_block(code, block, current_limit_up_datas,
            #                                                                       yesterday_current_limit_up_codes, 50)
            # is_top_4 = is_top_8_record and is_top_4_current
            # msg_list.append(f"\n实时top10(涨停数量:{len(current_limit_up_datas)})")
            # msg_list.append(f"历史top20(涨停数量:{len(top_8_record)})")
            # 获取主板实时身位,剔除高位板
            current_shsz_rank = kpl_block_util.get_code_current_rank(code, block, current_limit_up_datas,
                                                                     code_limit_up_reason_dict, yesterday_current_limit_up_codes, shsz=True)
                                                                     code_limit_up_reason_dict,
                                                                     yesterday_current_limit_up_codes, shsz=True)
            record_shsz_rank = kpl_block_util.get_code_record_rank(code, block, limit_up_record_datas,
                                                                   code_limit_up_reason_dict, yesterday_current_limit_up_codes, shsz=True)
                                                                   code_limit_up_reason_dict,
                                                                   yesterday_current_limit_up_codes, shsz=True)
            # 获取主板历史身位
            if is_top_4:
            if True:
                pen_limit_up_codes = kpl_block_util.get_shsz_open_limit_up_codes(code, block, limit_up_record_datas,
                                                                                 code_limit_up_reason_dict)
                if pen_limit_up_codes:
@@ -454,21 +511,22 @@
                            f"板块-{block}: top4涨停板块,非主板开1,不为主板龙1(实时身位-{current_shsz_rank},历史身位-{record_shsz_rank})")
                        continue
            else:
                # 是否满足行业精选流入要求
                is_in_top_input = RealTimeKplMarketData.is_in_top(set([block]))[0]
                if not is_in_top_input:
                    msg_list.append(
                        f"板块-{block}: 非top4涨停板块,不满足精选/行业流入要求")
                    continue
                else:
                    # 是否为主板龙1(实时龙1,历史龙2以内)
                    if current_shsz_rank == 0 and record_shsz_rank < 2:
                        can_buy_blocks.append((block, f"{block}:不是top4涨停板块,满足精选/行业流入要求,满足主板龙1"))
                        continue
                    else:
                        msg_list.append(
                            f"板块-{block}: 不是top4涨停板块,满足精选/行业流入要求,不为主板龙1(实时身位-{current_shsz_rank},历史身位-{record_shsz_rank})")
                        continue
                pass
                # # 是否满足行业精选流入要求
                # is_in_top_input = RealTimeKplMarketData.is_in_top(set([block]))[0]
                # if not is_in_top_input:
                #     msg_list.append(
                #         f"板块-{block}: 非top4涨停板块,不满足精选/行业流入要求")
                #     continue
                # else:
                #     # 是否为主板龙1(实时龙1,历史龙2以内)
                #     if current_shsz_rank == 0 and record_shsz_rank < 2:
                #         can_buy_blocks.append((block, f"{block}:不是top4涨停板块,满足精选/行业流入要求,满足主板龙1"))
                #         continue
                #     else:
                #         msg_list.append(
                #             f"板块-{block}: 不是top4涨停板块,满足精选/行业流入要求,不为主板龙1(实时身位-{current_shsz_rank},历史身位-{record_shsz_rank})")
                #         continue
        if len(can_buy_blocks) == len(keys):
            blocks = [x[0] for x in can_buy_blocks]
            blocks_msg = "\n".join([x[1] for x in can_buy_blocks])
@@ -479,68 +537,24 @@
    # 是否可以下单
    # 返回:是否可以下单,消息,板块类型
    @classmethod
    def can_buy(cls, code, current_limit_up_datas, limit_up_record_datas, yesterday_current_limit_up_codes,
                before_blocks_dict):
        if constant.TEST:
            return True, "", cls.BLOCK_TYPE_NONE
    def can_buy(cls, code):
        # if constant.TEST:
        #     return True, cls.BLOCK_TYPE_NONE
        return cls.__can_buy_compute_result_dict.get(code)
    @classmethod
    def __compute_can_buy_blocks(cls, code, current_limit_up_datas, limit_up_record_datas,
                                 yesterday_current_limit_up_codes, before_blocks_dict):
        blocks, block_msg = cls.get_can_buy_block(code, current_limit_up_datas,
                                                  limit_up_record_datas, yesterday_current_limit_up_codes,
                                                  before_blocks_dict)
        if not blocks:
            return False, block_msg
        # ---------------------------------判断目标代码的板块-------------------start------------
        # 判断匹配出的涨停原因,判断是否有已经下单的票
        # reason_need_buy_dict = {}
        # for k in match_limit_up_result:
        #     codes = match_limit_up_result[k]
        #     final_codes_keys = [keys]
        #     for code_ in codes:
        #         temp_key_set = set()
        #         temp_key_set |= cls.__CodesHisReasonAndBlocksManager.get_total_keys(code_)
        #         temp = cls.__LimitUpCodesPlateKeyManager.total_code_keys_dict.get(code_)
        #         if temp:
        #             temp_key_set |= temp
        #         # 二级
        #         industry = global_util.code_industry_map.get(code_)
        #         if industry:
        #             temp_key_set.add(industry)
        #
        #         final_codes_keys.append(temp_key_set)
        #     # 求共同的关键词
        #     intersection = set(final_codes_keys[0])
        #     for s in final_codes_keys:
        #         intersection &= s
        #     log.logger_kpl_debug.info("{}的板块求交集:{}-{}", code, k, intersection)
        #
        #     # 求公共的板块是否在流入前5中
        #     is_in, valid_keys = RealTimeKplMarketData.is_in_top(intersection)
        #     if is_in:
        #         reason_need_buy_dict[k] = (is_in, valid_keys)
        # ---------------------------------判断目标代码的板块-------------------end------------
        # 获取板块可以下单的个数
        # can_buy_codes_count_dict = {}
        #
        # for key__ in match_limit_up_result:
        #     can_buy_count, msg = RealTimeKplMarketData.get_can_buy_codes_count(code, key__)
        #     can_buy_codes_count_dict[key__] = can_buy_count
        # has_available_key = False
        # for key in can_buy_codes_count_dict:
        #     if can_buy_codes_count_dict[key] > 0:
        #         has_available_key = True
        #         break
        # if not has_available_key:
        #     return False, f"匹配到的【{','.join(match_limit_up_result.keys())}】没在精选/行业可以买入的板块中"
        # ---------------------------------加载已经下单/成交的代码信息------------start-------------
        # match_reasons = match_limit_up_result.keys()
        # 判断匹配到的原因是否已经有下单/买入成功的代码
        codes_delegate = set(trade_manager.get_codes_by_trade_states(
        log.logger_kpl_debug.info(f"{code}:获取委托/买入代码")
        codes_delegate = set(cls.__CodesTradeStateManager.get_codes_by_trade_states_cache(
            {trade_manager.TRADE_STATE_BUY_DELEGATED, trade_manager.TRADE_STATE_BUY_PLACE_ORDER}))
        codes_success = set(trade_manager.get_codes_by_trade_states(
        codes_success = set(cls.__CodesTradeStateManager.get_codes_by_trade_states_cache(
            {trade_manager.TRADE_STATE_BUY_SUCCESS}))
        codes = codes_delegate | codes_success
@@ -549,11 +563,13 @@
        trade_codes_blocks_dict = {}
        # 已经成交的板块
        trade_success_blocks_count = {}
        log.logger_kpl_debug.info(f"{code}:获取代码板块")
        for c in codes:
            keys_, k1_, k11_, k2_, k3_, k4_ = cls.__TargetCodePlateKeyManager.get_plate_keys(c)
            # 实时涨停原因
            trade_codes_blocks_dict[c] = k1_|k4_
            trade_codes_blocks_dict[c] = k1_ | k4_
        # 统计板块中的代码
        log.logger_kpl_debug.info(f"{code}:统计板块中的代码")
        trade_block_codes_dict = {}
        for c in trade_codes_blocks_dict:
            for b in trade_codes_blocks_dict[c]:
@@ -566,7 +582,7 @@
                trade_block_codes_dict[b].add(c)
        # ---------------------------------加载已经下单/成交的代码信息------------end-------------
        log.logger_kpl_debug.info(f"{code}:开始计算是否可以买")
        msg_list = []
        for key in blocks:
            # 板块中已经有成交的就不下单了
@@ -576,25 +592,20 @@
                    msg_list.append(f"【{key}】中已经有{success_codes_count}个成交代码")
                    log.logger_kpl_debug.debug(f"{code}:板块({key})已经有成交【{trade_success_blocks_count[key]}】")
                    continue
                # 10:30以后买1个
                if int(tool.get_now_time_str().replace(":", "")) > int("103000") and success_codes_count >= 1:
                    msg_list.append(f"【{key}】中已经有{success_codes_count}个成交代码")
                    log.logger_kpl_debug.debug(f"{code}:板块({key})已经有成交【{trade_success_blocks_count[key]}】")
                    continue
            return True, block_msg
            # 板块可以下单数量
            # if trade_block_codes_dict.get(key) is None or len(trade_block_codes_dict.get(key)) < \
            #         can_buy_codes_count_dict[key]:
            #     order_count = len(trade_block_codes_dict.get(key)) if key in trade_block_codes_dict else 0
            #     logger_kpl_block_can_buy.info(
            #         f"code={code}:【{key}】可以下单,现有数量:{order_count} 最大数量:{can_buy_codes_count_dict[key]}")
            #     return True, f"可以下单,板块:【{key}】,板块中已经下单的数量:{order_count}"
            # else:
            #     order_count = len(trade_block_codes_dict.get(key))
            #     msg_list.append(f"【{key}】中下单代码数量{order_count}/允许下单数量{can_buy_codes_count_dict[key]}")
        return False, ",".join(msg_list)
    @classmethod
    def update_can_buy_blocks(cls, code, current_limit_up_datas, limit_up_record_datas,
                              yesterday_current_limit_up_codes,
                              before_blocks_dict):
        can_buy, msg = cls.__compute_can_buy_blocks(code, current_limit_up_datas, limit_up_record_datas,
                                                    yesterday_current_limit_up_codes,
                                                    before_blocks_dict)
        # 保存板块计算结果
        cls.__can_buy_compute_result_dict[code] = (can_buy, msg)
if __name__ == "__main__":
    pass