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