| | |
| | | import time |
| | | |
| | | import constant |
| | | from code_attribute import big_money_num_manager, gpcode_manager |
| | | from code_attribute import big_money_num_manager, gpcode_manager, code_volumn_manager |
| | | import l2_data_util |
| | | from db import redis_manager_delegate as redis_manager |
| | | from db.redis_manager_delegate import RedisUtils |
| | |
| | | LCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index=buy_single_index, |
| | | is_default=is_default) |
| | | HourCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index) |
| | | GCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index, is_default) |
| | | NewGCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index, is_default) |
| | | FCancelBigNumComputer().set_real_order_index(code, index, is_default) |
| | | |
| | | |
| | |
| | | def cancel_success(self, code): |
| | | self.clear(code) |
| | | |
| | | def __get_fast_deal_threshold_value(self, code): |
| | | """ |
| | | 获取 F撤阈值 |
| | | @param code: |
| | | @return:(金额(单位:W),笔数) |
| | | """ |
| | | max60, yesterday = code_volumn_manager.get_histry_volumn(code) |
| | | if max60: |
| | | num = max60[0] |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price: |
| | | money_y = round((num * float(limit_up_price))/1e8,1) |
| | | money =int(200*money_y + 280) |
| | | count = int(money_y*10)//10 + 3 |
| | | return money,count |
| | | # 默认值 |
| | | return 300,3 |
| | | |
| | | # 下单3分钟内距离下单位置不足3笔(包含正在成交)且不到300w就需要撤单 |
| | | def need_cancel_for_deal_fast(self, code, trade_index=None): |
| | | if trade_index is None: |
| | |
| | | if tool.trade_time_sub(tool.get_now_time_str(), total_datas[real_order_index]['val']['time']) > 3 * 60: |
| | | return False, "下单超过180s" |
| | | |
| | | THRESHOLD_COUNT = 3 |
| | | THRESHOLD_MONEY_W, THRESHOLD_COUNT = self.__get_fast_deal_threshold_value(code) |
| | | |
| | | total_left_count = 0 |
| | | total_left_num = 0 |
| | |
| | | total_left_num -= dealing_info[1] // 100 |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if total_left_count <= 1 or (total_left_count <= THRESHOLD_COUNT and limit_up_price and total_left_num * float( |
| | | limit_up_price) < 300 * 100): |
| | | return True, f"剩余笔数({total_left_count})/金额({round(total_left_num * float(limit_up_price) * 100)})不足,成交进度:{trade_index},真实下单位置:{real_order_index}" |
| | | limit_up_price) < THRESHOLD_MONEY_W * 100): |
| | | return True, f"剩余笔数({total_left_count})/金额({round(total_left_num * float(limit_up_price) * 100)})不足,成交进度:{trade_index},真实下单位置:{real_order_index} 阈值:({THRESHOLD_MONEY_W},{THRESHOLD_COUNT}) " |
| | | return False, f"不满足撤单条件: 成交进度-{trade_index} 真实下单位置-{real_order_index} total_left_count-{total_left_count} total_left_num-{total_left_num}" |
| | | |
| | | # 距离太近,封单不足,有大单50w大单砸下来就撤 |
| | |
| | | origin_watch_index = self.__watch_indexes_dict.get(code) |
| | | if origin_watch_index is None: |
| | | origin_watch_index = set() |
| | | # 不需要备用 |
| | | origin_watch_index_by = self.__watch_indexes_by_dict.get(code) |
| | | if origin_watch_index_by is None: |
| | | origin_watch_index_by = set() |
| | |
| | | def cancel_success(self, code): |
| | | self.clear(code) |
| | | |
| | | # ---------------------------------新G撤------------------------------- |
| | | class NewGCancelBigNumComputer: |
| | | __real_place_order_index_dict = {} |
| | | __trade_progress_index_dict = {} |
| | | __watch_indexes_dict = {} |
| | | # 最新处理的卖单 |
| | | __latest_process_sell_order_no_dict = {} |
| | | |
| | | __instance = None |
| | | |
| | | def __new__(cls, *args, **kwargs): |
| | | if not cls.__instance: |
| | | cls.__instance = super(NewGCancelBigNumComputer, cls).__new__(cls, *args, **kwargs) |
| | | return cls.__instance |
| | | |
| | | def set_real_place_order_index(self, code, index, buy_single_index, is_default): |
| | | self.__real_place_order_index_dict[code] = (index, is_default) |
| | | start_index = buy_single_index |
| | | if code in self.__trade_progress_index_dict: |
| | | start_index = self.__trade_progress_index_dict.get(code) |
| | | self.__commpute_watch_indexes(code, start_index, (index, is_default), from_real_order_index_changed=True) |
| | | |
| | | def clear(self, code=None): |
| | | if code: |
| | | if code in self.__real_place_order_index_dict: |
| | | self.__real_place_order_index_dict.pop(code) |
| | | if code in self.__watch_indexes_dict: |
| | | self.__watch_indexes_dict.pop(code) |
| | | if code in self.__trade_progress_index_dict: |
| | | self.__trade_progress_index_dict.pop(code) |
| | | else: |
| | | self.__real_place_order_index_dict.clear() |
| | | self.__watch_indexes_dict.clear() |
| | | self.__trade_progress_index_dict.clear() |
| | | |
| | | # recompute:是否重新计算 |
| | | def __commpute_watch_indexes(self, code, traded_index, real_order_index_info, from_real_order_index_changed=False, |
| | | recompute=False): |
| | | if traded_index is None or real_order_index_info is None: |
| | | return |
| | | real_order_index, is_default = real_order_index_info[0], real_order_index_info[1] |
| | | origin_watch_index = self.__watch_indexes_dict.get(code) |
| | | if origin_watch_index is None: |
| | | origin_watch_index = set() |
| | | # 重新计算需要清除之前的数据 |
| | | if recompute: |
| | | origin_watch_index.clear() |
| | | |
| | | start_index = traded_index |
| | | if traded_index in origin_watch_index: |
| | | # 正在成交的是已经囊括了的大单 |
| | | start_index = traded_index + 1 |
| | | |
| | | total_datas = local_today_datas.get(code) |
| | | watch_indexes = set() |
| | | for i in range(start_index, real_order_index): |
| | | # 判断是否有未撤的大单 |
| | | data = total_datas[i] |
| | | val = data["val"] |
| | | if not L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | if val["num"] * float(val["price"]) < 29900: |
| | | continue |
| | | # 是否已撤单 |
| | | 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: |
| | | watch_indexes.add(i) |
| | | if watch_indexes: |
| | | # 还有300万以上的大单没有撤单 |
| | | if from_real_order_index_changed or recompute: |
| | | # 真实下单位改变后才会更新 |
| | | final_watch_indexes = origin_watch_index | watch_indexes |
| | | self.__watch_indexes_dict[code] = final_watch_indexes |
| | | l2_log.g_cancel_debug(code, f"大单监听:{final_watch_indexes} 是否重新计算:{recompute}") |
| | | |
| | | def set_trade_progress(self, code, buy_single_index, index): |
| | | if self.__trade_progress_index_dict.get(code) != index: |
| | | self.__trade_progress_index_dict[code] = index |
| | | self.__commpute_watch_indexes(code, index, self.__real_place_order_index_dict.get(code)) |
| | | |
| | | def need_cancel(self, code, buy_exec_index, start_index, end_index): |
| | | if code not in self.__real_place_order_index_dict: |
| | | return False, None, "没有找到真实下单位" |
| | | |
| | | real_place_order_index, is_default = self.__real_place_order_index_dict.get(code) |
| | | total_datas = local_today_datas.get(code) |
| | | |
| | | # if tool.trade_time_sub(total_datas[end_index]["val"]["time"], total_datas[buy_exec_index]['val']['time']) > 180: |
| | | # return False, None, "超过180s的生效时间" |
| | | |
| | | watch_indexes = self.__watch_indexes_dict.get(code) |
| | | if watch_indexes is None: |
| | | watch_indexes = set() |
| | | if len(watch_indexes) < 3: |
| | | return False, None, "大于等于3个大单生效" |
| | | |
| | | need_compute = False |
| | | for i in range(start_index, end_index + 1): |
| | | data = total_datas[i] |
| | | val = data["val"] |
| | | if not L2DataUtil.is_limit_up_price_buy_cancel(val): |
| | | continue |
| | | if val["num"] * float(val["price"]) < 5000: |
| | | continue |
| | | buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data_v2(data, |
| | | local_today_buyno_map.get( |
| | | code)) |
| | | if buy_index is not None and buy_index < real_place_order_index and (buy_index in watch_indexes): |
| | | if buy_index in watch_indexes: |
| | | # 大单撤需要重新计算大单撤单比例 |
| | | need_compute = True |
| | | break |
| | | if need_compute and watch_indexes: |
| | | canceled_indexes = set() |
| | | for index in watch_indexes: |
| | | cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, index, |
| | | total_datas, |
| | | local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if cancel_data: |
| | | canceled_indexes.add(cancel_data["index"]) |
| | | cancel_rate = round(len(canceled_indexes) / len(watch_indexes), 2) |
| | | threshhold_rate = constant.G_CANCEL_RATE |
| | | situation = trade_manager.MarketSituationManager().get_situation_cache() |
| | | if situation == trade_manager.MarketSituationManager.SITUATION_GOOD: |
| | | threshhold_rate = constant.G_CANCEL_RATE_FOR_GOOD_MARKET |
| | | if gpcode_manager.MustBuyCodesManager().is_in_cache(code): |
| | | threshhold_rate = constant.G_CANCEL_RATE_WITH_MUST_BUY |
| | | if cancel_rate > threshhold_rate: |
| | | canceled_indexes_list = list(canceled_indexes) |
| | | canceled_indexes_list.sort() |
| | | return True, total_datas[canceled_indexes_list[-1]], f"撤单比例:{cancel_rate}" |
| | | return False, None, "" |
| | | |
| | | def place_order_success(self, code): |
| | | self.clear(code) |
| | | |
| | | def cancel_success(self, code): |
| | | self.clear(code) |
| | | |
| | | # B撤单 |
| | | # 剩余一个大单撤半截就撤单 |
| | | def need_cancel_for_b(self, code, start_index, end_index): |
| | | real_place_order_info = self.__real_place_order_index_dict.get(code) |
| | | if not real_place_order_info or real_place_order_info[1]: |
| | | # 没有真实下单位置 |
| | | return False, None, "没有真实下单位置" |
| | | trade_index, is_default = TradeBuyQueue().get_traded_index(code) |
| | | if trade_index is None: |
| | | return False, None, "未获取到成交进度位" |
| | | total_datas = local_today_datas.get(code) |
| | | buyno_map = local_today_buyno_map.get(code) |
| | | cancel_half_index = None |
| | | for i in range(start_index, end_index + 1): |
| | | data = total_datas[i] |
| | | val = data['val'] |
| | | if not L2DataUtil.is_limit_up_price_buy_cancel(val): |
| | | continue |
| | | orderNo = val['orderNo'] |
| | | buy_data = buyno_map.get(f"{orderNo}") |
| | | if not buy_data: |
| | | continue |
| | | # 判断大单 |
| | | if buy_data["val"]["num"] * float(buy_data["val"]["price"]) < 29900: |
| | | continue |
| | | # 判断是否撤半截 |
| | | if buy_data["val"]["num"] > val["num"]: |
| | | cancel_half_index = i |
| | | break |
| | | if cancel_half_index is None: |
| | | return False, None, "没有撤半截" |
| | | # 有大单撤半截桩 |
| | | # 计算是否还剩下大单 |
| | | total_big_num_count = 0 |
| | | for i in range(trade_index, real_place_order_info[0]): |
| | | data = total_datas[i] |
| | | val = data['val'] |
| | | if not L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | if val["num"] * float(val["price"]) < 29900: |
| | | continue |
| | | 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_big_num_count += 1 |
| | | break |
| | | if total_big_num_count == 0: |
| | | # 没有剩下大单 |
| | | return True, total_datas[cancel_half_index], f"B撤:撤单索引-{cancel_half_index}" |
| | | return False, None, "还有大单没撤单" |
| | | |
| | | |
| | | |
| | | |
| | | # ---------------------------------独苗撤------------------------------- |
| | | class UCancelBigNumComputer: |