| | |
| | | if not constant.IS_NEW_VERSION_PLACE_ORDER: |
| | | try: |
| | | cls.__re_compute_threading_pool.submit( |
| | | cls.__recompute_real_order_index, code, place_order_index, order_info, compute_type) |
| | | cls.__recompute_real_order_index, code, place_order_index, order_info, |
| | | compute_type) |
| | | except: |
| | | pass |
| | | async_log_util.info(logger_l2_process, f"code:{code} 获取到下单真实位置:{place_order_index}") |
| | |
| | | b_need_cancel, b_cancel_data, extra_msg = RDCancelBigNumComputer().need_cancel(code, start_index, |
| | | end_index) |
| | | if b_need_cancel and b_cancel_data: |
| | | big_order_info = radical_buy_data_manager.get_total_deal_big_order_info(code, |
| | | gpcode_manager.get_limit_up_price_as_num( |
| | | code)) |
| | | if big_order_info[0]>0: |
| | | big_order_info = radical_buy_data_manager.get_total_deal_big_order_info(code, |
| | | gpcode_manager.get_limit_up_price_as_num( |
| | | code)) |
| | | if big_order_info[0] > 0: |
| | | return b_cancel_data, f"RD撤({extra_msg})", trade_constant.CANCEL_TYPE_RD |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_error, |
| | |
| | | is_limit_up_buy = False |
| | | return is_limit_up_buy |
| | | |
| | | @classmethod |
| | | def __is_big_order_deal_enough(cls, code): |
| | | """ |
| | | 大单成交是否足够 |
| | | @param code: |
| | | @param volume_rate: |
| | | @return: |
| | | """ |
| | | limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) |
| | | refer_volume = code_volumn_manager.CodeVolumeManager().get_max_volume_in_5days(code) |
| | | if refer_volume is None: |
| | | refer_volume = 0 |
| | | |
| | | money_y = int(refer_volume * limit_up_price / 1e8) |
| | | money_y = min(money_y, 50) |
| | | money_y = max(money_y, 5) |
| | | # 计算大单参考数量 |
| | | threshold_count = int(round(0.4 * money_y)) * 4 |
| | | threshold_money = threshold_count * 299 * 10000 |
| | | volume_rate_info = cls.volume_rate_info.get(code) |
| | | |
| | | deal_big_order_money = BigOrderDealManager().get_total_buy_money(code) |
| | | if deal_big_order_money >= threshold_money: |
| | | return True, f"量比-{volume_rate_info}, 总大单成交金额({deal_big_order_money})>={threshold_money}" |
| | | else: |
| | | return False, f"量比-{volume_rate_info}, 总大单成交金额({deal_big_order_money})<{threshold_money}" |
| | | |
| | | @classmethod |
| | | def __can_buy_first(cls, code): |
| | | """ |
| | | 是否可以下单 |
| | | @param code: |
| | | @return:(是否可以下单, 是否清理信号数据, 不能下单消息, 是否算有效执行) |
| | | """ |
| | | |
| | | pre_result = cls.__is_pre_can_buy(code) |
| | | if not pre_result[0]: |
| | | return pre_result[0], pre_result[1], pre_result[2], pre_result[3] |
| | | |
| | | now_time_int = int(tool.get_now_time_str().replace(":", "")) |
| | | if 130100 >= now_time_int >= 112900 or now_time_int < 93100: |
| | | if now_time_int < 93100: |
| | | # 判断近120天是否有涨停 |
| | | k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) |
| | | if k_format and len(k_format) >= 12 and not k_format[11]: |
| | | return False, True, f"09:31:00之前下单,90个交易日无涨停", True |
| | | |
| | | # 判断成交的大单数量 |
| | | data_list = BigOrderDealManager().get_total_buy_money_list(code) |
| | | bigger_money = 2990000 |
| | | fdatas = [] |
| | | for d in data_list: |
| | | if d < bigger_money: |
| | | continue |
| | | fdatas.append(d) |
| | | thresh_count = 3 if tool.is_sh_code(code) else 1 |
| | | if len(fdatas) < thresh_count: |
| | | return False, True, f"09:31:00之前下单,成交大单数量({len(fdatas)})不足{thresh_count}个", True |
| | | else: |
| | | # 判断数据是否卡 |
| | | total_datas = local_today_datas.get(code) |
| | | if tool.trade_time_sub_with_ms(tool.get_now_time_with_ms_str(), |
| | | L2DataUtil.get_time_with_ms(total_datas[-1]["val"])) > 500: |
| | | return False, True, f"09:31:00之前下单,L2数据时间相差500ms以上", True |
| | | else: |
| | | return False, True, f"09:31:00之前,11:29:00-13:01:00不能交易", True |
| | | |
| | | limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) |
| | | |
| | | if constant.MIN_CODE_PRICE < limit_up_price < constant.MAX_CODE_PRICE: |
| | | # 满足条件的单价 |
| | | pass |
| | | elif limit_up_price > constant.MAX_CODE_PRICE: |
| | | # HighIncreaseCodeManager().add_code(code) |
| | | # 小市值高股价可买 |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb > 25e8 or limit_up_price > constant.MAX_SUBSCRIPT_CODE_PRICE: |
| | | return False, True, f"股价大于{constant.MAX_CODE_PRICE}块/小于{constant.MIN_CODE_PRICE}块", True |
| | | else: |
| | | return False, True, f"股价小于{constant.MIN_CODE_PRICE}块", True |
| | | |
| | | # place_order_count = cls.__PlaceOrderCountManager.get_place_order_count(code) |
| | | # if place_order_count and place_order_count >= 10: |
| | | # l2_trade_util.forbidden_trade(code, msg="当日下单次数已达10次") |
| | | # return False, True, f"当日下单次数已达10次" |
| | | |
| | | # ---------均价约束------------- |
| | | average_rate = cls.__Buy1PriceManager.get_average_rate(code) |
| | | if average_rate and average_rate <= 0.01 and tool.trade_time_sub(tool.get_now_time_str(), "10:30:00") >= 0: |
| | | return False, True, f"均价涨幅({average_rate})小于1%", True |
| | | |
| | | total_data = local_today_datas.get(code) |
| | | |
| | | # 9:32之前上证开1的票不买 |
| | | if tool.is_sh_code(code) and int(total_data[-1]["val"]["time"].replace(":", "")) <= int("093100"): |
| | | # 获取涨停时间 |
| | | limit_up_data = kpl_data_manager.KPLLimitUpDataRecordManager.record_code_dict.get(code) |
| | | if limit_up_data: |
| | | limit_up_time = tool.to_time_str(limit_up_data[2]) |
| | | if int(limit_up_time.replace(":", "")) < int("093000"): |
| | | return False, True, f"上证开一09:32之前不下单", True |
| | | |
| | | # ------------挂单时间约束---------- |
| | | order_begin_pos = cls.__get_order_begin_pos( |
| | | code) |
| | | if not trade_result_manager.can_place_order_for_cancel_time(code, total_data[ |
| | | order_begin_pos.buy_exec_index]) and not gpcode_manager.GreenListCodeManager().is_in_cache(code): |
| | | return False, True, f"距离上次挂单小于时间限制", True |
| | | |
| | | # ------------板块约束------------- |
| | | if not cls.__WantBuyCodesManager.is_in_cache(code): |
| | | # 想买单无板块约束 |
| | | block_buy_result = buy_strategy_util.is_block_can_buy(code, cls.__get_can_buy_block(code)) |
| | | if not block_buy_result[0]: |
| | | return block_buy_result[0], block_buy_result[1], block_buy_result[2], True |
| | | |
| | | if constant.L2_SOURCE_TYPE == constant.L2_SOURCE_TYPE_HUAXIN: |
| | | # ---------------------判断是否为板上放量---------------------- |
| | | trade_price = current_price_process_manager.get_trade_price(code) |
| | | if trade_price is None: |
| | | return False, True, f"尚未获取到当前成交价", True |
| | | # 判断是否为板上放量: |
| | | # 1.当前成交价为涨停价 |
| | | # 2.距离最近的非板上成交的时间大于一个阈值 |
| | | if abs(limit_up_price - float(trade_price)) < 0.001: |
| | | is_limit_up_buy = cls.__is_at_limit_up_buy(code, order_begin_pos.buy_exec_index) |
| | | if is_limit_up_buy: |
| | | # 板上买且非加绿 |
| | | # 获取最近的非涨停价成交时间 |
| | | not_limit_up_trade_time_with_ms = current_price_process_manager.get_trade_not_limit_up_time_with_ms( |
| | | code) |
| | | # 判断成交进度到当前数据的笔数,如果少于10笔且还有未成交的大单(>=299)就可以下单 |
| | | trade_index, is_default = cls.__TradeBuyQueue.get_traded_index(code) |
| | | if trade_index is None: |
| | | trade_index = 0 |
| | | can_place_order, msg = buy_strategy_util.is_near_by_trade_index(code, trade_index) |
| | | if not can_place_order: |
| | | try: |
| | | # 不能下单,判断小群撤是否可以下 |
| | | if buy_strategy_util.is_has_small_batch_cancel(code, trade_index, |
| | | order_begin_pos.buy_single_index): |
| | | # 判断撤单比例是否足够 |
| | | cancel_rate_reieved_info = buy_strategy_util.is_cancel_rate_reieved(code, 0.69, |
| | | trade_index, |
| | | order_begin_pos.buy_single_index) |
| | | if not cancel_rate_reieved_info[0]: |
| | | return False, True, f"板上放量距离远({not_limit_up_trade_time_with_ms}),有小群撤, 整体撤单比例不足({trade_index}-{order_begin_pos.buy_single_index}){cancel_rate_reieved_info[1]}", False |
| | | else: |
| | | return False, True, f"板上放量距离远({not_limit_up_trade_time_with_ms}),没有小群撤({trade_index}-{order_begin_pos.buy_single_index})", False |
| | | except Exception as e: |
| | | l2_log.info(code, logger_l2_error, f"板上放量({not_limit_up_trade_time_with_ms})不足异常:{str(e)}") |
| | | logger_l2_error.exception(e) |
| | | return False, True, f"板上放量计算异常", False |
| | | |
| | | # -------是否距离成交进度位太远-------- |
| | | buy1_money = code_price_manager.Buy1PriceManager().get_latest_buy1_money(code) |
| | | buy1_price = code_price_manager.Buy1PriceManager().get_buy1_price(code) |
| | | if buy1_price and abs(limit_up_price - buy1_price) > 0.0001: |
| | | # 买1未涨停 |
| | | buy1_money = 0 |
| | | if not buy1_money: |
| | | buy1_money = 1 |
| | | if buy_strategy_util.is_far_away_from_trade_index(code, trade_index, buy1_money): |
| | | return False, True, f"距离成交进度位太远:成交进度-{trade_index} 买1-{buy1_money}", False |
| | | |
| | | # ------------------上证下单需要有成交大单(包含主动买与被动买)或者挂买的大单----------------- |
| | | if tool.is_sh_code(code): |
| | | deal_big_order_count = BigOrderDealManager().get_total_buy_count(code) |
| | | if deal_big_order_count < 1: |
| | | # 统计挂买大单 |
| | | trade_index, is_default = cls.__TradeBuyQueue.get_traded_index(code) |
| | | if trade_index is None: |
| | | trade_index = 0 |
| | | limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) |
| | | # 从成交进度位到截至位置计算大单 |
| | | min_money = l2_data_util.get_big_money_val(limit_up_price, tool.is_ge_code(code)) |
| | | left_count, left_money = cancel_buy_strategy.L2DataComputeUtil.compute_left_buy_order(code, |
| | | trade_index, |
| | | total_data[ |
| | | -1][ |
| | | "index"], |
| | | limit_up_price, |
| | | min_money=min_money) |
| | | if left_count < 1: |
| | | return False, False, f"没有已挂或者成交的大单", False |
| | | if not cls.__WantBuyCodesManager.is_in_cache(code): |
| | | # 想买单不需要大单约束 |
| | | big_deal_order_info = cls.__is_big_order_deal_enough(code) |
| | | if not big_deal_order_info[0]: |
| | | return False, False, big_deal_order_info[1], False |
| | | |
| | | place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code) |
| | | # ------------------第一和第二次下单都必须要有至少一笔未成交的大单-------------------------- |
| | | # 计算大单 |
| | | total_datas = local_today_datas.get(code) |
| | | if place_order_count < 2: |
| | | trade_index, is_default = transaction_progress.TradeBuyQueue().get_traded_index(code) |
| | | if trade_index is None: |
| | | trade_index = 0 |
| | | min_money = l2_data_util.get_big_money_val(limit_up_price, tool.is_ge_code(code)) |
| | | left_count, left_num = L2DataComputeUtil.compute_left_buy_order(code, trade_index, |
| | | total_datas[-1]["index"], |
| | | limit_up_price, min_money) |
| | | if left_count < 1: |
| | | return False, False, f"第{place_order_count + 1}次下单无待成交的大单", False |
| | | |
| | | # -------判断是否是量化下单,如果是就不跟到下单-------- |
| | | # 重要:量化下单会增加下单次数,板块下单中有下单次数的使用,所以板块需要在量化判断之前 |
| | | # 只有板块满足下单之后才能判断其它条件 |
| | | range_indexes = cls.__processing_data_indexes.get(code) |
| | | if range_indexes: |
| | | # 是否是量化单 |
| | | is_quantization_result = buy_strategy_util.is_quantization(code, range_indexes[0], range_indexes[1]) |
| | | if is_quantization_result[0] and not gpcode_manager.GreenListCodeManager().is_in_cache(code): |
| | | # 量化单且没有加绿 |
| | | cls.__next_buy_time_dict[code] = is_quantization_result[1] |
| | | return False, True, is_quantization_result[2], True |
| | | return True, False, "满足下单条件", True |
| | | |
| | | # 获取可以买的板块 |
| | | @classmethod |
| | | def __get_can_buy_block(cls, code): |
| | |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.total_datas, |
| | | latest_current_limit_up_records, |
| | | block_info.get_before_blocks_dict(), |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.get_current_limit_up_reason_codes_dict(), codes_delegate, codes_success) |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.get_current_limit_up_reason_codes_dict(), |
| | | codes_delegate, codes_success) |
| | | can_buy_result = CodePlateKeyBuyManager.can_buy(code) |
| | | return can_buy_result |
| | | |