""" 激进买策略管理 """ # 上一个50W的起始时间:{code:"09:30:00.120"} import time from code_attribute import code_volumn_manager, gpcode_manager from l2.code_price_manager import Buy1PriceManager from l2.huaxin import l2_huaxin_util from l2.l2_limitup_sell_data_manager import L2LimitUpSellDataManager from l2.l2_sell_manager import L2MarketSellManager from l2.l2_transaction_data_manager import HuaXinSellOrderStatisticManager, BigOrderDealManager from log_module import async_log_util from log_module.log import logger_l2_radical_buy, hx_logger_l2_transaction, logger_l2_not_buy_reasons from third_data import kpl_data_manager from third_data.kpl_data_constant import LimitUpDataConstant, LimitUpCodesBlockRecordManager from trade.buy_radical import radical_buy_data_manager, block_special_codes_manager from trade.buy_radical.block_special_codes_manager import BlockSpecialCodesManager from trade.buy_radical.radical_buy_data_manager import RadicalBuyBlockManager, TotalDealBigOrderThresholdMoneyManager from trade.trade_data_manager import RadicalBuyDealCodesManager from utils import tool, global_util # 不买入 BUY_MODE_NONE = 0 # 直接买入 BUY_MODE_DIRECT = 1 # 根据L2买入 BUY_MODE_BY_L2 = 2 # 开始计时时间 __start_time_dict = {} # 转换时间缓存 __huaxin_timestamp_convert_temp = {} # 主动成交的累计金额 __deal_active_buy_total_money = {} # 最近成交的买单信息{code:[订单号,量,金额]} __latest_deal_active_buy_order = {} def clear_data(code, force=False, market_time_str=None, msg=""): """ 清除数据:下单过后/开板后清除数据 @param market_time_str: L2 market时间 @param force: 是否强制清除 @param code: @return: """ if code in __latest_deal_active_buy_order: __latest_deal_active_buy_order.pop(code) if not force: # 非强制清除数据要看大单成交是否足够 big_deal_info = radical_buy_data_manager.get_total_deal_big_order_info(code, gpcode_manager.get_limit_up_price_as_num( code)) if big_deal_info[0] > 0: # 大单不够 force = True if force: # 如果比最近成交时间<=L2 market时间就视为数据延迟 if market_time_str and code in RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict: if tool.trade_time_sub(market_time_str, RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict[code][3]) <= 0: async_log_util.info(logger_l2_radical_buy, f"L2market时间小于成交时间:{code}-{market_time_str}") return if __deal_active_buy_total_money.get(code): async_log_util.info(logger_l2_radical_buy, f"清除涨停卖成交数据:{code}-{market_time_str}") # 强制清除数据 if code in __deal_active_buy_total_money: __deal_active_buy_total_money.pop(code) # 清除L2下单信号 if code in RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict: async_log_util.info(logger_l2_radical_buy, f"清除下单信号:{code}-{force}-{market_time_str} msg-{msg}") RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict.pop(code) def process_limit_up_active_buy_deal(code, transaction_datas, is_almost_open_limit_up=False, no_left_limit_up_sell=False): """ 计算抛压消耗之后是否能下单 @param code: @param transaction_datas: # ((data['SecurityID'], data['TradePrice'], data['TradeVolume'], # data['OrderTime'], data['MainSeq'], data['SubSeq'], data['BuyNo'], # data['SellNo'], data['ExecType'])) @param is_almost_open_limit_up: 是否即将炸板,如果即将炸板就按照上板无大单处理 @return: 买入方式, 消息 """ if is_almost_open_limit_up: return BUY_MODE_BY_L2, f"即将炸板" # ---------初始化------------- if code not in __huaxin_timestamp_convert_temp: __huaxin_timestamp_convert_temp[code] = {} if code not in __deal_active_buy_total_money: __deal_active_buy_total_money[code] = 0 if code not in __latest_deal_active_buy_order: __latest_deal_active_buy_order[code] = ['', 0, 0] for transaction_data in transaction_datas: # 当遇到大单之后才需要计算累计成交 # 统计金额 money = transaction_data[1] * transaction_data[2] price = transaction_data[1] # 统计成交的买单 if __latest_deal_active_buy_order[code][0] == transaction_data[6]: __latest_deal_active_buy_order[code][1] += transaction_data[2] __latest_deal_active_buy_order[code][2] += money else: __latest_deal_active_buy_order[code] = [transaction_data[6], transaction_data[2], money] if code not in __start_time_dict and False: # 判断买单成交的金额,如果金额大于50w就作为计时起始点 if __latest_deal_active_buy_order[code][2] >= 500000: # 设置计时起点,将当前的数据清零 __start_time_dict[code] = l2_huaxin_util.convert_time(transaction_data[3], with_ms=True) __deal_active_buy_total_money[code] = __latest_deal_active_buy_order[code][2] else: __deal_active_buy_total_money[code] += money # 已经开始计数 # THRESHOLD_TIME = 1000 if tool.is_sh_code(code) else 500 # huaxin_timestamp = transaction_data[3] # time_str_with_ms = __huaxin_timestamp_convert_temp[code].get(huaxin_timestamp) # if not time_str_with_ms: # __huaxin_timestamp_convert_temp[code].clear() # time_str_with_ms = l2_huaxin_util.convert_time(huaxin_timestamp, with_ms=True) # __huaxin_timestamp_convert_temp[code][huaxin_timestamp] = time_str_with_ms # if tool.trade_time_sub_with_ms(time_str_with_ms, __start_time_dict[code]) > THRESHOLD_TIME: # __start_time_dict.pop(code) # __deal_active_buy_total_money[code] = 0 # return BUY_MODE_NONE, f"距离上个大单成交超过{THRESHOLD_TIME}ms" # 初次上板需要计算临时大单 is_first = radical_buy_data_manager.is_first_limit_up_buy(code) if is_first: # 首封下单 money_info_list = BigOrderDealManager().get_total_buy_data_list(code) radical_buy_data_manager.BeforeSubDealBigOrderManager().set_temp_deal_big_orders(code, money_info_list) price = transaction_datas[-1][1] huaxin_timestamp = transaction_datas[-1][3] # 判断是否可以扫入 can_direct_buy = False human_setting_money = TotalDealBigOrderThresholdMoneyManager().get_money_cache(code) if human_setting_money: can_direct_buy = True # 获取参考总卖额 refer_sell_data = L2MarketSellManager().get_refer_sell_data(code, l2_huaxin_util.convert_time( huaxin_timestamp)) async_log_util.info(logger_l2_radical_buy, f"参考总卖额(备用):{code}-{refer_sell_data}") # 参考总卖额 refer_sell_money = 0 if refer_sell_data: refer_sell_money = refer_sell_data[1] if refer_sell_money < 500e4: # 参考抛压小于500万,直接根据L2下单 return BUY_MODE_BY_L2, f"总抛压小于500w({refer_sell_money})" # 处于涨停卖的委托订单总手数 selling_num = L2LimitUpSellDataManager.get_delegating_sell_num(code) if selling_num is None: selling_num = 0 # 剩余涨停卖金额 left_limit_up_sell_money = selling_num * price # 每次上板的大单与金额 big_order_count = radical_buy_data_manager.EveryLimitupBigDealOrderManager.get_big_buy_deal_order_count(code) big_order_money = radical_buy_data_manager.EveryLimitupBigDealOrderManager.get_big_buy_deal_order_money(code) total_lack_money_info = radical_buy_data_manager.get_total_deal_big_order_info(code, gpcode_manager.get_limit_up_price_as_num( code), is_for_buy=True) if total_lack_money_info[2] < 1e8: # 要求的大单阈值必须>1亿才能直接扫入 can_direct_buy = False if total_lack_money_info and total_lack_money_info[2] > 1e8 and total_lack_money_info[0] <= 0: # 要求的大单够了 以后,回封买,只要有两个大单成交了,立即下单 THRESHOLD_MONEY, is_temp_threshold_money = radical_buy_data_manager.BeforeSubDealBigOrderManager().get_big_order_threshold_info( code) if big_order_money > THRESHOLD_MONEY * 2 and can_direct_buy: return BUY_MODE_DIRECT, f"有两个以上大单瞬时成交({big_order_money}/{THRESHOLD_MONEY * 2}), 大单足够" if big_order_count >= 2: # 判断大单是否满足 average_big_order_money = int(big_order_money / big_order_count) # 如果均价涨幅小于7%,均大单等于299w average_rate = Buy1PriceManager().get_average_rate(code) if average_rate is not None and average_rate < 0.07: average_big_order_money = 299 * 10000 threshold_left_sell_money = average_big_order_money # 辨识度的票如果是非新题材的首封: 2个大单的折扣 # if block_special_codes_manager.BlockSpecialCodesManager().get_code_blocks(code) and radical_buy_data_manager.is_first_limit_up_buy(code) and not LimitUpCodesBlockRecordManager().has_new_block( # code): # threshold_left_sell_money = average_big_order_money * 2 # 判断是否可直接下单,不需要等到封单消耗 # if refer_sell_money >= 5e7 and is_first: # # 大抛压,是首封 # zyltgb = global_util.zyltgb_map.get(code) # if zyltgb and zyltgb > 50e8 and BlockSpecialCodesManager().get_code_blocks(code): # # 自由市值>50亿,具有辨识度 # total_lack_money_info = radical_buy_data_manager.get_total_deal_big_order_info(code, # gpcode_manager.get_limit_up_price_as_num( # code), # is_for_buy=True) # if total_lack_money_info[0] <= 0 and total_lack_money_info[1] > 5e7 and total_lack_money_info[1] > \ # total_lack_money_info[2] * 1.5: # # 大单足够,总成交金额是大单的1.2倍以上 # return BUY_MODE_DIRECT, f"首封下单抛压大、市值大、成交多、直接扫 卖1-{refer_sell_money} 大单-{total_lack_money_info}" if threshold_left_sell_money > left_limit_up_sell_money: # 剩余总卖小于均大单才能下单 # 如果是深证且卖一大于5000w可不判断大单是否满足 if tool.is_sz_code(code) and refer_sell_money >= 5e7 and can_direct_buy: return BUY_MODE_DIRECT, f"剩余涨停总卖额-{left_limit_up_sell_money},均大单-{average_big_order_money}, 剩余阈值-{threshold_left_sell_money}, 总抛压大({refer_sell_money})" else: if total_lack_money_info[0] <= 0 and tool.is_sz_code(code) and can_direct_buy: return BUY_MODE_DIRECT, f"剩余涨停总卖额-{left_limit_up_sell_money},均大单-{average_big_order_money}, 大单足够" else: average_big_order_money = 0 # 如果剩余总卖小于100w直接根据L2买入 if left_limit_up_sell_money < 100e4 or no_left_limit_up_sell: return BUY_MODE_BY_L2, f"剩余总卖小于100w({left_limit_up_sell_money}) 是否还有剩余涨停卖-{no_left_limit_up_sell}" return BUY_MODE_NONE, f"均大单-{average_big_order_money}({big_order_money}/{big_order_count}),剩余涨停卖:{left_limit_up_sell_money}" # #总卖 = 涨停主动买成交的累计金额 + 处于委托状态的涨停卖金额 # total_sell = __deal_active_buy_total_money[code] + left_limit_up_sell_money # if total_sell == 0: # total_sell = 1 # rate = round(__deal_active_buy_total_money[code] / total_sell, 2) # # 获取当前的成交量比 # limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) # volume_rate = code_volumn_manager.CodeVolumeManager().get_volume_rate_refer_in_5days(code, # total_sell_volume=int( # total_sell / limit_up_price)) # if volume_rate is None: # volume_rate = 0.5 # # THRESHOLD_RATE = radical_buy_data_manager.get_volume_rate_threshold(code, volume_rate) # if rate >= THRESHOLD_RATE: # # 根据大单判断是否可以扫 # big_order_deal_result = radical_buy_data_manager.is_big_order_deal_enough(code, volume_rate, # refer_sell_money, for_buy=True) # if big_order_deal_result[0]: # return BUY_MODE_DIRECT, f"剩余涨停总卖额-{selling_num * price},原涨停总卖-{total_sell},已成交额-{__deal_active_buy_total_money[code]},成交比例-{rate}/{THRESHOLD_RATE}, 大单信息-{big_order_deal_result}" # else: # # 无大单成交就只能通过L2下单 # return BUY_MODE_BY_L2, f"无大单成交-{big_order_deal_result},原涨停总卖-{total_sell},已成交额-{__deal_active_buy_total_money[code]},成交比例-{rate}/{THRESHOLD_RATE} " # else: # return BUY_MODE_NONE, f"被动卖成交比例未达到:剩余涨停总卖额-{selling_num * price},原涨停总卖-{total_sell},已成交额-{__deal_active_buy_total_money[code]},成交比例-{rate}/{THRESHOLD_RATE}" def is_can_buy_with_open_price(code, open_price): """ 根据开盘价判断是否可买 @param code: @param open_price: 开盘价没获取到就不判断 @return: """ if tool.get_now_time_as_int() < int("093500") and open_price: async_log_util.info(logger_l2_radical_buy, f"开盘价:{code}-{open_price}") pre_price = gpcode_manager.CodePrePriceManager.get_price_pre_cache(code) if pre_price: rate = round((open_price - pre_price) / pre_price, 4) async_log_util.info(logger_l2_radical_buy, f"开盘价涨幅:{code}-{rate}") if tool.get_limit_up_rate(code) > 1.1: return rate < 0.149 else: return rate < 0.049 return True # 板块缓存 __radical_buy_by_blocks_result_cache = {} def compute_can_radical_buy_blocks(code, deal_codes): """ 计算可以扫入的板块 @param code: @return: 可买板块集合, 过滤后的集合 """ result_cache = __radical_buy_by_blocks_result_cache.get(code) if not result_cache or result_cache[0] < time.time(): # 不存在/过期 yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes() if yesterday_codes is None: yesterday_codes = set() # 计算是否可以扫入 radical_result = RadicalBuyBlockManager.is_radical_buy(code, yesterday_codes) async_log_util.info(logger_l2_radical_buy, f"计算板块结果:{code}-{radical_result}") result_cache = (time.time() + 3, radical_result) __radical_buy_by_blocks_result_cache[code] = result_cache RadicalBuyDealCodesManager().set_code_blocks(code, radical_result[0]) if not radical_result[0]: async_log_util.info(logger_l2_not_buy_reasons, f"{code}#{radical_result[1]}") # 取缓存 result = result_cache[1] if result[0]: # 买入的板块 buy_blocks = result[0] # 如果关键词包含已成交的原因就不再下单 # 获取已经成交代码的板块 # ---------------判断板块是否还可以买入---------------- f_buy_blocks = radical_buy_data_manager.is_block_can_radical_buy(code, buy_blocks, deal_codes) return f_buy_blocks, result[0] return set(), result[0]