| | |
| | | # return False |
| | | rate = (float(limit_up_price) - min_price_info[1]["close"]) / min_price_info[1]["close"] |
| | | print(rate) |
| | | if rate >= 0.28: |
| | | if rate >= 0.319: |
| | | return True, rate |
| | | return False, rate |
| | | |
| | |
| | | for d in codes_data: |
| | | code = d[0] |
| | | codes.add(code) |
| | | self.codes_volume_and_price_dict[code] = (d[1], d[2]) |
| | | self.l2_data_upload_manager.set_order_fileter_condition(code, d[1], float(d[2])) |
| | | self.codes_volume_and_price_dict[code] = (d[1], d[2], d[3]) |
| | | self.l2_data_upload_manager.set_order_fileter_condition(code, d[1], float(d[2]), d[3]) |
| | | add_codes = codes - self.subscripted_codes |
| | | del_codes = self.subscripted_codes - codes |
| | | print("add del codes", add_codes, del_codes) |
| | |
| | | # self.special_code_volume_for_order_dict[code] = (volume, time.time() + 3) |
| | | d = self.codes_volume_and_price_dict.get(code) |
| | | if d: |
| | | min_volume, limit_up_price = d[0], d[1] |
| | | self.l2_data_upload_manager.set_order_fileter_condition(code, min_volume, limit_up_price, |
| | | min_volume, limit_up_price, special_price = d[0], d[1], d[2] |
| | | self.l2_data_upload_manager.set_order_fileter_condition(code, min_volume, limit_up_price,special_price, |
| | | {volume, constant.SHADOW_ORDER_VOLUME}, |
| | | time.time() + 3) |
| | | huaxin_l2_log.info(logger_local_huaxin_l2_subscript, f"设置下单量监听:{code}-{volume}") |
| | |
| | | self.l2_transaction_codes = set() |
| | | |
| | | # 设置订单过滤条件 |
| | | def set_order_fileter_condition(self, code, min_volume, limit_up_price, special_volumes=None, |
| | | # special_price:过滤的1手的价格 |
| | | def set_order_fileter_condition(self, code, min_volume, limit_up_price, special_price, special_volumes=None, |
| | | special_volumes_expire_time=None): |
| | | if special_volumes is None: |
| | | special_volumes = set() |
| | | if code in self.filter_order_condition_dict and not special_volumes and not special_volumes_expire_time: |
| | | self.filter_order_condition_dict[code][0] = (min_volume, limit_up_price) |
| | | self.filter_order_condition_dict[code][0] = (min_volume, limit_up_price, special_price) |
| | | huaxin_l2_log.info(logger_local_huaxin_l2_subscript, |
| | | f"({code})常规过滤条件设置:{self.filter_order_condition_dict[code]}") |
| | | else: |
| | | self.filter_order_condition_dict[code] = [(min_volume, limit_up_price), special_volumes, |
| | | self.filter_order_condition_dict[code] = [(min_volume, limit_up_price, special_price), special_volumes, |
| | | special_volumes_expire_time] |
| | | huaxin_l2_log.info(logger_local_huaxin_l2_subscript, |
| | | f"({code})下单后过滤条件设置:{self.filter_order_condition_dict[code]}") |
| | | |
| | | # 过滤订单 |
| | | def __filter_order(self, item): |
| | | # if item[2] == 100 and item[3] == '1': |
| | | # # 不过滤买1手 |
| | | # return item |
| | | filter_condition = self.filter_order_condition_dict.get(item[0]) |
| | | if filter_condition: |
| | | # item[2]为量 |
| | | if item[2] >= filter_condition[0][0]: |
| | | return item |
| | | # 1手的买单满足价格 |
| | | if item[2] == 100 and item[3] == '1' and abs(filter_condition[0][2] - item[1]) < 0.001: |
| | | return item |
| | | if filter_condition[1] and item[2] in filter_condition[1]: |
| | | if filter_condition[2] and time.time() > filter_condition[2]: |
| | |
| | | filter_condition[1] = set() |
| | | filter_condition[2] = None |
| | | return None |
| | | return item |
| | | elif item[2] == 100 and item[3] == '1': |
| | | return item |
| | | return None |
| | | return item |
| | |
| | | def OnTrade(self, client_id, request_id, sk, type_, data): |
| | | if type_ == 1: |
| | | async_log_util.info(logger_local_huaxin_trade_debug, |
| | | f"\n---------------------\n请求下单:client_id-{client_id} request_id-{request_id}") |
| | | f"\n---------------------\n请求下单:client_id-{client_id} request_id-{request_id} data:{data}") |
| | | # 下单 |
| | | # 1-买 2-卖 |
| | | direction = data["direction"] |
| | |
| | | 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) |
| | | FCancelBigNumComputer().set_real_order_index(code, index) |
| | | FCancelBigNumComputer().set_real_order_index(code, index, is_default) |
| | | |
| | | |
| | | class SecondCancelBigNumComputer: |
| | |
| | | for k in keys: |
| | | code = k.split("-")[-1] |
| | | val = RedisUtils.get(__redis, k) |
| | | CodeDataCacheUtil.set_cache(cls.__real_order_index_cache, code, int(val)) |
| | | val = json.loads(val) |
| | | CodeDataCacheUtil.set_cache(cls.__real_order_index_cache, code, val) |
| | | finally: |
| | | RedisUtils.realse(__redis) |
| | | |
| | |
| | | def __get_redis(cls): |
| | | return cls.__redis_manager.getRedis() |
| | | |
| | | def __set_real_order_index(self, code, index): |
| | | CodeDataCacheUtil.set_cache(self.__real_order_index_cache, code, index) |
| | | RedisUtils.setex_async(self.__db, f"f_cancel_real_order_index-{code}", tool.get_expire(), f"{index}") |
| | | def __set_real_order_index(self, code, index, is_default): |
| | | CodeDataCacheUtil.set_cache(self.__real_order_index_cache, code, (index, is_default)) |
| | | RedisUtils.setex_async(self.__db, f"f_cancel_real_order_index-{code}", tool.get_expire(), json.dumps((index, is_default))) |
| | | |
| | | def __del_real_order_index(self, code): |
| | | CodeDataCacheUtil.clear_cache(self.__real_order_index_cache, code) |
| | |
| | | def __get_real_order_index(self, code): |
| | | val = RedisUtils.get(self.__db, f"f_cancel_real_order_index-{code}") |
| | | if val: |
| | | return int(val) |
| | | val = json.loads(val) |
| | | return val[0] |
| | | return None |
| | | |
| | | def __get_real_order_index_cache(self, code): |
| | |
| | | else: |
| | | return False, "快速成交了50%以下" |
| | | |
| | | # 设置真实的下单位置,返回是否需要撤单 |
| | | def set_real_order_index(self, code, index): |
| | | self.__set_real_order_index(code, index) |
| | | # 设置真实的下单位置 |
| | | def set_real_order_index(self, code, index, is_default): |
| | | self.__set_real_order_index(code, index, is_default) |
| | | |
| | | def place_order_success(self, code): |
| | | self.clear(code) |
| | |
| | | def cancel_success(self, code): |
| | | self.clear(code) |
| | | |
| | | # 是否成交太快需要撤单 |
| | | def need_cancel_for_deal_fast(self, code, trade_index): |
| | | # 判断是否具有真实的下单位置 |
| | | real_order_index_info = self.__get_real_order_index_cache(code) |
| | | if not real_order_index_info: |
| | | return False, "没找到真实下单位" |
| | | if real_order_index_info[1]: |
| | | return False, "真实下单位为默认" |
| | | if real_order_index_info[0] <= trade_index: |
| | | return False, "真实下单位在成交位之前" |
| | | real_order_index = real_order_index_info[0] |
| | | # 统计未撤订单的数量与金额 |
| | | total_datas = local_today_datas.get(code) |
| | | # 是否是下单5分钟内 |
| | | if tool.trade_time_sub(tool.get_now_time_str(),total_datas[real_order_index]['val']['time']) > 5*60: |
| | | return False, "下单超过5分钟" |
| | | |
| | | total_left_count = 0 |
| | | total_left_num = 0 |
| | | for i in range(trade_index + 1, real_order_index_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"]) < 5000: |
| | | 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_left_count += left_count |
| | | total_left_num += val["num"] * left_count |
| | | if total_left_count < 10: |
| | | return True, f"剩余笔数不足({total_left_count}),成交进度:{trade_index},真实下单位置:{real_order_index}" |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price and total_left_num * float(limit_up_price) < 1000*100: |
| | | return True, f"剩余金额不足({round(total_left_num * float(limit_up_price)*100)}),成交进度:{trade_index},真实下单位置:{real_order_index}" |
| | | return False, "不满足撤单条件" |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | # ---------------------------------G撤------------------------------- |
| | | class GCancelBigNumComputer: |
| | |
| | | except Exception as e: |
| | | if constant.TEST: |
| | | logging.exception(e) |
| | | # TODO 可能耗时 |
| | | logger_l2_error.exception(e) |
| | | async_log_util.error(logger_l2_error, |
| | | f"H撤出错 参数:buy_single_index-{_buy_single_index} buy_exec_index-{_buy_exec_index} {str(e)}") |
| | | async_log_util.exception(logger_l2_error, e) |
| | |
| | | if order_begin_pos and order_begin_pos.buy_exec_index and order_begin_pos.buy_exec_index > -1: |
| | | HourCancelBigNumComputer().set_transaction_index(code, order_begin_pos.buy_single_index, |
| | | buy_progress_index) |
| | | cresult = FCancelBigNumComputer().need_cancel_for_deal_fast(code,buy_progress_index) |
| | | if cresult[0]: |
| | | L2TradeDataProcessor.cancel_buy(code, f"下单5分钟内排单不足:{cresult[1]}") |
| | | # ---------------------------------判断板块是否跟上来了------------------------------- |
| | | try: |
| | | pass |
| | |
| | | from code_attribute import gpcode_manager |
| | | from l2 import l2_data_source_util, l2_data_util |
| | | from l2.l2_data_util import L2DataUtil |
| | | from log_module import async_log_util |
| | | from log_module.log import logger_kp_msg |
| | | from msg import push_msg_manager |
| | | from utils import output_util, tool |
| | | |
| | | |
| | | # 即将成交 |
| | | def almost_deal(code, real_order_index, trade_index, total_datas): |
| | | if trade_index > real_order_index: |
| | | return |
| | | # 下单3s过后再提醒 |
| | | if tool.trade_time_sub(total_datas[-1]["val"]["time"], total_datas[real_order_index]["val"]["time"]) <= 3: |
| | | return |
| | |
| | | if total_left_count <= 10: |
| | | push_msg_manager.push_order_almost_deal(code, code_name, real_order_index, f"剩余:{total_left_count}笔", |
| | | ctype="count") |
| | | async_log_util.info(logger_kp_msg, f"{code}即将成交:trade_index-{trade_index},real_order_index-{real_order_index},剩余:{total_left_count}笔") |
| | | |
| | | elif total_left_money < 1500 * 10000: |
| | | push_msg_manager.push_order_almost_deal(code, code_name, real_order_index, |
| | | f"剩余:{output_util.money_desc(total_left_money)}", ctype="money") |
| | | async_log_util.info(logger_kp_msg, |
| | | f"{code}即将成交:trade_index-{trade_index},real_order_index-{real_order_index},剩余:{total_left_money}元") |
| | | |
| | | |
| | | # 真实下单位后面跟单不足 |
| | | def follow_not_enough(code, buy_exec_index, real_order_index, total_datas): |
| | | if buy_exec_index > real_order_index: |
| | | return |
| | | # 下单3s过后再提醒 |
| | | if tool.trade_time_sub(total_datas[-1]["val"]["time"], total_datas[buy_exec_index]["val"]["time"]) <= 3: |
| | | return |
| | |
| | | push_msg_manager.push_delegate_order_danger(code, code_name, buy_exec_index, |
| | | f"剩余:{real_place_order_after_count}笔", |
| | | ctype="count") |
| | | async_log_util.info(logger_kp_msg, |
| | | f"{code}封单不足:buy_exec_index-{buy_exec_index},real_order_index-{real_order_index},剩余:{real_place_order_after_count}元") |
| | | |
| | | if real_place_order_after_money <= 1500 * 10000: |
| | | push_msg_manager.push_delegate_order_danger(code, code_name, buy_exec_index, |
| | | f"剩余:{output_util.money_desc(real_place_order_after_money)}", |
| | | ctype="money") |
| | | async_log_util.info(logger_kp_msg, |
| | | f"{code}封单不足:buy_exec_index-{buy_exec_index},real_order_index-{real_order_index},剩余:{real_place_order_after_money}元") |
| | |
| | | if True: |
| | | print("设置L2代码数量:", len(add_code_set)) |
| | | global latest_add_codes |
| | | async_log_util.info(logger_l2_codes_subscript, f"({request_id})预处理新增订阅代码:{add_code_set - latest_add_codes}") |
| | | async_log_util.info(logger_l2_codes_subscript, |
| | | f"({request_id})预处理新增订阅代码:{add_code_set - latest_add_codes}") |
| | | latest_add_codes = add_code_set |
| | | add_datas = [] |
| | | for d in add_code_list: |
| | | limit_up_price = gpcode_manager.get_limit_up_price(d) |
| | | limit_up_price = round(float(limit_up_price), 2) |
| | | min_volume = int(round(50 * 10000 / limit_up_price)) |
| | | add_datas.append((d, min_volume, limit_up_price)) |
| | | # 传递笼子价 |
| | | add_datas.append( |
| | | (d, min_volume, limit_up_price, round(tool.get_shadow_price(limit_up_price), 2))) |
| | | huaxin_target_codes_manager.HuaXinL2SubscriptCodesManager.push(add_datas, request_id) |
| | | except Exception as e: |
| | | logging.exception(e) |
| | |
| | | limit_up_price = gpcode_manager.get_limit_up_price(d[0]) |
| | | if limit_up_price: |
| | | # 默认设置涨停,量为0 |
| | | datas.append((code, float(limit_up_price), 10, 0, time.time())) |
| | | datas.append((code, 0, float(limit_up_price), tool.get_shadow_price(float(limit_up_price)))) |
| | | except Exception as e: |
| | | logger_l2_codes_subscript.exception(e) |
| | | if not datas: |
| | |
| | | # 如果在9:24-9:30 需要加载板块 |
| | | if int("092400") < int(tool.get_now_time_str().replace(":", "")) < int("093000"): |
| | | for d in datas: |
| | | KPLCodeJXBlockManager().load_jx_blocks(d[0], gpcode_manager.get_price(d[0]), float(d[2]), KPLLimitUpDataRecordManager.get_current_reasons()) |
| | | KPLCodeJXBlockManager().load_jx_blocks(d[0], gpcode_manager.get_price(d[0]), float(d[2]), |
| | | KPLLimitUpDataRecordManager.get_current_reasons()) |
| | | time.sleep(1) |
| | | logger_l2_codes_subscript.info("({})发送到华鑫L2代码处理队列:数量-{}", request_id, len(datas)) |
| | | except Exception as e: |
| | |
| | | def __cancel_not_deal_order(self, code, order_ref, timeout=2): |
| | | time.sleep(timeout) |
| | | # 撤买单 |
| | | huaxin_trade_api.cancel_order(1, code, "", orderRef = order_ref) |
| | | huaxin_trade_api.cancel_order(1, code, "", orderRef=order_ref) |
| | | |
| | | # 交易 |
| | | def OnTrade(self, client_id, request_id, data): |
| | |
| | | if buy1_info and buy1_info[0] * buy1_info[1] > 50 * 10000: |
| | | # 如果买1在50w以上就加一档 |
| | | price += 0.01 |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price and price > float(limit_up_price): |
| | | price = round(float(limit_up_price), 2) |
| | | order_ref = huaxin_util.create_order_ref() |
| | | result = huaxin_trade_api.order(direction, code, volume, price, price_type=price_type, |
| | | sinfo=sinfo, order_ref=order_ref, |
| | |
| | | continue |
| | | if val["num"] * float(val["price"]) < 5000: |
| | | continue |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2( |
| | | code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if left_count > 0: |
| | | total_left_count += left_count |
| | | total_left_num += val["num"] * left_count |
| | |
| | | if not l2_data_util.is_big_money(val): |
| | | continue |
| | | |
| | | canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2( |
| | | code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if not canceled_data: |
| | | total_big_count += 1 |
| | | else: |
| | |
| | | if not l2_data_util.is_big_money(val): |
| | | continue |
| | | |
| | | canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2( |
| | | code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if not canceled_data: |
| | | not_deal_total_big_count += 1 |
| | | else: |
| | |
| | | if not l2_data_util.is_big_money(val): |
| | | continue |
| | | |
| | | canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | canceled_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2( |
| | | code, |
| | | i, |
| | | total_datas, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if not canceled_data: |
| | | real_place_order_after_count += 1 |
| | | real_place_order_after_num += val["num"] |
| | |
| | | limit_up_price) * 100 < 1500 * 10000) and ( |
| | | real_place_order_after_count <= 10 or real_place_order_after_num * float( |
| | | limit_up_price) * 100 < 1500 * 10000) |
| | | fdata = {"code_info": (code, code_name), "total_num": total_nums, "finish_num": deal_or_cancel_num, |
| | | fdata = {"code_info": (code, code_name), "total_num": total_nums, |
| | | "finish_num": deal_or_cancel_num, |
| | | "buy1_money": output_util.money_desc(buy1_money), |
| | | "big_num_count": total_big_count, |
| | | "big_num_money": output_util.money_desc(total_big_num * float(limit_up_price) * 100), |
| | | "big_num_money": output_util.money_desc( |
| | | total_big_num * float(limit_up_price) * 100), |
| | | "not_deal_big_num_count": not_deal_total_big_count, |
| | | "not_deal_big_num_money": output_util.money_desc( |
| | | not_deal_total_big_num * float(limit_up_price) * 100), |
| | |
| | | |
| | | # 获取买入价格笼子的最低价 |
| | | def get_shadow_price(price): |
| | | fprice = round((100 - random.randint(2, 10)) * price / 100, 2) |
| | | if price - 0.1 < fprice: |
| | | fprice = price - 0.1 |
| | | return round(fprice, 2) |
| | | # fprice = round((100 - random.randint(2, 10)) * price / 100, 2) |
| | | # if price - 0.1 < fprice: |
| | | # fprice = price - 0.1 |
| | | # return round(fprice, 2) |
| | | return round(get_buy_min_price(price), 2) |
| | | |
| | | |
| | | if __name__ == "__main__": |