Administrator
2024-09-12 a6db14d8bf83be51d61b285a86f16ffe7b4ce5cf
激进买策略修复
3个文件已修改
1个文件已添加
210 ■■■■ 已修改文件
servers/huaxin_trade_server.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
third_data/code_plate_key_manager.py 132 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/radical_buy_data_manager.py 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/tool.py 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
servers/huaxin_trade_server.py
@@ -49,6 +49,7 @@
from trade.huaxin import huaxin_trade_api as trade_api, huaxin_trade_api, huaxin_trade_data_update, \
    huaxin_trade_record_manager, huaxin_sell_util
from api.outside_api_command_callback import OutsideApiCommandCallback
from trade.radical_buy_data_manager import RedicalBuyDataManager
from trade.sell.sell_rule_manager import TradeRuleManager
from trade.trade_data_manager import RadicalBuyDealCodesManager
from trade.trade_manager import CodesTradeStateManager
@@ -441,7 +442,8 @@
                need_cancel, rule_id = DCancelBigNumComputer().need_cancel(code, buy_1_volume)
                if need_cancel:
                    try:
                        l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, f"盯封单撤:{time_str}-{buy_1_volume}", cancel_type=trade_constant.CANCEL_TYPE_D)
                        l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, f"盯封单撤:{time_str}-{buy_1_volume}",
                                                                            cancel_type=trade_constant.CANCEL_TYPE_D)
                    finally:
                        TradeRuleManager().excuted(rule_id)
        except Exception as e:
@@ -777,8 +779,8 @@
                async_log_util.info(logger_l2_radical_buy, f"该代码已经成交:{code}")
                return
            k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code)
            if k_format and k_format[13] and not k_format[14]:
            can_buy_result = RedicalBuyDataManager.can_buy(code)
            if can_buy_result[0]:
                # 获取激进买的板块
                result_cache = self.__radical_buy_by_blocks_result_cache.get(code)
                if not result_cache or result_cache[0] < time.time():
@@ -871,7 +873,9 @@
                                time.time() + 3, buy_no)
                else:
                    volume_rate = code_volumn_manager.get_volume_rate(code)
                    async_log_util.info(logger_l2_radical_buy, f"图形不符合要求:{code},量比:{volume_rate}")
                    async_log_util.info(logger_l2_radical_buy, f"没有可扫入的板块:{code},量比:{volume_rate}")
            else:
                async_log_util.info(logger_l2_radical_buy, f"目前代码不可交易:{code}-{can_buy_result[1]}")
        except Exception as e:
            async_log_util.info(logger_debug, f"激进买计算异常:{str(e)}")
third_data/code_plate_key_manager.py
@@ -15,6 +15,7 @@
from third_data.history_k_data_manager import HistoryKDataManager
from third_data.history_k_data_util import HistoryKDatasUtils
from third_data.kpl_data_constant import LimitUpDataConstant
from trade.radical_buy_data_manager import RedicalBuyDataManager
from utils import global_util, tool, buy_condition_util, init_data_util
from log_module import log, async_log_util
from db import redis_manager_delegate as redis_manager
@@ -1131,7 +1132,7 @@
        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):
    def __get_current_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None):
        """
        获取当前涨停身位
        @param code:
@@ -1139,12 +1140,16 @@
        @param yesterday_limit_up_codes:
        @return: 索引,前排代码信息([(代码, 涨停时间)])
        """
        if exclude_codes is None:
            exclude_codes = set()
        current_index = 0
        block_codes_infos = []
        timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range
        limit_up_time = time.time()
        for k in LimitUpDataConstant.current_limit_up_datas:
            _code = k[0]
            if _code in exclude_codes:
                continue
            blocks = LimitUpDataConstant.get_blocks_with_history(_code)
            if not blocks:
                blocks = set()
@@ -1178,7 +1183,7 @@
        return current_index, before_codes_info
    @classmethod
    def __get_history_index(cls, code, block, yesterday_limit_up_codes):
    def __get_history_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None):
        """
        获取历史涨停身位
        @param code:
@@ -1187,13 +1192,18 @@
        @param current_limit_up_codes: 目前的涨停代码
        @return:
        """
        if exclude_codes is None:
            exclude_codes = set()
        history_index = 0
        block_codes_infos = []
        # 开1时间范围
        timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range
        limit_up_time = time.time()
        limit_up_space_ge_60s_codes = set()
        for k in LimitUpDataConstant.history_limit_up_datas:
            _code = k[3]
            if _code in exclude_codes:
                continue
            blocks = LimitUpDataConstant.get_blocks_with_history(_code)
            if _code == code:
                # 获取当前代码涨停时间
