| | |
| | | left_num += val['num'] * left_count |
| | | # 剩下的不足动态M值的1/2 |
| | | rate = round(float(limit_up_price) * left_num * 100 / m_base_value, 3) |
| | | l2_log.d_cancel_debug(code, f"成交进度({index})到下单位置({real_order_index})的剩余笔数:{left_num},撤单比例:{rate},m值:{m_base_value}") |
| | | l2_log.d_cancel_debug(code, |
| | | f"成交进度({index})到下单位置({real_order_index})的剩余笔数:{left_num},撤单比例:{rate},m值:{m_base_value}") |
| | | if rate < constant.D_CANCEL_RATE: |
| | | l2_log.cancel_debug(code, "D撤撤单,比例为:{},目标比例{}", rate, constant.D_CANCEL_RATE) |
| | | return True, f"D撤比例为:{rate}" |
| | |
| | | __real_place_order_index_dict = {} |
| | | __cancel_watch_index_cache = {} |
| | | # 成交位附近临近大单索引 |
| | | __near_by_trade_progress_big_num_index_cache = {} |
| | | __near_by_trade_progress_index_cache = {} |
| | | |
| | | __SecondCancelBigNumComputer = SecondCancelBigNumComputer() |
| | | |
| | |
| | | code = k.split("-")[-1] |
| | | val = RedisUtils.smembers(__redis, k) |
| | | CodeDataCacheUtil.set_cache(cls.__cancel_watch_index_cache, code, val) |
| | | keys = RedisUtils.keys(__redis, "l_cancel_near_by_big_num_index-*") |
| | | keys = RedisUtils.keys(__redis, "l_cancel_near_by_index-*") |
| | | for k in keys: |
| | | code = k.split("-")[-1] |
| | | val = RedisUtils.get(__redis, k) |
| | | val = int(val) |
| | | CodeDataCacheUtil.set_cache(cls.__near_by_trade_progress_big_num_index_cache, code, val) |
| | | try: |
| | | val = set(json.loads(val)) |
| | | CodeDataCacheUtil.set_cache(cls.__near_by_trade_progress_index_cache, code, val) |
| | | except: |
| | | pass |
| | | finally: |
| | | RedisUtils.realse(__redis) |
| | | |
| | |
| | | return cache_result[1] |
| | | return set() |
| | | |
| | | def __set_near_by_big_num_index(self, code, index): |
| | | self.__near_by_trade_progress_big_num_index_cache[code] = index |
| | | RedisUtils.setex_async(self.__db, f"l_cancel_near_by_big_num_index-{code}", tool.get_expire(), index) |
| | | def __set_near_by_trade_progress_indexes(self, code, indexes): |
| | | self.__near_by_trade_progress_index_cache[code] = indexes |
| | | RedisUtils.setex_async(self.__db, f"l_cancel_near_by_index-{code}", tool.get_expire(), |
| | | json.dumps(list(indexes))) |
| | | |
| | | def __get_near_by_big_num_index(self, code): |
| | | val = RedisUtils.get(self.__get_redis(), f"l_cancel_near_by_big_num_index-{code}") |
| | | def __get_near_by_trade_progress_indexes(self, code): |
| | | val = RedisUtils.get(self.__get_redis(), f"l_cancel_near_by_index-{code}") |
| | | if val is None: |
| | | return None |
| | | return int(val) |
| | | return set(json.loads(val)) |
| | | |
| | | def __get_near_by_big_num_index_cache(self, code): |
| | | cache_result = CodeDataCacheUtil.get_cache(self.__near_by_trade_progress_big_num_index_cache, code) |
| | | def __get_near_by_trade_progress_indexes_cache(self, code): |
| | | cache_result = CodeDataCacheUtil.get_cache(self.__near_by_trade_progress_index_cache, code) |
| | | if cache_result[0]: |
| | | return cache_result[1] |
| | | return None |
| | |
| | | self.__real_place_order_index_dict[code] = index |
| | | if self.__last_trade_progress_dict.get(code): |
| | | self.compute_watch_index(code, self.__last_trade_progress_dict.get(code), index) |
| | | self.__compute_trade_progress_near_by_indexes(code, self.__last_trade_progress_dict.get(code) + 1, index) |
| | | else: |
| | | if buy_single_index: |
| | | self.compute_watch_index(code, buy_single_index, index) |
| | | self.__compute_trade_progress_near_by_indexes(code, buy_single_index, index) |
| | | |
| | | # 计算范围内的成交位临近未撤大单 |
| | | def __compute_near_by_big_num_index(self, code, start_index, end_index, total_datas): |
| | | MIN_MONEYS = [300, 200, 100, 50] |
| | | for min_money in MIN_MONEYS: |
| | | final_index = None |
| | | def __compute_trade_progress_near_by_indexes(self, code, start_index, end_index): |
| | | if start_index is None or end_index is None: |
| | | return |
| | | total_datas = local_today_datas.get(code) |
| | | MIN_MONEY = 50 * 100 |
| | | MAX_COUNT = 10 |
| | | watch_indexes = set() |
| | | total_num = 0 |
| | | thresh_hold_money = l2_trade_factor.L2PlaceOrderParamsManager.get_base_m_val(code) |
| | | threshold_num = thresh_hold_money // (float(gpcode_manager.get_limit_up_price(code)) * 100) |
| | | for i in range(start_index, end_index): |
| | | data = total_datas[i] |
| | | val = data['val'] |
| | | if not L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | # 小金额过滤 |
| | | if float(val['price']) * val['num'] < min_money * 100: |
| | | if float(val['price']) * val['num'] < MIN_MONEY: |
| | | continue |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count(code, i, |
| | | total_datas, |
| | | local_today_num_operate_map.get( |
| | | code)) |
| | | if left_count > 0: |
| | | final_index = i |
| | | total_num += val['num'] * left_count |
| | | watch_indexes.add(i) |
| | | if len(watch_indexes) > MAX_COUNT or total_num >= threshold_num: |
| | | break |
| | | if final_index: |
| | | self.__near_by_trade_progress_big_num_index_cache[code] = final_index |
| | | break |
| | | # 保存数据 |
| | | l2_log.l_cancel_debug(code,f"设置成交位临近撤单监控范围:{watch_indexes} 计算范围:{start_index}-{end_index}") |
| | | self.__set_near_by_trade_progress_indexes(code, watch_indexes) |
| | | |
| | | # 设置成交位置,成交位置变化之后相应的监听数据也会发生变化 |
| | | def set_trade_progress(self, code, index, total_datas): |
| | | # 临近撤先撤单 |
| | | # 如果成交位置并未该改变且没有没有找到成交位置临近大单 |
| | | # need_compute_big = False |
| | | # if self.__last_trade_progress_dict.get( |
| | | # code) == index and code not in self.__near_by_trade_progress_big_num_index_cache: |
| | | # need_compute_big = True |
| | | # elif self.__last_trade_progress_dict.get(code) != index: |
| | | # need_compute_big = True |
| | | # |
| | | # # 设置成交位置临近大单监听 |
| | | # real_place_order = self.__real_place_order_index_dict.get(code) |
| | | # # 真实下单位置 |
| | | # end_index = real_place_order |
| | | # if not end_index: |
| | | # end_index = total_datas[-1]["index"] |
| | | # |
| | | # if need_compute_big: |
| | | # self.__compute_near_by_big_num_index(code, index+1, end_index, total_datas) |
| | | |
| | | if self.__last_trade_progress_dict.get(code) == index: |
| | | return |
| | | |
| | | # 重新计算成交位置临近大单撤单 |
| | | self.__compute_trade_progress_near_by_indexes(code, index + 1, self.__real_place_order_index_dict.get(code)) |
| | | |
| | | try: |
| | | # 已经有计算的无法触发计算 |
| | | old_watch_indexes = self.__get_watch_indexes_cache(code) |
| | |
| | | |
| | | return False, None |
| | | |
| | | def __compute_near_by_trade_progress_need_cancel(self, code, buy_exec_index, start_index, end_index, total_data, |
| | | _local_today_num_operate_map, is_first_code): |
| | | watch_indexes = self.__get_near_by_trade_progress_indexes_cache(code) |
| | | if not watch_indexes: |
| | | return False, None |
| | | # 计算监听的总条数 |
| | | total_count = 0 |
| | | for wi in watch_indexes: |
| | | total_count += total_data[wi]["re"] |
| | | # 判断撤单中是否有监听中的索引 |
| | | need_compute = False |
| | | for i in range(start_index, end_index + 1): |
| | | data = total_data[i] |
| | | val = data["val"] |
| | | if L2DataUtil.is_limit_up_price_buy_cancel(val): |
| | | # 查询买入位置 |
| | | buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data(code, data, |
| | | _local_today_num_operate_map) |
| | | if buy_index is not None and buy_index in watch_indexes: |
| | | need_compute = True |
| | | break |
| | | if need_compute: |
| | | # 计算撤单比例 |
| | | canceled_count = 0 |
| | | for wi in watch_indexes: |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count(code, |
| | | wi, |
| | | total_data, |
| | | _local_today_num_operate_map) |
| | | canceled_count += total_data[wi]["re"] - left_count |
| | | rate = round(canceled_count / total_count, 3) |
| | | l2_log.l_cancel_debug(code, f"计算范围:{start_index}-{end_index},成交位临近已撤单比例:{rate}") |
| | | if rate >= constant.L_CANCEL_RATE: |
| | | return True, total_data[-1] |
| | | |
| | | return False, None |
| | | |
| | | def need_cancel(self, code, buy_exec_index, start_index, end_index, total_data, _local_today_num_operate_map, |
| | | is_first_code): |
| | | if buy_exec_index is None: |
| | |
| | | # 守护S撤以外的数据 |
| | | if time_space <= constant.L_CANCEL_START_TIME or int(tool.get_now_time_str().replace(":", "")) > int("145000"): |
| | | return False, None |
| | | # 下单位临近撤 |
| | | can_cancel, cancel_data = self.__compute_need_cancel(code, buy_exec_index, start_index, end_index, total_data, |
| | | _local_today_num_operate_map, is_first_code) |
| | | if not can_cancel: |
| | | # 成交位临近撤 |
| | | can_cancel, cancel_data = self.__compute_near_by_trade_progress_need_cancel(code, buy_exec_index, |
| | | start_index, end_index, |
| | | total_data, |
| | | _local_today_num_operate_map, |
| | | is_first_code) |
| | | return can_cancel, cancel_data |
| | | |
| | | def place_order_success(self, code): |