| | |
| | | from log_module import async_log_util |
| | | from third_data import code_plate_key_manager |
| | | from trade.buy_radical import radical_buy_data_manager |
| | | from trade.buy_radical.radical_buy_data_manager import BeforeSubDealBigOrderManager |
| | | |
| | | from utils import tool |
| | | from l2.transaction_progress import TradeBuyQueue |
| | | from trade import l2_trade_factor, trade_record_log_util, trade_constant |
| | |
| | | if cancel_result[0]: |
| | | return True, f"S慢砸:{cancel_result[1]}" |
| | | # 卖金额>=均大单才触发重新囊括 |
| | | THRESHOLD_MONEY, is_temp_threshold_money = BeforeSubDealBigOrderManager().get_big_order_threshold_info(code) |
| | | THRESHOLD_MONEY, is_temp_threshold_money = radical_buy_data_manager.BeforeSubDealBigOrderManager().get_big_order_threshold_info( |
| | | code) |
| | | if total_deal_money >= THRESHOLD_MONEY: |
| | | l2_log.s_cancel_debug(code, "准备更新L后囊括") |
| | | start_order_no = big_sell_order_info[1][-1][4][1] |
| | |
| | | |
| | | # 获取撤单比例,返回(撤单比例,是否必买) |
| | | @classmethod |
| | | def get_cancel_rate(cls, code, buy_exec_time, is_up=False, is_l_down_recomputed=False, buy_mode=None): |
| | | def get_cancel_rate(cls, code, is_up=False, is_l_down_recomputed=False, buy_mode=None): |
| | | try: |
| | | must_buy = cls.__MustBuyCodesManager.is_in_cache(code) |
| | | if buy_mode == OrderBeginPosInfo.MODE_RADICAL: |
| | |
| | | # 根据成交额的大单成交占比来计算撤单比例 |
| | | big_money_rate = radical_buy_data_manager.TotalDealBigOrderInfoManager.get_big_order_rate(code) |
| | | if big_money_rate is not None: |
| | | threshold_rate = min(big_money_rate*3, 0.95) |
| | | threshold_rate = min(big_money_rate * 3, 0.95) |
| | | return threshold_rate, False |
| | | else: |
| | | deal_big_order_info = radical_buy_data_manager.get_total_deal_big_order_info(code, |
| | |
| | | if temp_count >= 10: |
| | | # 获取中位数 |
| | | min_num = not_cancel_indexes_with_num[temp_count // 2][1] |
| | | MIN_MONEYS = [300, 200, 100, 50] |
| | | MIN_MONEYS = [300, 200, 100] |
| | | watch_indexes = set() |
| | | for min_money in MIN_MONEYS: |
| | | for i in range(end_index, re_start_index - 1, -1): |
| | |
| | | # 计算监听的总条数 |
| | | total_num = 0 |
| | | max_num = 0 |
| | | thresh_hold_rate, must_buy = LCancelRateManager.get_cancel_rate(code, |
| | | total_data[buy_exec_index]["val"]["time"]) |
| | | thresh_hold_rate, must_buy = LCancelRateManager.get_cancel_rate(code) |
| | | |
| | | for wi in watch_indexes: |
| | | if str(wi) in after_place_order_index_dict: |
| | |
| | | canceled_num = 0 |
| | | # 记录撤单索引 |
| | | canceled_indexes = [] |
| | | |
| | | deal_order_nos = HuaXinBuyOrderManager().get_deal_buy_order_nos(code) |
| | | if deal_order_nos is None: |
| | | deal_order_nos = set() |
| | | trade_index, is_default = TradeBuyQueue().get_traded_index(code) |
| | | if is_default: |
| | | trade_index = None |
| | | canceled_buyno_map = local_today_canceled_buyno_map.get(code) |
| | | for wi in watch_indexes: |
| | | cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, |
| | | wi, |
| | | total_data, |
| | | local_today_canceled_buyno_map.get( |
| | | code)) |
| | | cancel_data = L2DataComputeUtil.is_canceled(code, wi, total_data, canceled_buyno_map, trade_index, deal_order_nos) |
| | | if cancel_data: |
| | | if str(wi) in after_place_order_index_dict: |
| | | # 真实下单位置之后的按照权重比例来计算 |
| | |
| | | 10 - after_place_order_index_by_dict[str(wi)]) // 10 |
| | | else: |
| | | canceled_num += total_data[wi]["val"]["num"] |
| | | |
| | | canceled_indexes.append(cancel_data["index"]) |
| | | # if wi == watch_indexes_list[-1] and left_count == 0: |
| | | # # 离下单位置最近的一个撤单,必须触发撤单 |
| | |
| | | temp_thresh_hold_rate = round((total_num - max_num) * 0.9 / total_num, 2) |
| | | if thresh_hold_rate > temp_thresh_hold_rate: |
| | | # 目标撤单比例大于大单撤单比例就取比例均值 |
| | | thresh_hold_rate = round((thresh_hold_rate+temp_thresh_hold_rate)/2, 2) |
| | | thresh_hold_rate = round((thresh_hold_rate + temp_thresh_hold_rate) / 2, 2) |
| | | |
| | | l2_log.l_cancel_debug(code, |
| | | f"L后计算范围:{start_index}-{end_index},已撤单比例:{rate}/{thresh_hold_rate}, 下单位之后的索引:{after_place_order_index_dict}") |
| | |
| | | else: |
| | | canceled_count_weight += WATCH_INDEX_WEIGHTS[-1] |
| | | rate = round(canceled_count_weight / total_count_weight, 3) |
| | | thresh_cancel_rate, must_buy = LCancelRateManager.get_cancel_rate(code, |
| | | total_data[buy_exec_index]["val"]["time"], |
| | | is_up=True) |
| | | thresh_cancel_rate, must_buy = LCancelRateManager.get_cancel_rate(code, is_up=True) |
| | | l2_log.l_cancel_debug(code, f"计算范围:{start_index}-{end_index},L前已撤单比例:{rate}/{thresh_cancel_rate}") |
| | | if rate >= thresh_cancel_rate: |
| | | # 计算成交进度位置到当前下单位置的纯买额 |
| | |
| | | |
| | | return False, None |
| | | |
| | | # L后重新囊括的时间 |
| | | __recompute_l_down_time_dict = {} |
| | | |
| | | def set_big_sell_order_info(self, code, big_sell_order_info): |
| | | """ |
| | | 设置大卖单信息 |
| | | @param code: |
| | | @param big_sell_order_info: |
| | | @return: |
| | | """ |
| | | if not big_sell_order_info or not big_sell_order_info[0] or not big_sell_order_info[1]: |
| | | return False, "" |
| | | |
| | | total_datas = local_today_datas.get(code) |
| | | # 查询是否是真的真实下单位置 |
| | | trade_index, is_default = TradeBuyQueue().get_traded_index(code) |
| | | if trade_index is None: |
| | | trade_index = 0 |
| | | real_order_index_info = self.get_real_place_order_index_info(code) |
| | | if real_order_index_info is None or real_order_index_info[1]: |
| | | return False, "没找到真实下单位" |
| | | real_order_index = real_order_index_info[0] |
| | | total_deal_money = sum([x[1] * x[2] for x in big_sell_order_info[1]]) |
| | | start_order_no = big_sell_order_info[1][0][3][1] |
| | | # 防止分母位0 |
| | | total_num = 1 |
| | | # 获取正在成交的数据 |
| | | dealing_info = HuaXinBuyOrderManager.get_dealing_order_info(code) |
| | | for i in range(trade_index, real_order_index): |
| | | data = total_datas[i] |
| | | val = data['val'] |
| | | if not L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | if int(val['orderNo']) < start_order_no: |
| | | continue |
| | | if i == trade_index and dealing_info and str(total_datas[trade_index]["val"]["orderNo"]) == str( |
| | | dealing_info[0]): |
| | | # 减去当前正在成交的数据中已经成交了的数据 |
| | | total_num -= dealing_info[1] // 100 |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code, i, |
| | | total_datas, |
| | | local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if left_count > 0: |
| | | total_num += val["num"] |
| | | |
| | | # 卖金额>=均大单才触发重新囊括 |
| | | THRESHOLD_MONEY = radical_buy_data_manager.BeforeSubDealBigOrderManager().get_big_sell_order_threshold(code) |
| | | if total_deal_money >= THRESHOLD_MONEY: |
| | | l2_log.l_cancel_debug(code, "准备更新L后囊括(大卖单)") |
| | | start_order_no = big_sell_order_info[1][-1][4][1] |
| | | latest_deal_time_ms = l2_huaxin_util.convert_time(big_sell_order_info[1][-1][4][0], with_ms=True) |
| | | real_trade_index = None |
| | | for i in range(trade_index, real_order_index): |
| | | data = total_datas[i] |
| | | val = data['val'] |
| | | if not L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | if int(val['orderNo']) < start_order_no: |
| | | continue |
| | | real_trade_index = i |
| | | break |
| | | if real_trade_index is None: |
| | | l2_log.l_cancel_debug(code, f"没找到真实的成交进度(大卖单):start_order_no-{start_order_no} 卖单-{big_sell_order_info}") |
| | | return False, "" |
| | | # 间隔1S以上才能重新囊括 |
| | | if code in self.__recompute_l_down_time_dict and tool.trade_time_sub_with_ms(latest_deal_time_ms, |
| | | self.__recompute_l_down_time_dict[ |
| | | code]) < 1000: |
| | | l2_log.s_cancel_debug(code, |
| | | f"更新L后囊括(大卖单):更新间隔在1s内,{latest_deal_time_ms}-{self.__recompute_l_down_time_dict[code]}") |
| | | return False, "" |
| | | self.__recompute_l_down_time_dict[code] = latest_deal_time_ms |
| | | # 重新囊括L后 |
| | | # 撤单时间比早成交时间大就需要计算在里面 |
| | | self.re_compute_l_down_watch_indexes(code, big_sell_info=( |
| | | real_trade_index, latest_deal_time_ms)) |
| | | l2_log.l_cancel_debug(code, f"更新L后囊括完成(大卖单):{(real_trade_index, latest_deal_time_ms)}") |
| | | else: |
| | | l2_log.l_cancel_debug(code, f"大卖单金额不足({THRESHOLD_MONEY})") |
| | | return False, "" |
| | | |
| | | # L后是否还有可能撤单 |
| | | def __is_l_down_can_cancel(self, code, buy_exec_index): |
| | | watch_indexes_info = self.__get_watch_indexes_cache(code) |
| | |
| | | total_nums += val["num"] |
| | | if left_count > 0 and index < trade_index: |
| | | total_deal_nums += val["num"] |
| | | thresh_hold_rate, must_buy = LCancelRateManager.get_cancel_rate(code, |
| | | total_datas[buy_exec_index]["val"]["time"]) |
| | | thresh_hold_rate, must_buy = LCancelRateManager.get_cancel_rate(code) |
| | | if total_deal_nums / total_nums > 1 - thresh_hold_rate - 0.05: |
| | | return False |
| | | return True |
| | |
| | | @return: |
| | | """ |
| | | total_datas = local_today_datas.get(code) |
| | | MIN_MONEYS = [300, 200, 100, 50] |
| | | MIN_MONEYS = [300, 200, 100] |
| | | watch_indexes = set() |
| | | for min_money in MIN_MONEYS: |
| | | for i in range(end_index, start_index - 1, -1): |