@@ -1210,9 +1220,11 @@
            # 剔除高位板
            if _code in yesterday_limit_up_codes:
                continue
            # 剔除炸板代码持续涨停时间小于1分钟的代码
            # 剔除炸板代码持续涨停时间小于1分钟的代码 且 只能用于不排除前2条数据
            if _code not in cls.__current_limit_up_codes and _code in cls.__total_limit_up_space_dict and \
                    cls.__total_limit_up_space_dict[_code] < 60:
                    cls.__total_limit_up_space_dict[_code] < 60 and not exclude_codes and len(
                limit_up_space_ge_60s_codes) < 3:
                limit_up_space_ge_60s_codes.add(_code)
                continue
            # 代码,涨停时间
            block_codes_infos.append((_code, int(k[5])))
@@ -1238,11 +1250,13 @@
        @param yesterday_limit_up_codes 昨日涨停代码
        @return:
        """
        # 9:45点之前才能买入
        if not constant.TEST:
            if int(tool.get_now_time_str().replace(":", "")) > 94500:
                return False, "超过生效时间"
        # 9:45点之前涨停的才能买入
        # 获取当前代码的涨停时间
        limit_up_timestamp = LimitUpDataConstant.get_first_limit_up_time(code)
        if not limit_up_timestamp:
            limit_up_timestamp = time.time()
        if int(tool.timestamp_format(limit_up_timestamp, "%H%M%S")) > 94500:
            return False, "超过生效时间"
        # 根据板块聚合数据
        open_limit_up_block_codes_dict = {}
        for c in kpl_data_constant.open_limit_up_code_dict_for_radical_buy:
@@ -1259,27 +1273,50 @@
        history_index, history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes)
        # ----获取实时身位----
        current_index, current_before_codes_info = cls.__get_current_index(code, block, yesterday_limit_up_codes)
        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):
            # 开始数量大于2个或者只有一个2板开1
            if history_index == 0 and current_index == 0:
                return True, f"开1数量:{count}"
            else:
                return False, f"开1数量:{count},非开1首板身位不匹配:历史-{history_index + 1} 实时-{current_index + 1}"
            exclude_codes.clear()
        else:
            # 买老3
            if history_index == 1 and current_index == 1:
                return True, f"开1数量:{count}"
            # 获取包含高位板的身位
            # ----获取历史身位----
            history_index, history_before_codes_info = cls.__get_history_index(code, block, set())
            # ----获取实时身位----
            current_index, current_before_codes_info = cls.__get_current_index(code, block, set())
            if history_before_codes_info and current_before_codes_info and history_before_codes_info[0][0] == \
                    current_before_codes_info[0][0]:
                # 前排第一个元素无炸板
                exclude_codes = {history_before_codes_info[0][0]}
            else:
                return False, f"开1数量:{count},非开1首板身位不匹配:历史-{history_index + 1} 实时-{current_index + 1}"
                return False, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}"
        # 获取主板的身位
        history_index, history_before_codes_info = cls.__get_history_index(code, block,
                                                                           yesterday_limit_up_codes,
                                                                           exclude_codes=exclude_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])[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}"
    @classmethod
    def __is_radical_buy_with_block_up(cls, code, block, yesterday_limit_up_codes):
        """
        是否激进买(板块突然涨起来)
        老大和老二的涨停时间相差5分钟内
        老三的涨停时间距离老大涨停在10分钟内就买
        1.老大和老二的涨停时间相差5分钟内
        2.老三的涨停时间距离老大涨停在10分钟内就买
        3.前2个票不能炸板(历史身位与现在身位一致)
        4.除开前两个代码可买老1与老2
        5.买老2的情况:老1不满足买入条件
        @param code:
        @param block:
        @param yesterday_limit_up_codes:
