third_data/code_plate_key_manager.py
@@ -12,18 +12,19 @@
from db.redis_manager_delegate import RedisUtils
from third_data import kpl_block_util, kpl_api, kpl_util, kpl_data_constant, huaxin_l1_data_manager
from settings.trade_setting import MarketSituationManager
from third_data.kpl_data_constant import LimitUpDataConstant
from third_data.kpl_data_constant import LimitUpDataConstant, LimitUpCodesBlockRecordManager
from third_data.third_blocks_manager import BlockMapManager, CodeThirdBlocksManager
from trade.buy_money_count_setting import RadicalBuyBlockCodeCountManager
from trade.order_statistic import DealAndDelegateWithBuyModeDataManager
from trade.radical_buy_data_manager import RedicalBuyDataManager
from trade.radical_buy_data_manager import RadicalBuyDataManager, BlockPlaceOrderRecordManager
from trade.trade_data_manager import RadicalBuyDealCodesManager
from utils import global_util, tool, buy_condition_util
from log_module import log, async_log_util
from db import redis_manager_delegate as redis_manager
from log_module.log import logger_kpl_block_can_buy, logger_debug, logger_kpl_jx_out
from third_data.kpl_util import KPLPlatManager
from trade import trade_manager, l2_trade_util, trade_constant
from trade import trade_manager, l2_trade_util, trade_constant, radical_buy_data_manager
# 代码精选板块管理
from utils.kpl_data_db_util import KPLLimitUpDataUtil
@@ -293,12 +294,6 @@
    def get_today_limit_up_reason(cls, code):
        return cls.__today_total_limit_up_reason_dict.get(code)
    # 今日涨停原因变化
    def set_today_limit_up_reason_change(self, code, from_reason, to_reason):
        RedisUtils.sadd(self.__get_redis(), f"kpl_limit_up_reason_his-{code}", from_reason)
        RedisUtils.expire(self.__get_redis(), f"kpl_limit_up_reason_his-{code}", tool.get_expire())
        self.__set_total_keys(code)
    # 设置代码的今日涨停原因
    def __set_total_keys(self, code):
        keys = set()
