From 3ea84f8adaeeb851e590fa74ceed009a0a19b08c Mon Sep 17 00:00:00 2001 From: Administrator <admin@example.com> Date: 星期二, 28 十一月 2023 17:46:38 +0800 Subject: [PATCH] 近6个交易日涨幅过高实现 --- huaxin_client/l2_client.py | 1 code_attribute/code_nature_analyse.py | 29 ++++++ code_attribute/first_target_code_data_processor.py | 7 + trade/huaxin/huaxin_trade_server.py | 58 ++++++++++++-- third_data/code_plate_key_manager.py | 2 test/test_code_attribute.py | 25 ++++++ test/l2_trade_test.py | 1 trade/huaxin/huaxin_trade_api.py | 91 ++++++++++++---------- l2/code_price_manager.py | 12 ++ l2/l2_data_manager_new.py | 5 + 10 files changed, 174 insertions(+), 57 deletions(-) diff --git a/code_attribute/code_nature_analyse.py b/code_attribute/code_nature_analyse.py index 5600454..d4f9886 100644 --- a/code_attribute/code_nature_analyse.py +++ b/code_attribute/code_nature_analyse.py @@ -224,7 +224,7 @@ # 鏄惁鍏锋湁K绾垮舰鎬� def is_has_k_format(limit_up_price, record_datas): - is_too_high, is_new_top, is_lowest, is_near_new_top, is_n, is_v, has_format, volume_info, is_special = get_k_format( + is_too_high, is_new_top, is_lowest, is_near_new_top, is_n, is_v, has_format, volume_info, is_special, has_max_volume = get_k_format( float(limit_up_price), record_datas) if not has_format: return False, "涓嶆弧瓒矺绾垮舰鎬�" @@ -255,7 +255,7 @@ # 鏄惁娑ㄥ緱澶珮 -def is_up_too_high_in_10d(record_datas): +def is_up_too_high_in_10d_with_limit_up(record_datas): datas = copy.deepcopy(record_datas) datas.sort(key=lambda x: x["bob"]) datas = datas[-10:] @@ -348,6 +348,31 @@ return False +# 鍦ㄦ渶杩戝嚑澶╁唴鑲′环鏄惁闀垮緱澶珮 +def is_price_too_high_in_days(record_datas, limit_up_price, day_count=6): + datas = copy.deepcopy(record_datas) + datas.sort(key=lambda x: x["bob"]) + datas = datas[0 - day_count:] + min_price = None + max_price = None + for d in datas: + if min_price is None: + min_price = d["low"] + if max_price is None: + max_price = d["high"] + if min_price > d["low"]: + min_price = d["low"] + if max_price < d["high"]: + max_price = d["high"] + if max_price > float(limit_up_price): + return False + rate = (float(limit_up_price) - min_price) / min_price + # print(rate) + if rate >= 0.25: + return True + return False + + # 鏄惁鏈夋定鍋� def get_first_limit_up_count(datas): datas = copy.deepcopy(datas) diff --git a/code_attribute/first_target_code_data_processor.py b/code_attribute/first_target_code_data_processor.py index fddeab8..6804624 100644 --- a/code_attribute/first_target_code_data_processor.py +++ b/code_attribute/first_target_code_data_processor.py @@ -123,7 +123,7 @@ k_format = code_nature_analyse.get_k_format(limit_up_price, volumes_data) code_nature_analyse.CodeNatureRecordManager().save_k_format(code, k_format) - if code_nature_analyse.is_up_too_high_in_10d(volumes_data): + if code_nature_analyse.is_up_too_high_in_10d_with_limit_up(volumes_data): # 鍒ゆ柇鏄惁澶珮 l2_trade_util.forbidden_trade(code, "鑲′环闀垮緱澶珮") HighIncreaseCodeManager().add_code(code) @@ -133,6 +133,11 @@ l2_trade_util.forbidden_trade(code, "120澶╁唴鑲′环闀垮緱澶珮") HighIncreaseCodeManager().add_code(code) + if code_nature_analyse.is_price_too_high_in_days(volumes_data, limit_up_price): + # 鍒ゆ柇鏄惁澶珮 + l2_trade_util.forbidden_trade(code, "6澶╁唴鑲′环闀垮緱澶珮") + HighIncreaseCodeManager().add_code(code) + if code_nature_analyse.is_have_latest_max_volume(volumes_data, 2): # 鏈�杩�2澶╂槸鍚︽槸鏈�楂橀噺 code_nature_analyse.LatestMaxVolumeManager().set_has_latest_max_volume(code) diff --git a/huaxin_client/l2_client.py b/huaxin_client/l2_client.py index c4230e5..38aa0c6 100644 --- a/huaxin_client/l2_client.py +++ b/huaxin_client/l2_client.py @@ -276,6 +276,7 @@ d = {"dataTimeStamp": pDepthMarketData['DataTimeStamp'], "securityID": pDepthMarketData['SecurityID'], "lastPrice": pDepthMarketData['LastPrice'], "totalVolumeTrade": pDepthMarketData['TotalVolumeTrade'], + "totalValueTrade":pDepthMarketData['TotalValueTrade'], "totalAskVolume": pDepthMarketData['TotalAskVolume'], "avgAskPrice": pDepthMarketData["AvgAskPrice"], "buy": [(pDepthMarketData['BidPrice1'], pDepthMarketData['BidVolume1']), diff --git a/l2/code_price_manager.py b/l2/code_price_manager.py index dba7264..160e45e 100644 --- a/l2/code_price_manager.py +++ b/l2/code_price_manager.py @@ -25,6 +25,8 @@ # 鏈�杩�3鍒嗛挓鍐呯殑涔�1閲戦 __latest_3m_buy1_money_list_dict = {} __open_limit_up_lowest_price_cache = {} + # 鍧囦环 + __average_rate_dict = {} __instance = None @@ -139,16 +141,20 @@ price = self.__get_open_limit_up_lowest_price_cache(code) return price - # 澶勭悊 + def get_average_rate(self, code): + return self.__average_rate_dict.get(code) - def process(self, code, buy_1_price, buy_1_volume, time_str, limit_up_price, sell_1_price, sell_1_volumn): + # 澶勭悊 + def process(self, code, buy_1_price, buy_1_volume, time_str, limit_up_price, sell_1_price, sell_1_volumn, + average_rate=None): + self.__average_rate_dict[code] = average_rate data_str = f"{buy_1_price},{buy_1_volume},{time_str},{limit_up_price},{sell_1_price},{sell_1_volumn}" if self.__latest_data.get(code) == data_str: return # 璁板綍鏃ュ織 logger_trade_queue_price_info.info( - f"code={code} data: time_str-{time_str}, buy_1_price-{buy_1_price},limit_up_price-{limit_up_price},sell_1_price-{sell_1_price},sell_1_volumn-{sell_1_volumn}") + f"code={code} data: time_str-{time_str}, buy_1_price-{buy_1_price},limit_up_price-{limit_up_price},sell_1_price-{sell_1_price},sell_1_volumn-{sell_1_volumn},percent_rate-{percent_rate}") # 涔�1浠锋牸涓嶈兘灏忎簬1鍧� if float(buy_1_price) < 1.0: return diff --git a/l2/l2_data_manager_new.py b/l2/l2_data_manager_new.py index 21cc71f..1dbc5fd3 100644 --- a/l2/l2_data_manager_new.py +++ b/l2/l2_data_manager_new.py @@ -846,6 +846,11 @@ 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: + return False, True, f"鍧囦环娑ㄥ箙({average_rate})灏忎簬1%" + # -------閲忕殑绾︽潫-------- if cls.volume_rate_info[code][0] < 0.2: return False, True, f"褰撴棩閲忔瘮({cls.volume_rate_info[code][0]})灏忎簬0.2" diff --git a/test/l2_trade_test.py b/test/l2_trade_test.py index d030330..b7cd8c6 100644 --- a/test/l2_trade_test.py +++ b/test/l2_trade_test.py @@ -218,6 +218,7 @@ def test_block(self): code = "002962" KPLCodeJXBlockManager().load_jx_blocks(code, 14.99, 14.99) + KPLCodeJXBlockManager().load_jx_blocks(code, 14.99, 14.99) block_info.init_code(code) kpl_data_manager.KPLLimitUpDataRecordManager.load_total_datas() yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes() diff --git a/test/test_code_attribute.py b/test/test_code_attribute.py new file mode 100644 index 0000000..32cbd94 --- /dev/null +++ b/test/test_code_attribute.py @@ -0,0 +1,25 @@ +from code_attribute import code_nature_analyse +from utils import init_data_util + + +def is_too_high(datas): + limit_up_price = round(datas[0]["close"] * 1.1, 2) + datas.reverse() + is_new_high = code_nature_analyse.is_price_too_high_in_days(datas, limit_up_price) + return is_new_high + + +if __name__ == "__main__": + code_str = "000536,000625,000628,000670,000766,000829,001311,001331,002189,002275,002331,002341,002363,002406,002416,002655,002691,002848,002861,002885,002906,002917,002962,300217,300462,300552,301111,301215,301372,600107,600178,600222,600288,600513,600698,600960,601777,603029,603286,603297,603569,605020,688314,688789" + codes = code_str.split(",") + for code in codes: + if code.find("00") != 0 and code.find("60") != 0: + continue + try: + datas = init_data_util.get_volumns_by_code(code, 120) + datas = datas[3:] + result = is_too_high(datas) + if result: + print(code, result) + except: + print(code, "鍑洪敊") diff --git a/third_data/code_plate_key_manager.py b/third_data/code_plate_key_manager.py index a48d004..e59202f 100644 --- a/third_data/code_plate_key_manager.py +++ b/third_data/code_plate_key_manager.py @@ -104,7 +104,7 @@ async_log_util.info(logger_kpl_block_can_buy, f"{code}:鑾峰彇鍒扮簿閫夋澘鍧�-{blocks}") else: # 杩樻病娑ㄥ仠鐨勯渶瑕佹洿鏂扮簿閫夋澘鍧� 鏇存柊绮鹃�夋澘鍧� - if abs(float(buy_1_price) - float(limit_up_price)) >= 0.001: + if abs(float(buy_1_price) - float(limit_up_price)) >= 0.001 or constant.TEST: # 闈炴定鍋滅姸鎬� UPDATE_TIME_SPACE = 5 * 60 time_diff = tool.trade_time_sub(tool.get_now_time_str(), "09:30:00") diff --git a/trade/huaxin/huaxin_trade_api.py b/trade/huaxin/huaxin_trade_api.py index 9bc7249..57ede74 100644 --- a/trade/huaxin/huaxin_trade_api.py +++ b/trade/huaxin/huaxin_trade_api.py @@ -37,6 +37,50 @@ def __run_recv_queue_trade(queue: multiprocessing.Queue): + + def __process_order(data): + code = data["securityID"] + accountID = data["accountID"] + orderStatus = data["orderStatus"] + orderRef = data["orderRef"] + orderSysID = data["orderSysID"] + insertTime = data.get("insertTime") + acceptTime = data.get("acceptTime") + insertDate = data.get("insertDate") + direction = data.get("direction") + limitPrice = data.get("limitPrice") + volume = data.get("volume") + is_shadow_order = False + # 鑾峰彇娑ㄥ仠浠� + limit_up_price = gpcode_manager.get_limit_up_price(code) + if limit_up_price and volume == huaxin_client_constant.SHADOW_ORDER_VOLUME: + if abs(float(limitPrice) - float(limit_up_price)) >= 0.01: + is_shadow_order = True + + order = HuaxinOrderEntity(code, orderStatus, orderRef, accountID, orderSysID, + insertTime=insertTime, acceptTime=acceptTime, + insertDate=insertDate, direction=direction, + is_shadow_order=is_shadow_order) + try: + if order.direction == str(huaxin_util.TORA_TSTP_D_Sell): + # 鍒锋柊鎸佷粨鍒楄〃 + huaxin_trade_data_update.add_position_list() + TradeResultProcessor.process_buy_order(order) + TradeResultProcessor.process_sell_order(order) + finally: + try: + # 鍔犲叆2娆★紝澧炲ぇ鍔犲叆鎴愬姛鐜� + __save_data_queue.put_nowait(data) + except Exception as e: + hx_logger_trade_debug.exception(e) + + if not is_shadow_order: + # 璁㈠崟鐩稿叧鍥炶皟 + # 閲嶆柊璇锋眰濮旀墭鍒楄〃涓庤祫閲� + # huaxin_trade_data_update.add_delegate_list("鏉ヨ嚜浜ゆ槗绠¢亾") + huaxin_trade_data_update.add_deal_list() + huaxin_trade_data_update.add_money_list() + # 璁剧疆缁撴灉 def __set_response(data_json): if 'request_id' not in data_json: @@ -62,6 +106,10 @@ async_log_util.info(hx_logger_trade_callback, f"response锛歳equest_id-{request_id}") __response_thread_pool.submit(__set_response, data_json) + if type(data_json.get("data")) == dict: + data = data_json["data"].get("data") + if type(data) == dict and "orderRef" in data: + __response_thread_pool.submit(__process_order, data) elif type_ == "trade_callback": try: # 浜ゆ槗鍥炶皟 @@ -72,48 +120,7 @@ if ctype == 0: data = data_json.get("data") # 鑾峰彇璁㈠崟鐘舵�� - code = data["securityID"] - accountID = data["accountID"] - orderStatus = data["orderStatus"] - orderRef = data["orderRef"] - orderSysID = data["orderSysID"] - insertTime = data.get("insertTime") - acceptTime = data.get("acceptTime") - insertDate = data.get("insertDate") - direction = data.get("direction") - limitPrice = data.get("limitPrice") - volume = data.get("volume") - is_shadow_order = False - # 鑾峰彇娑ㄥ仠浠� - limit_up_price = gpcode_manager.get_limit_up_price(code) - if limit_up_price and volume == huaxin_client_constant.SHADOW_ORDER_VOLUME: - if abs(float(limitPrice) - float(limit_up_price)) >= 0.01: - is_shadow_order = True - - order = HuaxinOrderEntity(code, orderStatus, orderRef, accountID, orderSysID, - insertTime=insertTime, acceptTime=acceptTime, - insertDate=insertDate, direction=direction, - is_shadow_order=is_shadow_order) - try: - if order.direction == str(huaxin_util.TORA_TSTP_D_Sell): - # 鍒锋柊鎸佷粨鍒楄〃 - huaxin_trade_data_update.add_position_list() - TradeResultProcessor.process_buy_order(order) - TradeResultProcessor.process_sell_order(order) - finally: - try: - # 鍔犲叆2娆★紝澧炲ぇ鍔犲叆鎴愬姛鐜� - __save_data_queue.put_nowait(data) - except Exception as e: - hx_logger_trade_debug.exception(e) - - if not is_shadow_order: - # 璁㈠崟鐩稿叧鍥炶皟 - # 閲嶆柊璇锋眰濮旀墭鍒楄〃涓庤祫閲� - # huaxin_trade_data_update.add_delegate_list("鏉ヨ嚜浜ゆ槗绠¢亾") - huaxin_trade_data_update.add_deal_list() - huaxin_trade_data_update.add_money_list() - # print("鍝嶅簲缁撴灉锛�", data_json['data']) + __process_order(data) finally: pass except: diff --git a/trade/huaxin/huaxin_trade_server.py b/trade/huaxin/huaxin_trade_server.py index 38142b5..191102b 100644 --- a/trade/huaxin/huaxin_trade_server.py +++ b/trade/huaxin/huaxin_trade_server.py @@ -27,7 +27,7 @@ import inited_data import outside_api_command_manager from code_attribute import gpcode_manager, code_volumn_manager, global_data_loader -from code_attribute.gpcode_manager import CodePrePriceManager +from code_attribute.gpcode_manager import CodePrePriceManager, CodesNameManager from db import mysql_data_delegate as mysql_data, redis_manager_delegate as redis_manager from db.redis_manager_delegate import RedisUtils from huaxin_client import l1_subscript_codes_manager, l2_data_transform_protocol @@ -366,10 +366,17 @@ limit_up_price = gpcode_manager.get_limit_up_price(code) if limit_up_price is not None: + average_rate = None + try: + average_price = data["totalValueTrade"] / data["totalVolumeTrade"] + pre_close_price = CodePrePriceManager.get_price_pre_cache(code) + average_rate = round((average_price - pre_close_price) / pre_close_price, 4) + except: + pass # 澶勭悊涔�1,鍗�1淇℃伅 code_price_manager.Buy1PriceManager().process(code, buy_1_price, buy_1_volume, time_str, limit_up_price, - sell_1_price, sell_1_volume // 100) + sell_1_price, sell_1_volume // 100, average_rate) latest_3m_buy1_money_list = code_price_manager.Buy1PriceManager().get_latest_3m_buy1_money_list(code) # -----------------------------閲嶆柊璁$畻L鎾ゅ悗--------------------------- # 濡傛灉鏃舵定鍋滅姸鎬� @@ -403,7 +410,9 @@ volume_info = l2_data_manager_new.L2TradeDataProcessor.volume_rate_info.get(code) if volume_info: volume_rate = volume_info[0] - need_cancel, msg = UCancelBigNumComputer().need_cancel(code, order_begin_pos, kpl_data_manager.KPLLimitUpDataRecordManager.get_current_reason_codes_dict(), volume_rate) + need_cancel, msg = UCancelBigNumComputer().need_cancel(code, order_begin_pos, + kpl_data_manager.KPLLimitUpDataRecordManager.get_current_reason_codes_dict(), + volume_rate) if need_cancel: l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, msg) except Exception as e: @@ -569,15 +578,13 @@ raise Exception("娌℃湁鑾峰彇鍒癓1鐜颁环") price = round(float(current_price) - 0.05, 2) async_log_util.info(logger_trade, f"API鍗�: 鍗曚环-{price}") - result = huaxin_trade_api.order(direction, code, volume, price, sinfo=sinfo, + order_ref = huaxin_util.create_order_ref() + result = huaxin_trade_api.order(direction, code, volume, price, sinfo=sinfo, order_ref=order_ref, blocking=True, request_id=request_id) - logger_debug.info(f"鍗栨帴鍙h繑鍥炴暟鎹細{result}") - order_ref = result.get("order_ref") # 濡傛灉鏄湪姝e父浜ゆ槗鏃堕棿鎻愪氦鐨�2s涔嬪唴杩樻湭鎴愪氦鐨勯渶瑕佹挙鍗� if int("092958") <= int(tool.get_now_time_str().replace(":", "")) <= int("150000"): self.__cancel_sell_thread_pool.submit(lambda: self.__cancel_sell_order(code, order_ref)) - - self.send_response({"code": 0, "data": result}, client_id, request_id) + self.send_response(result, client_id, request_id) else: result = huaxin_trade_api.order(direction, code, volume, price, price_type=price_type, sinfo=sinfo, blocking=True, request_id=request_id) @@ -1011,6 +1018,12 @@ fdata = {"code": code, "total": 0, "available": 0, "sell_rules_count": sell_rules_count} if positions: for d in positions: + code_name = gpcode_manager.get_code_name(d["securityID"]) + if not code_name: + # 鍒ゆ柇鏄惁鏈夊悕绉� + results = HistoryKDatasUtils.get_gp_codes_names([d["securityID"]]) + threading.Thread( + target=CodesNameManager.add_first_code_name(d["securityID"], results[0])).start() if d["prePosition"] <= 0: continue if d["securityID"] != code: @@ -1020,6 +1033,8 @@ break result = {"code": 0, "data": fdata} self.send_response(result, client_id, request_id) + + except Exception as e: logging.exception(e) self.send_response(json.dumps({"code": 1, "msg": f"鏁版嵁澶勭悊鍑洪敊锛歿e}"}), client_id, request_id) @@ -1027,6 +1042,33 @@ def OnCommonRequest(self, client_id, request_id, data): # 閫氱敤璇锋眰 ctype = data["ctype"] + try: + if ctype == "get_sell_result": + order_ref = data["order_ref"] + order_entity = huaxin_trade_order_processor.TradeResultProcessor.get_huaxin_order_by_order_ref( + order_ref) + if not order_entity: + self.send_response(json.dumps({"code": 1, "msg": f"娌℃湁鑾峰彇鍒拌鍗曠姸鎬�"}), client_id, request_id) + else: + code_name = gpcode_manager.get_code_name(order_entity.code) + result = {} + if huaxin_util.is_canceled(order_entity.orderStatus): + result = {"code": 0, + "data": {"orderStatus": order_entity.orderStatus, "code": order_entity.code, + "msg": f"銆恵order_entity.code}({code_name})銆戝凡鎾ゅ崟"}} + elif huaxin_util.is_deal(order_entity.orderStatus): + result = {"code": 0, + "data": {"orderStatus": order_entity.orderStatus, "code": order_entity.code, + "msg": f"銆恵order_entity.code}({code_name})銆戝凡缁忔垚浜�"}} + else: + result = {"code": 0, + "data": {"orderStatus": order_entity.orderStatus, "code": order_entity.code, + "msg": f"銆恵order_entity.code}({code_name})銆戝凡鎸傚崟"}} + self.send_response(result, client_id, request_id) + except Exception as e: + logging.exception(e) + self.send_response(json.dumps({"code": 1, "msg": f"鏁版嵁澶勭悊鍑洪敊锛歿e}"}), client_id, request_id) + # 鑾峰彇瀛愮被鍨� -- Gitblit v1.8.0