@@ -1287,25 +1324,44 @@
        """
        # 获取当前的板块
        current_index, current_before_codes_info = cls.__get_current_index(code, block, set())
        current_before_codes = [x[0] for x in current_before_codes_info]
        if len(current_before_codes_info) < 2:
            return False, f"前排代码小于2个"
        if current_before_codes_info[0][1] >= kpl_block_util.open_limit_up_time_range[1]:
            return False, f"有开1"
        if current_index != 2:
            return False, f"只能买老3,当前身位-{current_index + 1}"
        history_index, history_before_codes_info = cls.__get_history_index(code, block, set())
        if history_index != current_index or len(current_before_codes_info) != len(history_before_codes_info):
            return False, f"前排代码有炸板"
            return False, f"前排代码小于2个:{current_before_codes_info}"
        if current_before_codes_info[0][1] < kpl_block_util.open_limit_up_time_range[1]:
            return False, f"有开1:{current_before_codes_info}"
        # 老大,老二必须相隔5分钟内
        if current_before_codes_info[1][1] - current_before_codes_info[0][1] < 5 * 60:
            # 获取当前代码的涨停时间
            limit_up_timestamp = LimitUpDataConstant.get_first_limit_up_time(code)
            if not limit_up_timestamp:
                limit_up_timestamp = time.time()
            if limit_up_timestamp - current_before_codes_info[0][1] < 10 * 60:
                return True, f"前排涨停:{current_before_codes_info}"
        return False, "前排涨停时间间隔不满足条件"
        if current_before_codes_info[1][1] - current_before_codes_info[0][1] >= 5 * 60:
            return False, f"老大老二涨停时间必须间隔5分钟内"
        # 获取当前代码的涨停时间
        limit_up_timestamp = LimitUpDataConstant.get_first_limit_up_time(code)
        if not limit_up_timestamp:
            limit_up_timestamp = time.time()
        if limit_up_timestamp - current_before_codes_info[0][1] >= 10 * 60:
            return False, f"距离老大涨停已过去10分钟({current_before_codes_info[0]})"
        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]
        # 前两个代码是否有炸板
        dif_codes = set(history_before_codes[:2]) - set(current_before_codes[:2])
        if dif_codes:
            return False, f"前2代码有炸板:{dif_codes}"
        # 不计算前2的代码
        exclude_codes = set(current_before_codes[:2])
        history_index, history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes,
                                                                           exclude_codes)
        if history_index > 1:
            return False, f"排除前2,目标代码位于历史身位-{history_index + 1},前排代码:{history_before_codes_info}"
        if history_index == 1:
            # 首板老2,判断前面的老大是否是属于不能买的范畴
            pre_code = history_before_codes_info[0][0]
            # pre_code不能买,才能买
            if RedicalBuyDataManager.can_buy(pre_code)[0]:
                return False, f"前排代码可买:{pre_code}"
        return True, "满足买入需求"
    @classmethod
    def is_radical_buy(cls, code, yesterday_limit_up_codes):
@@ -1333,16 +1389,16 @@
            result = cls.__is_radical_buy_with_open_limitup(code, b, yesterday_limit_up_codes)
            if result[0]:
                can_buy_blocks.add(b)
            msges.append(f"【{b}】:{result}")
            msges.append(f"【{b}】:{result[1]}")
        fmsges.append("开1判断##" + ",".join(msges))
        if not can_buy_blocks:
            msges.clear()
            for b in match_blocks:
            for b in keys_:
                # 板块快速启动
                result = cls.__is_radical_buy_with_block_up(code, b, yesterday_limit_up_codes)
                if result[0]:
                    can_buy_blocks.add(b)
                msges.append(f"【{b}】:{result}")
                msges.append(f"【{b}】:{result[1]}")
            fmsges.append("板块快速启动判断##" + ",".join(msges))
        return can_buy_blocks, " **** ".join(fmsges)
trade/radical_buy_data_manager.py
New file
@@ -0,0 +1,49 @@
"""
激进买数据管理
"""
import constant
from code_attribute import code_nature_analyse, code_volumn_manager, gpcode_manager
from code_attribute.code_l1_data_manager import L1DataManager
from l2.l2_sell_manager import L2MarketSellManager
class RedicalBuyDataManager():
    @classmethod
    def can_buy(cls, code):
        """
        是否可以买
        @param code: 代码
        @param total_sell_volume: 总卖量
        @return:
        """
        k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code)
        if k_format:
            if not k_format[13]:
                return False, "近60个交易日无涨停"
            if k_format[14]:
                # 昨天炸板,且当前的量比小于33%
                current_total_sell_data = L2MarketSellManager().get_current_total_sell_data(code)
                total_sell_volume = 0
                if current_total_sell_data:
                    total_sell_volume = current_total_sell_data[2]
                volume_rate = code_volumn_manager.get_volume_rate(code, total_sell_volume=total_sell_volume)
                if volume_rate < 0.33:
                    return False, f"昨日炸板,量比({volume_rate})<0.33"
        # MAX_CODE_PRICE = 50
        # MIN_CODE_PRICE = 2
        # 获取涨停价
        price = gpcode_manager.get_limit_up_price_as_num(code)
        if not price:
            # 获取现价
            price =  L1DataManager.get_l1_current_price(code)
        if price:
            if price < constant.MIN_CODE_PRICE or price > constant.MAX_CODE_PRICE:
                return False, "价格不满足需求"
        if gpcode_manager.BlackListCodeManager().is_in_cache(code):
            return False, "已拉黑"
        return True, ""
utils/tool.py
@@ -53,6 +53,7 @@
    time_str = datetime.datetime.now().strftime("%H:%M:%S")
    return time_str
def get_now_time_with_ms_str():
    now = datetime.datetime.now()
    ms = int(now.microsecond / 1000)
@@ -183,6 +184,16 @@
    m = seconds % 3600 // 60
    s = seconds % 60
    return "{0:0>2}:{1:0>2}:{2:0>2}.{3:0>3}".format(h, m, s, ms)
def timestamp_format(timestamp, format):
    """
    时间戳格式化
    @param timestamp:
    @param format:
    @return:
    """
    return datetime.datetime.fromtimestamp(timestamp).strftime(format)
# 交易時間的差值
@@ -422,8 +433,4 @@
if __name__ == "__main__":
    print(get_now_time_with_ms_str())
    print(get_now_time_with_ms_str())
    print(get_now_time_with_ms_str())
    time.sleep(0.001)
    print(get_now_time_with_ms_str())
    print(timestamp_format(1726034271, "%H%M%S"))