@@ -378,7 +373,8 @@
        """
        blocks = set()
        for i in range(0, len(datas)):
            if i >= 10:
            if i >= 10 and int(tool.get_now_time_str().replace(":", "")) < int("100000"):
                # 10点前看前10,十点后不看前10
                break
            data = datas[i]
            if data[3] > 0 - 5e7:
@@ -926,7 +922,8 @@
            current_limit_up_datas = []
        # 获取目标代码板块
        keys, k1, k11, k2, k3, k4 = cls.__TargetCodePlateKeyManager.get_plate_keys(code)
        # keys, k1, k11, k2, k3, k4 = cls.__TargetCodePlateKeyManager.get_plate_keys(code)
        keys, k1 = RadicalBuyBlockManager.get_code_blocks(code)
        # log.logger_kpl_debug.info("{}最终关键词:{}", code, keys)
@@ -935,10 +932,6 @@
        fresults = []
        if not keys:
            return fresults, set()
        # 获取精选流出板块
        jx_out_blocks = RealTimeKplMarketData.get_top_market_jingxuan_out_blocks()
        if jx_out_blocks:
            keys -= jx_out_blocks
        code_limit_up_reasons_dict = {}
        load_code_block()
@@ -1112,7 +1105,7 @@
class RadicalBuyBlockManager:
    """
    激进买板块管理
    扫入买板块管理
    """
    __TargetCodePlateKeyManager = TargetCodePlateKeyManager()
    # 上次的涨停代码
@@ -1184,16 +1177,25 @@
            blocks -= constant.KPL_INVALID_BLOCKS
            # 过滤
            blocks = BlockMapManager().filter_blocks(blocks)
            temp_dict[code] = (kpl_util.get_high_level_count(d[4]), blocks)
            # 开1剔除4板以上的
            high_level = kpl_util.get_high_level_count(d[4])
            if high_level >= 4:
                continue
            temp_dict[code] = (high_level, blocks)
        kpl_data_constant.open_limit_up_code_dict_for_radical_buy = temp_dict
    @classmethod
    def __get_current_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None, limit_up_time=None):
    def __get_current_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None, limit_up_time=None,
                            ignore_open_limit_up=True):
        """
        获取当前涨停身位
         获取当前涨停身位
        @param code:
        @param block:
        @param yesterday_limit_up_codes:
        @param exclude_codes:
        @param limit_up_time:
        @param ignore_open_limit_up: 是否忽略开1的代码
        @return: 索引,前排代码信息([(代码, 涨停时间)])
        """
        if exclude_codes is None:
@@ -1210,7 +1212,6 @@
            blocks = LimitUpDataConstant.get_blocks_with_history(_code)
            if not blocks:
                blocks = set()
            blocks = BlockMapManager().filter_blocks(blocks)
            if _code == code:
                # 获取当前代码涨停时间
                limit_up_time = int(k[2])
@@ -1218,10 +1219,15 @@
            # 不是这个板块
            if block not in blocks:
                continue
            # 剔除4板以上的板
            if kpl_util.get_high_level_count(k[4]) >= 4 and len(blocks) > 1:
                continue
            if not tool.is_can_buy_code(_code):
                continue
            # 剔除开1的数据
            if timestamp_start <= int(k[2]) < timestamp_end:
            if ignore_open_limit_up and timestamp_start <= int(k[2]) < timestamp_end:
                continue
            # 剔除高位板
            if _code in yesterday_limit_up_codes:
@@ -1241,13 +1247,14 @@
        return current_index, before_codes_info
    @classmethod
    def __get_history_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None):
    def __get_history_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None, ignore_open_limit_up=True):
        """
        获取历史涨停身位
        @param code:
        @param block:
        @param current_limit_up_datas: 昨日涨停代码
        @param current_limit_up_codes: 目前的涨停代码
        @param yesterday_limit_up_codes:
        @param exclude_codes:
        @param ignore_open_limit_up: 是否忽略开1代码
        @return:
        """
        if exclude_codes is None:
@@ -1262,19 +1269,23 @@
            _code = k[3]
            if _code in exclude_codes:
                continue
            blocks = LimitUpDataConstant.get_blocks_with_history(_code)
            blocks = BlockMapManager().filter_blocks(blocks)
            if _code == code:
                # 获取当前代码涨停时间
                limit_up_time = int(k[5])
                continue
            blocks = LimitUpDataConstant.get_blocks_with_history(_code)
            # 不是这个板块
            if block not in blocks:
                continue
            # 剔除4板以上且板块数量大于1个
            if kpl_util.get_high_level_count(k[12]) >= 4 and len(blocks) > 1:
                continue
            if not tool.is_can_buy_code(_code):
                continue
            # 剔除开1的数据
            if timestamp_start <= int(k[5]) < timestamp_end:
            if ignore_open_limit_up and timestamp_start <= int(k[5]) < timestamp_end:
                continue
            # 剔除高位板
            if _code in yesterday_limit_up_codes:
@@ -1312,7 +1323,7 @@
        # 9:45点之前涨停的才能买入
        # 获取当前代码的涨停时间
        limit_up_timestamp = cls.__get_limit_up_timestamp(code)
        if int(tool.timestamp_format(limit_up_timestamp, "%H%M%S")) > 94500:
        if tool.get_now_time_as_int() > 100000:
            return False, "超过生效时间"
        # 根据板块聚合数据
        open_limit_up_block_codes_dict = {}
@@ -1332,12 +1343,26 @@
        current_index, current_before_codes_info = cls.__get_current_index(code, block, yesterday_limit_up_codes,
                                                                           limit_up_time=limit_up_timestamp)
        exclude_codes = set()
        if count >= 2 or (
                count == 1 and kpl_data_constant.open_limit_up_code_dict_for_radical_buy[open_limit_up_block_codes[0]][
            0] == 2):
        # 是否为强势二板开1:该代码所有的慨念必须都为二板开1且开1的只能有他自己
        is_strong_2_level = count == 1 and \
                            kpl_data_constant.open_limit_up_code_dict_for_radical_buy[open_limit_up_block_codes[0]][
                                0] == 2
        if is_strong_2_level:
            _code = open_limit_up_block_codes[0]
            blocks = LimitUpDataConstant.get_blocks_with_history(_code)
            if blocks:
                # 所有的慨念的开1代码必须只有他自己
                for b in blocks:
                    temp_codes = open_limit_up_block_codes_dict.get(b)
                    if temp_codes and len(temp_codes) > 1:
                        is_strong_2_level = False
                        break
        if count >= 2 or is_strong_2_level:
            # 开始数量大于2个或者只有一个2板开1
            exclude_codes.clear()
        else:
            # 只有一个开1
            # 获取包含高位板的身位
            # ----获取历史身位----
            history_index, history_before_codes_info = cls.__get_history_index(code, block, set())
@@ -1346,26 +1371,76 @@
                                                                               limit_up_time=limit_up_timestamp)
            if history_before_codes_info and current_before_codes_info and history_before_codes_info[0][0] == \
                    current_before_codes_info[0][0]:
                # 前排第一个元素无炸板
                # 排除第一个非开1数据
                exclude_codes = {history_before_codes_info[0][0]}
            else:
                return False, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}"
        # 获取主板的身位
        # 获取主板的身位(已经排除了开1的代码)
        history_index, history_before_codes_info = cls.__get_history_index(code, block,
                                                                           yesterday_limit_up_codes,
                                                                           exclude_codes=exclude_codes)
        # 过滤不正的原因
        history_index, history_before_codes_info = cls.__filter_before_codes(block, history_index,
                                                                             history_before_codes_info,
                                                                             yesterday_limit_up_codes)
        # 买首板老大/老二
        # 首板老大不能买时可买老二
        if history_index > 1:
            return False, f"开1数量:{count},非开1首板身位不匹配:历史-{history_index + 1} 实时-{current_index + 1}"
        if history_index == 1:
            # 当前代码为老2,要判断老大是否可买
            if RedicalBuyDataManager.can_buy(history_before_codes_info[0][0],
                                             DealAndDelegateWithBuyModeDataManager().get_deal_codes())[0]:
            if RadicalBuyDataManager.is_code_can_buy(history_before_codes_info[0][0],
                                                     DealAndDelegateWithBuyModeDataManager().get_deal_codes(),
                                                     is_refered=True)[0]:
                return False, f"开1数量:{count},前排代码可买:{history_before_codes_info[0]}"
            return True, f"开1数量:{count},前排代码不可买:{history_before_codes_info[0]}"
        return True, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}"
            return True, f"开1数量:{count},前排代码不可买:{history_before_codes_info[0]},历史前排-{history_before_codes_info},开1代码-{open_limit_up_block_codes}"
        return True, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}, 前排代码-{current_before_codes_info}, 开1代码-{open_limit_up_block_codes}"
    @classmethod
    def __filter_before_codes(cls, block, index, before_codes_info, yesterday_codes):
        """
        过滤前排涨停原因不正/不算身位的代码
        @param code:
        @param block:板块
        @param index: 目标代码位置
        @param before_codes_info: [(代码, 涨停时间戳)]
        @return: 过滤之后的 (index, before_codes_info)
        """
        try:
            if index == 0 or not before_codes_info:
                return index, before_codes_info
            temp_index = index
            temp_before_codes_info = []
            deal_codes = RadicalBuyDealCodesManager().get_deal_codes()
            for b in before_codes_info:
                # 当作目标票获取扫入板块
                code_ = b[0]
                blocks = LimitUpCodesBlockRecordManager().get_radical_buy_blocks(code_)
                blocks = BlockMapManager().filter_blocks(blocks)
                need_delete = False
                # 判断原因不正
                if block not in blocks and b[0] not in yesterday_codes:
                    # 首板涨停原因不正
                    need_delete = True
                # 判断是否是不计算身位
                if not need_delete:
                    if radical_buy_data_manager.ExcludeIndexComputeCodesManager.is_in_cache(code_):
                        need_delete = True
                # 判断是不是扫了没有扫进入
                if not need_delete:
                    if code_ in  BlockPlaceOrderRecordManager().get_codes() and code_ not in deal_codes:
                        need_delete = True
                if need_delete:
                    temp_index -= 1
                else:
                    temp_before_codes_info.append(b)
            return temp_index, temp_before_codes_info
        except Exception as e:
            async_log_util.error(logger_debug, f"扫入板块过滤出错:{str(e)}")
            return index, before_codes_info
    @classmethod
    def __is_radical_buy_with_block_up(cls, code, block, yesterday_limit_up_codes):
@@ -1400,15 +1475,19 @@
        if tool.trade_time_sub(tool.timestamp_format(limit_up_timestamp, '%H:%M:%S'),
                               tool.timestamp_format(current_before_codes_info[-1][1], '%H:%M:%S')) >= 10 * 60:
            return False, f"距离上个代码涨停已过去10分钟({current_before_codes_info[0]})"
            return False, f"距离上个代码涨停已过去10分钟({current_before_codes_info[-1]})"
        history_index, history_before_codes_info = cls.__get_history_index(code, block, set())
        history_before_codes = [x[0] for x in history_before_codes_info]
        # 包含高位板的整体排序
        all_history_index, all_history_before_codes_info = cls.__get_history_index(code, block, set())
        all_history_before_codes = [x[0] for x in all_history_before_codes_info]
        # 前两个代码是否有炸板
        dif_codes = set(history_before_codes[:2]) - set(current_before_codes[:2])
        dif_codes = set(all_history_before_codes[:2]) - set(current_before_codes[:2])
        if dif_codes:
            return False, f"前2代码有炸板:{dif_codes}"
        # 不计算前2的代码
            return False, f"前2代码有炸板:{dif_codes}, 前排代码:{all_history_before_codes}"
        # 前排代码炸板不能>=2个
        dif_codes = set(all_history_before_codes) - set(current_before_codes)
        if len(dif_codes) >= 2:
            return False, f"板块前排有{len(dif_codes)}个炸板"
        exclude_codes = set()
        for x in current_before_codes_info:
@@ -1427,6 +1506,12 @@
            exclude_codes |= set(open_limit_up_code_dict.keys())
        history_index, history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes,
                                                                           exclude_codes)
        # 过滤不正的原因
        history_index, history_before_codes_info = cls.__filter_before_codes(block, history_index,
                                                                             history_before_codes_info,
                                                                             yesterday_limit_up_codes)
        # 获取本板块买入代码的最大数量
        max_count = RadicalBuyBlockCodeCountManager().get_block_code_count(block)
        if history_index > max_count:
@@ -1437,22 +1522,26 @@
                # 首板老2,判断前面的老大是否是属于不能买的范畴
                pre_code = history_before_codes_info[0][0]
                # pre_code不能买,才能买
                if RedicalBuyDataManager.can_buy(pre_code, DealAndDelegateWithBuyModeDataManager().get_deal_codes())[0]:
                if RadicalBuyDataManager.is_code_can_buy(pre_code,
                                                         DealAndDelegateWithBuyModeDataManager().get_deal_codes(),
                                                         is_refered=True)[0]:
                    return False, f"前排代码可买:{pre_code}"
                # 距离前一个是否在10分钟内
                if tool.trade_time_sub(tool.timestamp_format(limit_up_timestamp, '%H:%M:%S'),
                                       tool.timestamp_format(history_before_codes_info[-1][1], '%H:%M:%S')) >= 10 * 60:
                    return False, f"距离上个不能买的代码涨停已过去10分钟({history_before_codes_info[0]})"
                # 前面一个代码不能买,前一个代码必须与前前个代码涨停时间相差15分钟内
                for i in range(len(all_history_before_codes_info) - 1, -1, -1):
                    if all_history_before_codes_info[i][0] == pre_code:
                        if tool.trade_time_sub(tool.timestamp_format(all_history_before_codes_info[i][1], '%H:%M:%S'),
                                               tool.timestamp_format(all_history_before_codes_info[i - 1][1],
                                                                     '%H:%M:%S')) >= 15 * 60:
                            return False, f"被顺位代码({pre_code}) 与上个代码涨停时间>=15分钟 ({all_history_before_codes_info[i]}##{all_history_before_codes_info[i - 1]})"
                        else:
                            return True, f"被顺位代码({pre_code}) 与上个代码涨停时间<15分钟 ({all_history_before_codes_info[i]}##{all_history_before_codes_info[i - 1]})"
                return False, f"没找到顺位代码({pre_code})的前排代码"
            else:
                # 距离上个代码涨停5分钟以内
                if tool.trade_time_sub(tool.timestamp_format(limit_up_timestamp, '%H:%M:%S'),
                                       tool.timestamp_format(current_before_codes_info[-1][1], '%H:%M:%S')) >= 5 * 60:
                    return False, f"距离上个代码涨停已过去5分钟({current_before_codes_info[-1]})"
                # 代码为目标代码
                pass
        else:
            if tool.trade_time_sub(tool.timestamp_format(limit_up_timestamp, '%H:%M:%S'),
                                   tool.timestamp_format(current_before_codes_info[-1][1], '%H:%M:%S')) >= 5 * 60:
                return False, f"距离上个代码涨停已过去5分钟({current_before_codes_info[-1]})"
            # 代码为目标代码
            pass
        return True, f"满足买入需求: 前排代码-{current_before_codes_info}"
    @classmethod
@@ -1530,25 +1619,34 @@
        @param code:
        @return: 过滤后的板块,过滤前的板块
        """
        blocks = cls.get_code_kpl_blocks(code)
        match_blocks, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks)
        match_blocks -= constant.KPL_INVALID_BLOCKS
        fblocks = match_blocks & RealTimeKplMarketData.get_top_market_jingxuan_blocks()
        if not fblocks:
            fblocks = set()
        match_blocks_3, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks, same_count=3)
        if match_blocks_3:
            match_blocks_3 -= constant.KPL_INVALID_BLOCKS
            fblocks |= match_blocks_3
        # 获取开盘啦历史涨停原因
        kpl_history_blocks = CodesHisReasonAndBlocksManager().get_history_blocks_cache(code)
        if kpl_history_blocks:
            fblocks |= BlockMapManager().filter_blocks(kpl_history_blocks)
        jx_out_blocks = RealTimeKplMarketData.get_top_market_jingxuan_out_blocks()
        if jx_out_blocks:
            fblocks-=jx_out_blocks
        # blocks = cls.get_code_kpl_blocks(code)
        # match_blocks, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks)
        # match_blocks -= constant.KPL_INVALID_BLOCKS
        # fblocks = match_blocks & RealTimeKplMarketData.get_top_market_jingxuan_blocks()
        # if not fblocks:
        #     fblocks = set()
        # match_blocks_3, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks, same_count=3)
        # if match_blocks_3:
        #     match_blocks_3 -= constant.KPL_INVALID_BLOCKS
        #     fblocks |= match_blocks_3
        # # 获取开盘啦历史涨停原因
        # kpl_history_blocks = CodesHisReasonAndBlocksManager().get_history_blocks_cache(code)
        # if kpl_history_blocks:
        #     fblocks |= BlockMapManager().filter_blocks(kpl_history_blocks)
        # jx_out_blocks = RealTimeKplMarketData.get_top_market_jingxuan_out_blocks()
        # if jx_out_blocks:
        #     fblocks -= jx_out_blocks
        #
        # return fblocks, match_blocks
        return fblocks, match_blocks
        # 新版本
        before_fblocks = LimitUpCodesBlockRecordManager().get_radical_buy_blocks(code)
        if not before_fblocks:
            before_fblocks = set()
        fblocks = BlockMapManager().filter_blocks(before_fblocks)
        if fblocks:
            fblocks -= constant.KPL_INVALID_BLOCKS
        return fblocks, before_fblocks
    @classmethod
    def is_radical_buy(cls, code, yesterday_limit_up_codes):
@@ -1599,6 +1697,18 @@
                    can_buy_blocks.add(b)
                    msges.append(f"【{b}】:{result[1]}")
            fmsges.append("板块回封判断##" + ",".join(msges))
        # 如果能扫入就需要获取代码在板块中的身位
        # if can_buy_blocks:
        #     excude_codes = set()
        #     if kpl_data_constant.open_limit_up_code_dict_for_radical_buy:
        #         excude_codes |= kpl_data_constant.open_limit_up_code_dict_for_radical_buy.keys()
        #     # 剔除开1的代码
        #     for b in keys_:
        #         history_index, history_before_codes_info = cls.__get_history_index(code, b, yesterday_limit_up_codes,
        #                                                                            excude_codes)
        #         if history_index >= 4:
        #             return set(), f"在【{b}】中身位({history_index + 1})靠后"
        return can_buy_blocks, " **** ".join(fmsges)