From 394e24aaba9b28c6427444d47aab6505c735fb7e Mon Sep 17 00:00:00 2001
From: Administrator <admin@example.com>
Date: 星期五, 30 九月 2022 16:54:18 +0800
Subject: [PATCH] L2数据处理完善

---
 l2_data_manager.py | 1098 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 936 insertions(+), 162 deletions(-)

diff --git a/l2_data_manager.py b/l2_data_manager.py
index 25093bc..ac30d38 100644
--- a/l2_data_manager.py
+++ b/l2_data_manager.py
@@ -18,7 +18,7 @@
 import redis_manager
 import tool
 import trade_manager
-from log import logger_l2_trade, logger_l2_trade_cancel, logger_l2_trade_buy
+from log import logger_l2_trade, logger_l2_trade_cancel, logger_l2_trade_buy, logger_l2_process
 from trade_data_manager import TradeBuyDataManager
 import limit_up_time_manager
 
@@ -142,6 +142,30 @@
         redis = TradePointManager.__get_redis()
         redis.delete("compute_info_for_cancel_buy-{}".format(code))
 
+    # 浠庝拱鍏ヤ俊鍙峰紑濮嬭缃定鍋滀拱涓庢定鍋滄挙鐨勫崟鏁�
+    @classmethod
+    def set_count_info_for_cancel_buy(cls, code, index, buy_count, cancel_count):
+        redis = TradePointManager.__get_redis()
+        expire = tool.get_expire()
+        redis.setex("count_info_for_cancel_buy-{}".format(code), expire, json.dumps((index, buy_count, cancel_count)))
+        logger_l2_trade_buy.info("{}淇濆瓨鎾ゅ崟绾拱棰濅俊鎭細{}锛寋}", code, index, buy_count, cancel_count)
+
+    # 鑾峰彇涔版挙绾拱棰濊绠椾俊鎭�
+    @classmethod
+    def get_count_info_for_cancel_buy(cls, code):
+        redis = TradePointManager.__get_redis()
+        info = redis.get("count_info_for_cancel_buy-{}".format(code))
+        if info is None:
+            return None, 0, 0
+        else:
+            info = json.loads(info)
+            return info[0], info[1], info[2]
+
+    @classmethod
+    def delete_count_info_for_cancel_buy(cls, code):
+        redis = TradePointManager.__get_redis()
+        redis.delete("count_info_for_cancel_buy-{}".format(code))
+
 
 def load_l2_data(code, force=False):
     redis = _redisManager.getRedis()
@@ -208,11 +232,6 @@
     return datas
 
 
-# TODO 鑾峰彇l2鐨勬暟鎹�
-def get_l2_data_index(code, key):
-    pass
-
-
 def parseL2Data(str):
     day = datetime.now().strftime("%Y%m%d")
     dict = json.loads(str)
@@ -247,7 +266,6 @@
 class L2DataUtil:
     @classmethod
     def is_same_time(cls, time1, time2):
-        # TODO 娴嬭瘯
         if global_util.TEST:
             return True
         time1_s = time1.split(":")
@@ -331,8 +349,11 @@
             num = item["num"]
             limitPrice = item["limitPrice"]
             # 娑ㄥ仠浠�
-            if limit_up_price is not None and limit_up_price == tool.to_price(decimal.Decimal(price)):
-                limitPrice = 1
+            if limit_up_price is not None:
+                if limit_up_price == tool.to_price(decimal.Decimal(price)):
+                    limitPrice = 1
+                else:
+                    limitPrice = 0
                 item["limitPrice"] = "{}".format(limitPrice)
             operateType = item["operateType"]
             cancelTime = item["cancelTime"]
@@ -353,6 +374,11 @@
     def get_time_as_second(cls, time_str):
         ts = time_str.split(":")
         return int(ts[0]) * 3600 + int(ts[1]) * 60 + int(ts[2])
+
+    # @classmethod
+    # def get_time_as_str(cls, time_seconds):
+    #     ts = time_str.split(":")
+    #     return int(ts[0]) * 3600 + int(ts[1]) * 60 + int(ts[2])
 
     # 鏄惁鏄定鍋滀环涔�
     @classmethod
@@ -383,13 +409,6 @@
         if price * num * 100 < 50 * 10000:
             return False
         return True
-
-    @staticmethod
-    def is_index_end(code, index):
-        if index >= len(local_today_datas[code]) - 1:
-            return True
-        else:
-            return False
 
 
 # L2浜ゆ槗鏁版嵁澶勭悊鍣�
@@ -427,6 +446,7 @@
         __start_time = round(t.time() * 1000)
         try:
             if len(datas) > 0:
+
                 # 鍒ゆ柇浠锋牸鍖洪棿鏄惁姝g‘
                 if not data_process.is_same_code_with_price(code, float(datas[0]["val"]["price"])):
                     raise L2DataException(L2DataException.CODE_PRICE_ERROR,
@@ -444,25 +464,31 @@
                     local_today_datas[code].extend(add_datas)
                     l2_data_util.load_num_operate_map(local_today_num_operate_map, code, add_datas)
                 total_datas = local_today_datas[code]
-                # 涔板叆纭鐐瑰鐞�
-                TradeBuyDataManager.process_buy_sure_position_info(code, capture_timestamp, total_datas,
-                                                                   total_datas[-1],
-                                                                   add_datas)
+                # 杩囨椂 涔板叆纭鐐瑰鐞�
+                # TradeBuyDataManager.process_buy_sure_position_info(code, capture_timestamp, total_datas,
+                #                                                    total_datas[-1],
+                #                                                    add_datas)
                 if len(add_datas) > 0:
+                    _start_time = round(t.time() * 1000)
                     # 璁$畻澶у崟鏁伴噺
                     cls.__compute_big_money_data(code, add_datas)
 
                     latest_time = add_datas[len(add_datas) - 1]["val"]["time"]
                     # 鏃堕棿宸笉鑳藉お澶ф墠鑳藉鐞�
+                    # TODO 鏆傛椂鍏抽棴澶勭悊
                     if L2DataUtil.is_same_time(now_time_str, latest_time):
                         # 鍒ゆ柇鏄惁宸茬粡鎸傚崟
                         state = trade_manager.get_trade_state(code)
+                        start_index = len(total_datas) - len(add_datas)
+                        end_index = len(total_datas)-1
                         if state == trade_manager.TRADE_STATE_BUY_DELEGATED or state == trade_manager.TRADE_STATE_BUY_PLACE_ORDER:
                             # 宸叉寕鍗�
-                            cls.__process_order(code, len(total_datas) - len(add_datas) - 3, capture_timestamp)
+                            cls.__process_order(code, start_index,end_index, capture_timestamp)
                         else:
                             # 鏈寕鍗�
-                            cls.__process_not_order(code, add_datas, capture_timestamp)
+                            cls.__process_not_order(code,start_index,end_index,capture_timestamp)
+                    logger_l2_process.info("code:{} 澶勭悊鏁版嵁鑼冨洿: {}-{} 澶勭悊鏃堕棿:{}", code, add_datas[0]["index"],
+                                           add_datas[-1]["index"], round(t.time() * 1000) - __start_time)
                 # 淇濆瓨鏁版嵁
                 save_l2_data(code, datas, add_datas)
         finally:
@@ -483,48 +509,140 @@
 
     # 澶勭悊鏈寕鍗�
     @classmethod
-    def __process_not_order(cls, code, add_datas, capture_time):
+    def __process_not_order(cls, code, start_index, end_index, capture_time):
         # 鑾峰彇闃堝��
         threshold_money = cls.__get_threshmoney(code)
-        cls.__start_compute_buy(code, len(local_today_datas[code]) - len(add_datas), threshold_money, capture_time)
+        cls.__start_compute_buy(code, start_index, end_index, threshold_money, capture_time)
+
+    @classmethod
+    def __statistic_count_l2_data_for_cancel(cls, code, start_index, end_index, has_cancel_single=False):
+        index, old_buy_count, old_cancel_count = TradePointManager.get_count_info_for_cancel_buy(code)
+        for i in range(start_index, end_index + 1):
+            buy_count, buy_cancel_count = cls.__count_l2_data_for_cancel(code, i, i)
+            old_buy_count += buy_count
+
+            old_cancel_count += buy_cancel_count
+            if old_buy_count > 0 and (old_buy_count - old_cancel_count) / old_buy_count < 0.3 and has_cancel_single:
+                return i, True
+        TradePointManager.set_count_info_for_cancel_buy(code, end_index, old_buy_count,
+                                                        old_cancel_count)
+        return end_index, False
 
     # 澶勭悊宸叉寕鍗�
     @classmethod
-    def __process_order(cls, code, start_index, capture_time):
+    def __process_order(cls, code, start_index, end_index, capture_time, new_add=True):
         if start_index < 0:
             start_index = 0
+
+        if end_index < start_index:
+            return
         # 鑾峰彇涔嬪墠鏄惁鏈夎褰曠殑鎾や拱淇″彿
-        cancel_index = TradePointManager.get_buy_cancel_single_pos(code)
+        #  cancel_index = TradePointManager.get_buy_cancel_single_pos(code)
 
-        cancel_computed_index, cancel_buy_num = TradePointManager.get_compute_info_for_cancel_buy(code)
-        if cancel_computed_index is None:
-            logger_l2_trade.error("{} 鏈幏鍙栧埌涔版挙绾拱棰�,璧峰璁$畻浣嶏細{}", code, start_index)
+        # cancel_computed_index, cancel_buy_num = TradePointManager.get_compute_info_for_cancel_buy(code)
+        # if cancel_computed_index is None:
+        #     logger_l2_trade.error("{} 鏈幏鍙栧埌涔版挙绾拱棰�,璧峰璁$畻浣嶏細{}", code, start_index)
 
-        buy_single_index, buy_exec_index, buy_compute_index, buy_num = cls.__get_order_begin_pos(code)
-        if cancel_index is None:
-            # 鏃犳挙鍗曚俊鍙疯捣濮嬬偣璁板綍
-            cancel_index = cls.__compute_order_cancel_begin_single(code, max(start_index - 3, 0), 3)
-            if cancel_index is not None:
-                cls.debug(code, "鎵惧埌鎾ゅ崟淇″彿-{}锛屼拱鍏ヤ俊鍙蜂负 锛屾暟鎹鐞嗚捣濮嬬偣锛歿}", cancel_index, start_index)
-                # 淇濆瓨鎾ゅ崟淇″彿
-                TradePointManager.set_buy_cancel_single_pos(code, cancel_index)
-            # 鑾峰彇闃堝�� 鏈変拱鎾や俊鍙凤紝缁熻鎾や拱绾拱棰�
-        threshold_money = cls.__get_threshmoney(code)
-        cls.__start_compute_cancel(code, cancel_index, cancel_computed_index + 1,
-                                   cancel_buy_num,
-                                   threshold_money,
-                                   capture_time)
+        # 缁熻缇ゆ挙澶у崟
+        L2BetchCancelBigNumProcessor.process_new(code, start_index, end_index)
 
-        # 鏄惁鏈夎櫄鎷熶笅鍗�
-        unreal_buy_info = cls.unreal_buy_dict.get(code)
-        if unreal_buy_info is not None:
-            cls.debug(code, "鏈夎櫄鎷熶笅鍗曪紝鏃犱拱鎾や俊鍙凤紝寮�濮嬫墽琛屼拱鍏�,鎴浘鏃堕棿锛歿}", capture_time)
-            # unreal_buy_info 鐨勫唴瀹规牸寮忎负锛�(瑙︽硶涔版搷浣滀笅鏍�,鎴浘鏃堕棿)
-            # 鐪熷疄涓嬪崟
-            cls.__buy(code, unreal_buy_info[1], local_today_datas[code][unreal_buy_info[0]],
-                      unreal_buy_info[0])
+        # 缁熻鏈�澶ц繛缁拱鍗�
+        L2ContinueLimitUpCountManager.process(code, start_index, end_index)
 
-    # 寮�濮嬭绠楁挙鐨勪俊鍙�
+        # 璁$畻澶у崟鎾ら攢
+        need_cancel, cancel_data = L2BigNumProcessor.process_cancel_with_big_num(code, start_index, end_index)
+        if need_cancel:
+            # 宸茬粡鎾ゅ崟浜�
+            threshold_money = cls.__get_threshmoney(code)
+            # 閲嶆柊澶勭悊涓嬪崟
+            cls.__start_compute_buy(code, cancel_data["index"] + 1, end_index, threshold_money, capture_time)
+            return
+
+        # buy_single_index, buy_exec_index, buy_compute_index, buy_num = cls.__get_order_begin_pos(code)
+        # if cancel_index is None:
+        # 鏃犳挙鍗曚俊鍙疯捣濮嬬偣璁板綍
+
+        continue_cancel = L2ContinueLimitUpCountManager.get_continue_count(code)
+        order_cancel_begin_start = max(start_index - (continue_cancel - 1),
+                                       0) if new_add else start_index
+        order_cancel_begin_end = end_index
+        total_datas = local_today_datas[code]
+
+        little_cancel = False
+        # 澶у崟鎾ゅ崟鐨勬暟鎹笉涓虹┖
+        if cancel_data is not None:
+            # 灏忕兢鎾や簨浠�
+            continue_cancel = 5
+            cancel_time_seconds = L2DataUtil.get_time_as_second(cancel_data["val"]["time"])
+            # 鏌ユ壘涓婁竴绉掍笌涓嬩竴绉�
+            for i in range(int(cancel_data["index"]), 0, -1):
+                # 鏌ユ壘涓婁竴绉掑拰涓嬩竴绉�
+                if total_datas[i]["val"]["time"] != cancel_data["val"][
+                    "time"] and cancel_time_seconds - L2DataUtil.get_time_as_second(total_datas[i]["val"]["time"]) > 1:
+                    order_cancel_begin_start = i + 1
+                    break
+
+            for i in range(int(cancel_data["index"]), len(local_today_datas[code])):
+                # 鏌ユ壘涓婁竴绉掑拰涓嬩竴绉�
+                if total_datas[i]["val"]["time"] != cancel_data["val"]["time"] and L2DataUtil.get_time_as_second(
+                        total_datas[i]["val"]["time"]) - cancel_time_seconds > 1:
+                    order_cancel_begin_end = i - 1
+                    break
+            cls.cancel_debug(code, "灏忕兢鎾や簨浠惰绠楄寖鍥达細{}锛寋}", order_cancel_begin_start, order_cancel_begin_end)
+            little_cancel = True
+        cancel_start_index = None
+        cancel_end_index = None
+        need_cancel = False
+        if little_cancel:
+            # 灏忕兢鎾や簨浠�
+            cancel_start_index, cancel_end_index = cls.__compute_order_cancel_little_begin_single(code,
+                                                                                                  order_cancel_begin_start
+                                                                                                  , continue_cancel,
+                                                                                                  order_cancel_begin_end)
+            if cancel_start_index is not None:
+                cls.debug(code, "鎵惧埌灏忕兢鎾や俊鍙凤紝鎾ゅ崟淇″彿鑼冨洿:{}-{}", cancel_start_index, cancel_end_index)
+                # 鏈夊皬缇ゆ挙淇″彿
+                need_cancel = True
+            else:
+                # 涓嶆弧瓒冲皬缇ゆ挙,浠庡皬缇ゆ挙鍚庨潰涓�鏉℃暟鎹户缁鐞�
+                cls.__process_order(code, cancel_data["index"] + 1, end_index, capture_time, False)
+                return
+
+        else:
+            # 澶х兢鎾や簨浠�
+            cancel_start_index, cancel_end_index = cls.__compute_order_cancel_begin_single(
+                code, order_cancel_begin_start
+                , continue_cancel, order_cancel_begin_end)
+            if cancel_start_index is not None:
+                cls.debug(code, "鎵惧埌澶х兢鎾や俊鍙凤紝杩炵画绗旀暟闃堝�硷細{}锛� 鎾ゅ崟淇″彿鑼冨洿:{}-{}", continue_cancel, cancel_start_index,
+                          cancel_end_index)
+                # 鍒ゆ柇鏄惁鏈夊ぇ缇ゆ挙澶у崟鎾�
+                need_cancel = L2BetchCancelBigNumProcessor.need_cancel(code, cancel_start_index, cancel_end_index)
+                if need_cancel:
+                    cls.debug(code, "澶х兢鎾や俊鍙锋湁澶у崟鎾ら攢")
+                else:
+                    cls.debug(code, "澶х兢鎾や俊鍙锋棤澶у崟鎾ら攢")
+
+        if need_cancel:
+            # 闇�瑕佹挙涔�
+            cls.cancel_buy(code)
+            if cancel_end_index >= end_index:
+                return
+            # 缁х画澶勭悊涓嬪崟淇″彿
+            threshold_money = cls.__get_threshmoney(code)
+            cls.__start_compute_buy(code, cancel_end_index + 1, end_index, threshold_money, capture_time, False)
+
+        else:
+            # 鏄惁鏈夎櫄鎷熶笅鍗�
+            unreal_buy_info = cls.unreal_buy_dict.get(code)
+            if unreal_buy_info is not None:
+                cls.debug(code, "鏈夎櫄鎷熶笅鍗曪紝鏃犱拱鎾や俊鍙凤紝寮�濮嬫墽琛屼拱鍏ワ紝鎵ц浣嶇疆锛歿},鎴浘鏃堕棿锛歿}", unreal_buy_info[0], capture_time)
+                # unreal_buy_info 鐨勫唴瀹规牸寮忎负锛�(瑙︽硶涔版搷浣滀笅鏍�,鎴浘鏃堕棿)
+                # 鐪熷疄涓嬪崟
+                cls.__buy(code, unreal_buy_info[1], local_today_datas[code][unreal_buy_info[0]],
+                          unreal_buy_info[0])
+
+    # 杩囨椂 寮�濮嬭绠楁挙鐨勪俊鍙�
     @classmethod
     def __start_compute_cancel(cls, code, cancel_index, compute_start_index, origin_num, threshold_money, capture_time):
         # sure_type 0-铏氭嫙鎸備拱浣�  1-鐪熷疄鎸備拱浣�
@@ -552,7 +670,7 @@
 
             if computed_index < len(local_today_datas[code]) - 1:
                 # 鏁版嵁灏氭湭澶勭悊瀹�,閲嶆柊杩涘叆涓嬪崟璁$畻娴佺▼
-                cls.__start_compute_buy(code, computed_index + 1, threshold_money, capture_time)
+                cls.__start_compute_buy(code, computed_index + 1, threshold_money, capture_time, False)
                 pass
         else:
             cls.debug(code, "鎾や拱绾拱棰濊绠楋紝璁$畻浣嶇疆锛歿}-{}锛岀洰鍓嶄负姝㈢函涔版墜鏁帮細{}", compute_start_index, total_datas[-1]["index"],
@@ -596,21 +714,38 @@
             TradePointManager.delete_buy_point(code)
             TradePointManager.delete_buy_cancel_point(code)
             TradePointManager.delete_compute_info_for_cancel_buy(code)
+            TradePointManager.delete_count_info_for_cancel_buy(code)
+            # 鍒犻櫎澶х兢鎾や簨浠剁殑澶у崟
+            L2BetchCancelBigNumProcessor.del_recod(code)
             cls.debug(code, "鎵ц鎾ゅ崟鎴愬姛")
         except Exception as e:
             cls.debug(code, "鎵ц鎾ゅ崟寮傚父锛歿}", str(e))
 
     @classmethod
-    def __start_compute_buy(cls, code, compute_start_index, threshold_money, capture_time):
+    def cancel_buy(cls, code):
+        # 鍒犻櫎澶х兢鎾や簨浠剁殑澶у崟
+        L2BetchCancelBigNumProcessor.del_recod(code)
+        L2ContinueLimitUpCountManager.del_data(code)
+        if code in cls.unreal_buy_dict:
+            cls.unreal_buy_dict.pop(code)
+        else:
+            cls.__cancel_buy(code)
+
+    @classmethod
+    def __start_compute_buy(cls, code, compute_start_index, compute_end_index, threshold_money, capture_time,
+                            new_add=True):
+        if compute_end_index < compute_start_index:
+            return
+
         total_datas = local_today_datas[code]
         # 鑾峰彇涔板叆淇″彿璁$畻璧峰浣嶇疆
-        # index, num, finish_index = cls.__get_order_begin_pos(code)
         buy_single_index, buy_exec_index, buy_compute_index, num = cls.__get_order_begin_pos(code)
         # 鏄惁涓烘柊鑾峰彇鍒扮殑浣嶇疆
         new_get_pos = False
         if buy_single_index is None:
             # 鏈変拱鍏ヤ俊鍙�
-            has_single, _index = cls.__compute_order_begin_pos(code, max(compute_start_index - 3, 0), 3)
+            has_single, _index = cls.__compute_order_begin_pos(code, max(
+                compute_start_index - 2 if new_add else compute_start_index, 0), 3, compute_end_index)
             buy_single_index = _index
             if has_single:
                 num = 0
@@ -623,9 +758,16 @@
             return None
 
         # 涔板叆绾拱棰濈粺璁�
-        compute_index, buy_nums = cls.__sum_buy_num_for_order_2(code, max(buy_single_index, compute_start_index), num,threshold_money,buy_single_index)
+        compute_index, buy_nums, rebegin_buy_pos = cls.__sum_buy_num_for_order_3(code, max(buy_single_index,
+                                                                                           compute_start_index),
+                                                                                 compute_end_index, num,
+                                                                                 threshold_money, buy_single_index,
+                                                                                 capture_time)
+        if rebegin_buy_pos is not None:
+            # 闇�瑕侀噸鏂拌绠楃函涔伴
+            cls.__start_compute_buy(code, rebegin_buy_pos, compute_end_index, threshold_money, capture_time, False)
+            return
 
-        #cls.__sum_buy_num_for_order(code, max(buy_single_index, compute_start_index), num,threshold_money)
         if compute_index is not None:
             cls.debug(code, "鑾峰彇鍒颁拱鍏ユ墽琛屼綅缃細{} m鍊硷細{} 绾拱鎵嬫暟锛歿} 鏁版嵁锛歿}", compute_index, threshold_money, buy_nums,
                       total_datas[compute_index])
@@ -636,23 +778,41 @@
             # 鍒犻櫎涔嬪墠鐨勬墍鏈夋挙鍗曚俊鍙�
             TradePointManager.delete_buy_cancel_point(code)
             TradePointManager.delete_compute_info_for_cancel_buy(code)
-            # 涓轰拱鎾や繚瀛樺熀纭�绾拱棰�
-            TradePointManager.set_compute_info_for_cancel_buy(code, compute_index, buy_nums)
+            TradePointManager.delete_count_info_for_cancel_buy(code)
+            TradeBuyDataManager.remove_buy_position_info(code)
+            # 宸茶繃鏃� 涓轰拱鎾や繚瀛樺熀纭�绾拱棰�
+            # TradePointManager.set_compute_info_for_cancel_buy(code, compute_index, buy_nums)
+            b_buy_count, b_buy_cancel_count = cls.__count_l2_data_before_for_cancel(code, buy_single_index)
+            buy_count, buy_cancel_count = cls.__count_l2_data_for_cancel(code, buy_single_index, compute_index)
+            TradePointManager.set_count_info_for_cancel_buy(code, compute_index, b_buy_count + buy_count,
+                                                            b_buy_cancel_count + buy_cancel_count)
+            # 璁$畻澶у崟(浠庝拱鍏ヤ俊鍙疯捣濮嬬偣鍒版寕鍗曟墽琛岀偣),杩斿洖鏄惁鍙栨秷
+            cancel_result, cancel_data = L2BigNumProcessor.process_cancel_with_big_num(code, buy_single_index,
+                                                                                       compute_index)
+            # 璁$畻澶х兢鎾ょ殑澶у崟
+            L2BetchCancelBigNumProcessor.process_new(code, buy_single_index, compute_index)
+
+            L2ContinueLimitUpCountManager.process(code, buy_single_index, compute_index)
 
             # 鏁版嵁鏄惁澶勭悊瀹屾瘯
-            if L2DataUtil.is_index_end(code, compute_index):
+            if compute_index >= compute_end_index:
                 cls.debug(code, "鏁版嵁澶勭悊瀹屾瘯锛屼笅鍗�, 鏁版嵁鎴浘鏃堕棿-{}", capture_time)
-                # 鏁版嵁宸茬粡澶勭悊瀹屾瘯锛屼笅鍗�
-                cls.__buy(code, capture_time, total_datas[compute_index], compute_index)
+                # 鏁版嵁宸茬粡澶勭悊瀹屾瘯锛屽鏋滆繕娌℃挙鍗曞氨瀹為檯涓嬪崟
+                if not cancel_result:
+                    cls.__buy(code, capture_time, total_datas[compute_index], compute_index)
             else:
                 # 鏁版嵁灏氭湭澶勭悊瀹屾瘯锛岃繘琛屼笅涓�姝ュ鐞�
                 cls.debug(code, "鏁版嵁灏氭湭澶勭悊瀹屾瘯锛岃繘琛屼笅涓�姝ュ鐞嗭紝澶勭悊杩涘害锛歿}", compute_index)
-                cls.__process_order(code, compute_index + 1, capture_time)
-
+                # 濡傛灉杩樻病鎾ゅ崟锛屽氨缁х画澶勭悊宸蹭笅鍗曠殑姝ラ
+                if not cancel_result:
+                    cls.__process_order(code, compute_index + 1, compute_end_index, capture_time, False)
+                else:
+                    cls.__start_compute_buy(code, compute_index + 1, compute_end_index, threshold_money, capture_time,
+                                            False)
         else:
             # 鏈揪鍒颁笅鍗曟潯浠讹紝淇濆瓨绾拱棰濓紝璁剧疆绾拱棰�
             # 璁板綍涔板叆淇″彿浣嶇疆
-            cls.__save_order_begin_data(code, buy_single_index, -1, len(total_datas) - 1, buy_nums)
+            cls.__save_order_begin_data(code, buy_single_index, -1, compute_end_index, buy_nums)
         pass
 
     # 鑾峰彇涓嬪崟璧峰淇″彿
@@ -668,105 +828,102 @@
     # 璁$畻涓嬪崟璧峰淇″彿
     # compute_data_count 鐢ㄤ簬璁$畻鐨刲2鏁版嵁鏁伴噺
     @classmethod
-    def __compute_order_begin_pos(cls, code, start_index, continue_count):
+    def __compute_order_begin_pos(cls, code, start_index, continue_count, end_index):
         # 鍊掓暟100鏉℃暟鎹煡璇�
         datas = local_today_datas[code]
-        __len = len(datas)
-        if len(datas) - start_index < continue_count:
+        if end_index - start_index + 1 < continue_count:
             return False, None
         __time = None
-        _limit_up_count_1s = 0
-        _limit_up_count_1s_start_index = -1
 
-        for i in range(start_index, __len - (continue_count - 1)):
+        last_index = None
+        count = 0
+        start = None
+
+        for i in range(start_index, end_index + 1):
             _val = datas[i]["val"]
             # 鏃堕棿瑕�>=09:30:00
             if L2DataUtil.get_time_as_second(_val["time"]) < second_930:
                 continue
 
-            # 鏈夎繛缁�4涓定鍋滀拱灏辨爣璁拌绠楄捣濮嬬偣
-            if L2DataUtil.is_limit_up_price_buy(_val):
-                index_0 = i
-                index_1 = -1
-                index_2 = -1
-                # index_3 = -1
-                for j in range(index_0 + 1, __len):
-                    # 娑ㄥ仠涔�
-                    if L2DataUtil.is_limit_up_price_buy(datas[j]["val"]):
-                        index_1 = j
-                        break
-
-                if index_1 > 0:
-                    for j in range(index_1 + 1, __len):
-                        # 娑ㄥ仠涔�
-                        if L2DataUtil.is_limit_up_price_buy(datas[j]["val"]):
-                            index_2 = j
-                            break
-                # if index_2 > 0:
-                #     for j in range(index_2 + 1, __len):
-                #         # 娑ㄥ仠涔�
-                #         if datas[j]["val"]["limitPrice"] == 1 and datas[j]["val"]["operateType"] == 0:
-                #             index_3 = j
-                if index_1 - index_0 == 1 and index_2 - index_1 == 1:  # and index_3 - index_2 == 1
-                    logger_l2_trade.info("鎵惧埌鐗╃悊杩炵画娑ㄥ仠涔� {},{},{}".format(code, i, datas[i]))
-                    return True, i
-            # 鍚�1s鍐呮湁涓嶈繛缁殑4涓定鍋滀拱锛堝鏋滈亣涔版挙灏遍噸鏂拌绠楋紝涓棿鍙棿闅斾笉娑ㄥ仠涔帮級鏍囪璁$畻璧峰鐐�
-            if L2DataUtil.is_limit_up_price_buy(_val):
-                # 娑ㄥ仠涔�
-                if __time is None:
-                    _time = datas[i]["val"]["time"]
-                    _limit_up_count_1s = 1
-                    _limit_up_count_1s_start_index = i
-                elif _time == _val["time"]:
-                    _limit_up_count_1s += 1
-                else:
-                    _time = datas[i]["val"]["time"]
-                    _limit_up_count_1s = 1
-                    _limit_up_count_1s_start_index = i
-            elif _val["operateType"] == 1:
-                # 涔版挙
-                _time = None
-                _limit_up_count_1s = 0
-                _limit_up_count_1s_start_index = -1
-
-            if _limit_up_count_1s >= 4 and _limit_up_count_1s_start_index > -1:
-                logger_l2_trade.info("鎵惧埌鍚屼竴绉掕繛缁定鍋滀拱 {},{},{}".format(code, _limit_up_count_1s_start_index, datas[i]))
-                return True, _limit_up_count_1s_start_index
+            if L2DataUtil.is_limit_up_price_buy(_val) and (last_index is None or (i - last_index == 1 and datas[last_index]["val"]["time"] == datas[i]["val"]["time"])):
+                if start is None:
+                    start = i
+                last_index = i
+                count += datas[i]["re"]
+                if count >= continue_count:
+                    return True, start
+            else:
+                last_index = None
+                count = 0
+                start = None
 
         return False, None
 
-    # 鏄惁鏈夋挙閿�淇″彿
+    # 澶х兢鎾や簨浠�,鏈�澶氱浉闅�1s
     @classmethod
-    def __compute_order_cancel_begin_single(cls, code, start_index, continue_count):
+    def __compute_order_cancel_begin_single(cls, code, start_index, continue_count, end_index):
+        datas = local_today_datas[code]
+        if end_index - start_index + 1 < continue_count:
+            return None, None
+        count = 0
+        start = -1
+        start_time = None
+        for i in range(start_index, end_index + 1):
+            _val = datas[i]["val"]
+            _timestamp = L2DataUtil.get_time_as_second(_val["time"])
+            if L2DataUtil.get_time_as_second(_val["time"]) < second_930:
+                continue
+            if L2DataUtil.is_limit_up_price_buy_cancel(_val) and (start_time is None or _timestamp - start_time < 2):
+                if start == -1:
+                    start = i
+                    start_time = L2DataUtil.get_time_as_second(_val["time"])
+                count += datas[i]["re"]
+            else:
+                if count >= continue_count:
+                    return start, i - 1
+                start = -1
+                count = 0
+                start_time = None
+        if count >= continue_count:
+            return start, end_index
+        else:
+            return None, None
+
+    # 灏忕兢鎾や簨浠�
+    @classmethod
+    def __compute_order_cancel_little_begin_single(cls, code, start_index, continue_count, end_index=None):
+        # 蹇呴』涓哄悓涓�绉掔殑鏁版嵁
+        same_second = True
         datas = local_today_datas[code]
         __len = len(datas)
         if len(datas) - start_index < continue_count:
-            return None
-        for i in range(start_index, __len - (continue_count - 1)):
+            return None, None
+        count = 0
+        start = -1
+        start_time = None
+        if end_index is None:
+            end_index = __len - continue_count
+        for i in range(start_index, end_index + 1):
             _val = datas[i]["val"]
-            if L2DataUtil.get_time_as_second(_val["time"]) < second_930:
+            _timestamp = L2DataUtil.get_time_as_second(_val["time"])
+            if _timestamp < second_930:
                 continue
-            # 鏈夎繛缁�3涓拱鎾�
-            if L2DataUtil.is_limit_up_price_buy_cancel(_val):
-                index_0 = i
-                index_1 = -1
-                index_2 = -1
-                for j in range(index_0 + 1, __len):
-                    # 娑ㄥ仠涔�
-                    if L2DataUtil.is_limit_up_price_buy_cancel(datas[j]["val"]):
-                        index_1 = j
-                        break
-
-                if index_1 > 0:
-                    for j in range(index_1 + 1, __len):
-                        # 娑ㄥ仠涔�
-                        if L2DataUtil.is_limit_up_price_buy_cancel(datas[j]["val"]):
-                            index_2 = j
-                            break
-                if index_1 - index_0 == 1 and index_2 - index_1 == 1:
-                    logger_l2_trade.info("杩炵画3涓定鍋滀拱鎾� {},{},{}".format(code, i, json.dumps(datas[i])))
-                    return i
-        return None
+            # 闂撮殧鏃堕棿涓嶈兘澶氫簬1s
+            if L2DataUtil.is_limit_up_price_buy_cancel(_val) and (start_time is None or _timestamp - start_time < 2):
+                if start == -1:
+                    start = i
+                    start_time = L2DataUtil.get_time_as_second(_val["time"])
+                count += int(datas[i]["re"])
+            else:
+                if count >= continue_count:
+                    return start, i - 1
+                start = -1
+                count = 0
+                start_time = None
+        if count >= continue_count:
+            return start, end_index
+        else:
+            return None, None
 
     # 鏄惁鍙互涓嬪崟
     def __is_can_order(self):
@@ -789,7 +946,7 @@
         else:
             return 1, index, data
 
-    # 缁熻涔板叆鍑�涔伴噺
+    # 杩囨椂 缁熻涔板叆鍑�涔伴噺
     @classmethod
     def __sum_buy_num_for_order(cls, code, compute_start_index, origin_num, threshold_money):
         total_datas = local_today_datas[code]
@@ -805,16 +962,16 @@
                 # 娑ㄥ仠涔�
                 buy_nums += int(_val["num"]) * int(total_datas[i]["re"])
                 if buy_nums >= threshold_num:
-                    logger_l2_trade_buy.info("{}鑾峰彇鍒颁拱鍏ユ墽琛岀偣锛歿} 缁熻绾拱鎵嬫暟锛歿} 鐩爣绾拱鎵嬫暟锛歿}", code, i, buy_nums, threshold_num)
+                    cls.debug(code, "鑾峰彇鍒颁拱鍏ユ墽琛岀偣锛歿} 缁熻绾拱鎵嬫暟锛歿} 鐩爣绾拱鎵嬫暟锛歿}", i, buy_nums, threshold_num)
                     return i, buy_nums
             elif L2DataUtil.is_limit_up_price_buy_cancel(_val):
                 # 娑ㄥ仠涔版挙
                 buy_nums -= int(_val["num"]) * int(total_datas[i]["re"])
-        logger_l2_trade_buy.info("{}灏氭湭鑾峰彇鍒颁拱鍏ユ墽琛岀偣锛岃捣濮嬭绠椾綅缃細{} 缁熻绾拱鎵嬫暟锛歿} 鐩爣绾拱鎵嬫暟锛歿}", code, compute_start_index, buy_nums,
-                                 threshold_num)
+        cls.debug(code, "灏氭湭鑾峰彇鍒颁拱鍏ユ墽琛岀偣锛岃捣濮嬭绠椾綅缃細{} 缁熻绾拱鎵嬫暟锛歿} 鐩爣绾拱鎵嬫暟锛歿}", compute_start_index, buy_nums,
+                  threshold_num)
         return None, buy_nums
 
-    # 缁熻涔板叆鍑�涔伴噺锛屼笉璁$畻鍦ㄤ拱鍏ヤ俊鍙蜂箣鍓嶇殑涔版挙鍗�
+    # 杩囨椂 缁熻涔板叆鍑�涔伴噺锛屼笉璁$畻鍦ㄤ拱鍏ヤ俊鍙蜂箣鍓嶇殑涔版挙鍗�
     @classmethod
     def __sum_buy_num_for_order_2(cls, code, compute_start_index, origin_num, threshold_money, buy_single_index):
         total_datas = local_today_datas[code]
@@ -866,6 +1023,98 @@
                       threshold_num)
         return None, buy_nums + property_buy_num
 
+    # 缁熻涔板叆鍑�涔伴噺锛屼笉璁$畻鍦ㄤ拱鍏ヤ俊鍙蜂箣鍓嶇殑涔版挙鍗�
+    @classmethod
+    def __sum_buy_num_for_order_3(cls, code, compute_start_index, compute_end_index, origin_num, threshold_money,
+                                  buy_single_index,
+                                  capture_time):
+        total_datas = local_today_datas[code]
+        buy_nums = origin_num
+        limit_up_price = gpcode_manager.get_limit_up_price(code)
+        if limit_up_price is None:
+            raise Exception("娑ㄥ仠浠锋棤娉曡幏鍙�")
+        threshold_num = threshold_money / (limit_up_price * 100)
+        buy_single_time_seconds = L2DataUtil.get_time_as_second(total_datas[buy_single_index]["val"]["time"])
+        for i in range(compute_start_index, compute_end_index + 1):
+            data = total_datas[i]
+            _val = total_datas[i]["val"]
+            if L2DataUtil.get_time_as_second(_val["time"]) - buy_single_time_seconds > 1:
+                TradePointManager.delete_buy_point(code)
+                if i == compute_end_index:
+                    # 鏁版嵁澶勭悊瀹屾瘯
+                    return None, buy_nums, None
+                else:
+                    # 璁$畻涔板叆淇″彿锛屼笉鑳藉悓涓�鏃堕棿寮�濮嬭绠�
+                    for ii in range(buy_single_index + 1, compute_end_index + 1):
+                        if total_datas[buy_single_index]["val"]["time"] != total_datas[ii]["val"]["time"]:
+                            return None, buy_nums, ii
+
+            # 娑ㄥ仠涔�
+            if L2DataUtil.is_limit_up_price_buy(_val):
+                # 娑ㄥ仠涔�
+                buy_nums += int(_val["num"]) * int(total_datas[i]["re"])
+                if buy_nums >= threshold_num:
+                    logger_l2_trade_buy.info("{}鑾峰彇鍒颁拱鍏ユ墽琛岀偣锛歿} 缁熻绾拱鎵嬫暟锛歿} 鐩爣绾拱鎵嬫暟锛歿}", code, i, buy_nums, threshold_num)
+            elif L2DataUtil.is_limit_up_price_buy_cancel(_val):
+                # 娑ㄥ仠涔版挙
+                # 鍒ゆ柇涔板叆浣嶇疆鏄惁鍦ㄤ拱鍏ヤ俊鍙蜂箣鍓�
+                buy_index, buy_data = l2_data_util.get_buy_data_with_cancel_data(total_datas[i],
+                                                                                 local_today_num_operate_map.get(code))
+                if buy_index is not None:
+                    # 鎵惧埌涔版挙鏁版嵁鐨勪拱鍏ョ偣
+                    if buy_index >= buy_single_index:
+                        buy_nums -= int(_val["num"]) * int(data["re"])
+                        cls.buy_debug(code, "{}鏁版嵁鍦ㄤ拱鍏ヤ俊鍙蜂箣鍚� 鎾や拱绾拱鎵嬫暟锛歿} 鐩爣鎵嬫暟锛歿}", i, buy_nums, threshold_num)
+                    else:
+                        cls.buy_debug(code, "{}鏁版嵁鍦ㄤ拱鍏ヤ俊鍙蜂箣鍓嶏紝涔板叆浣嶏細{}", i, buy_index)
+                        if total_datas[buy_single_index]["val"]["time"] == buy_data["val"]["time"]:
+                            # 鍚屼竴绉�,褰撲綔涔板叆淇″彿涔嬪悗澶勭悊
+                            buy_nums -= int(_val["num"]) * int(data["re"])
+                            cls.buy_debug(code, "{}鏁版嵁涔板叆浣嶄笌棰勪及涔板叆浣嶅湪鍚屼竴绉�", i)
+                else:
+                    # 鏈壘鍒颁拱鎾ゆ暟鎹殑涔板叆鐐�
+                    cls.buy_debug(code, "鏈壘鍒颁拱鎾ゆ暟鎹殑涔板叆鐐�: 浣嶇疆-{} 鏁版嵁-{}", i, data)
+                    buy_nums -= int(_val["num"]) * int(total_datas[i]["re"])
+            cls.buy_debug(code, "浣嶇疆-{}锛屾�绘墜鏁帮細{}锛岀洰鏍囨墜鏁帮細{}", i,
+                          buy_nums, threshold_num)
+            # 鏈夋挙鍗曚俊鍙凤紝涓斿皬浜庨槇鍊�
+            if buy_nums >= threshold_num:
+                return i, buy_nums, None
+
+        cls.buy_debug(code, "灏氭湭鑾峰彇鍒颁拱鍏ユ墽琛岀偣锛岃捣濮嬭绠椾綅缃細{} 缁熻绾拱鎵嬫暟锛歿} 鐩爣绾拱鎵嬫暟锛歿}", compute_start_index,
+                      buy_nums,
+                      threshold_num)
+        return None, buy_nums, None
+
+    # 璁$畻涔板叆淇″彿涔嬪墠鐨勪笖鍜屼拱鍏ヤ俊鍙锋暟鎹湪鍚屼竴鏃堕棿鐨勬暟閲�
+    @classmethod
+    def __count_l2_data_before_for_cancel(cls, code, buy_single_index):
+        total_data = local_today_datas[code]
+        single_time = total_data[buy_single_index]["val"]["time"]
+        buy_count = 0
+        cancel_count = 0
+        for i in range(buy_single_index, -1, -1):
+            if single_time == total_data[i]["val"]["time"]:
+                if L2DataUtil.is_limit_up_price_buy(total_data[i]["val"]):
+                    buy_count += int(total_data[i]["re"])
+                elif L2DataUtil.is_limit_up_price_buy(total_data[i]["val"]):
+                    cancel_count += int(total_data[i]["re"])
+            else:
+                break
+        return buy_count, cancel_count
+
+    @classmethod
+    def __count_l2_data_for_cancel(cls, code, start_index, end_index):
+        total_data = local_today_datas[code]
+        buy_count = 0
+        cancel_count = 0
+        for i in range(start_index, end_index + 1):
+            if L2DataUtil.is_limit_up_price_buy(total_data[i]["val"]):
+                buy_count += int(total_data[i]["re"])
+            elif L2DataUtil.is_limit_up_price_buy_cancel(total_data[i]["val"]):
+                cancel_count += int(total_data[i]["re"])
+        return buy_count, cancel_count
+
     # 鍚屼竴鏃堕棿涔板叆鐨勬鐜囪绠�
     @classmethod
     def __get_same_time_property(cls, code):
@@ -877,7 +1126,7 @@
                 return 1 - l2_trade_factor.L2TradeFactorUtil.get_industry_rate(hot_num)
         return 0.5
 
-    # 缁熻涔版挙鍑�涔伴噺
+    # 杩囨椂 缁熻涔版挙鍑�涔伴噺
     @classmethod
     def __sum_buy_num_for_cancel_order(cls, code, start_index, origin_num, threshold_money, cancel_single=True):
         buy_nums = origin_num
@@ -934,17 +1183,542 @@
         cls.cancel_debug(code, "澶勭悊璧峰浣嶇疆锛歿} 鏈�缁堢函涔伴锛歿}", start_index, buy_num_news)
         return None, buy_num_news, sure_type
 
+        # 缁熻涔版挙鍑�涔伴噺
+
+    @classmethod
+    def __count_num_for_cancel_order(cls, code, start_index, origin_buy_num, origin_cancel_num, min_rate,
+                                     betch_cancel_single=True):
+        buy_nums = origin_buy_num
+        buy_cancel_num = origin_cancel_num
+        total_datas = local_today_datas[code]
+        limit_up_price = gpcode_manager.get_limit_up_price(code)
+        if limit_up_price is None:
+            raise Exception("娑ㄥ仠浠锋棤娉曡幏鍙�")
+        # 鑾峰彇棰勪及鎸備拱浣� sure_type:0 铏氭嫙鎸備拱 1 瀹為檯鎸備拱
+        for i in range(start_index, len(total_datas)):
+            data = total_datas[i]
+            _val = data["val"]
+            if L2DataUtil.is_limit_up_price_buy(_val):
+                # 娑ㄥ仠涔�
+                buy_nums += int(data["re"])
+            elif L2DataUtil.is_limit_up_price_buy_cancel(_val):
+                buy_cancel_num += int(data["re"])
+            # 鏈夋挙鍗曚俊鍙凤紝涓斿皬浜庨槇鍊�
+            if (buy_nums - buy_cancel_num) / buy_cancel_num <= min_rate and betch_cancel_single:
+                return i, buy_nums, buy_cancel_num
+        return None, buy_nums, buy_cancel_num
+
     @classmethod
     def test(cls):
-        code = "002336"
+        code = "000593"
+        load_l2_data(code, True)
+
+        if False:
+            state = trade_manager.get_trade_state(code)
+            cls.random_key[code] = random.randint(0, 100000)
+            capture_timestamp = 1999988888
+            try:
+                if state == trade_manager.TRADE_STATE_BUY_DELEGATED or state == trade_manager.TRADE_STATE_BUY_PLACE_ORDER:
+                    # 宸叉寕鍗�
+                    cls.__process_order(code, 201, 237, capture_timestamp)
+                else:
+                    # 鏈寕鍗�
+                    cls.__process_not_order(code, 201, 237, capture_timestamp)
+            except Exception as e:
+                logging.exception(e)
+            return
+
+        _start = t.time()
+        # 鎸塻鎵归噺鍖栨暟鎹�
+        total_datas = local_today_datas[code]
+        start_time = total_datas[0]["val"]["time"]
+        start_index = 0
+        for i in range(0, len(total_datas)):
+            if total_datas[i]["val"]["time"] != start_time:
+                cls.random_key[code] = random.randint(0, 100000)
+                # 澶勭悊鏁版嵁
+                start = start_index
+                # if start != 201:
+                #     continue
+                end = i - 1
+                print("澶勭悊杩涘害锛歿},{}".format(start, end))
+                capture_timestamp = 1999999999
+                state = trade_manager.get_trade_state(code)
+                try:
+                    if state == trade_manager.TRADE_STATE_BUY_DELEGATED or state == trade_manager.TRADE_STATE_BUY_PLACE_ORDER:
+                        # 宸叉寕鍗�
+                        cls.__process_order(code, start, end, capture_timestamp)
+                    else:
+                        # 鏈寕鍗�
+                        cls.__process_not_order(code, start, end, capture_timestamp)
+                except Exception as e:
+                    logging.exception(e)
+                # t.sleep(1)
+                start_index = i
+                start_time = total_datas[i]["val"]["time"]
+
+        print("鏃堕棿鑺辫垂:", round((t.time() - _start) * 1000))
+
+    @classmethod
+    def test1(cls):
+        code = "000593"
+        load_l2_data(code, True)
+        print( cls.__compute_order_begin_pos(code,232,3,239))
+
+    @classmethod
+    def test2(cls):
+        code = "000677"
+        load_l2_data(code, True)
         cls.random_key[code] = random.randint(0, 100000)
-        load_l2_data(code)
-        try:
-            # cls.__sum_buy_num_for_cancel_order(code, 112, 100000, 10000000)
-            has_single, _index = cls.__compute_order_begin_pos(code, max(9, 0), 3)
-            print(has_single, _index)
-        except Exception as e:
-            logging.exception(e)
+        L2BetchCancelBigNumProcessor.process_new(code, 57, 150)
+
+
+# 杩炵画娑ㄥ仠涔板崟鏁版渶澶у�肩鐞嗗櫒
+class L2ContinueLimitUpCountManager:
+    @classmethod
+    def del_data(cls, code):
+        cls.__del_last_record(code)
+        cls.__del_max(code)
+
+    # 鑾峰彇鏈�澶у��
+    @classmethod
+    def __get_max(cls, code):
+        key = "max_same_time_buy_count-{}".format(code)
+        redis = _redisManager.getRedis()
+        val = redis.get(key)
+        if val is not None:
+            return int(val)
+        else:
+            return None
+
+    # 淇濆瓨鏈�澶у��
+    @classmethod
+    def __save_max(cls, code, max_num):
+        key = "max_same_time_buy_count-{}".format(code)
+        redis = _redisManager.getRedis()
+        redis.setex(key, tool.get_expire(), max_num)
+
+    @classmethod
+    def __del_max(cls, code):
+        key = "max_same_time_buy_count-{}".format(code)
+        redis = _redisManager.getRedis()
+        redis.delete(key)
+
+    # 淇濆瓨涓婁竴鏉℃暟鎹渶澶у��
+    @classmethod
+    def __save_last_record(cls, code, _time, count, index):
+        key = "same_time_buy_last_count-{}".format(code)
+        redis = _redisManager.getRedis()
+        redis.setex(key, tool.get_expire(), json.dumps((_time, count, index)))
+
+    @classmethod
+    def __del_last_record(cls, code):
+        key = "same_time_buy_last_count-{}".format(code)
+        redis = _redisManager.getRedis()
+        redis.delete(key)
+
+    @classmethod
+    def __get_last_record(cls, code):
+        key = "same_time_buy_last_count-{}".format(code)
+        redis = _redisManager.getRedis()
+        val = redis.get(key)
+        if val is None:
+            return None, None, None
+        else:
+            val = json.loads(val)
+            return val[0], val[1], val[2]
+
+    @classmethod
+    def process(cls, code, start_index, end_index):
+        last_time, last_count, last_index = cls.__get_last_record(code)
+        total_datas = local_today_datas[code]
+        time_count_dict = {}
+        for index in range(start_index, end_index + 1):
+            if last_index is not None and last_index >= index:
+                continue
+
+            if L2DataUtil.is_limit_up_price_buy(total_datas[index]["val"]):
+                if last_count is None:
+                    last_count = 0
+                    last_time = total_datas[index]["val"]["time"]
+                    last_index = index
+                if last_time == total_datas[index]["val"]["time"]:
+                    last_count += total_datas[index]["re"]
+                    last_index = index
+                else:
+                    if last_count is not None and last_count > 0:
+                        time_count_dict[last_time] = last_count
+                    last_count = total_datas[index]["re"]
+                    last_time = total_datas[index]["val"]["time"]
+                    last_index = index
+            else:
+                if last_count is not None and last_count > 0:
+                    time_count_dict[last_time] = last_count
+                last_count = 0
+                last_time = None
+                last_index = None
+        if last_count is not None and last_count > 0:
+            time_count_dict[last_time] = last_count
+            # 淇濆瓨latest
+            cls.__save_last_record(code, last_time, last_count, last_index)
+        else:
+            # 绉婚櫎
+            cls.__del_last_record(code)
+
+        # 鏌ユ壘杩欐壒鏁版嵁涓殑鏈�澶ф暟閲�
+        max_time = None
+        max_num = None
+        for key in time_count_dict:
+            if max_time is None:
+                max_time = key
+                max_num = time_count_dict[key]
+            if time_count_dict[key] > max_num:
+                max_num = time_count_dict[key]
+                max_time = key
+        if max_num is not None:
+            old_max = cls.__get_max(code)
+            if old_max is None or max_num > old_max:
+                cls.__save_max(code, max_num)
+
+    @classmethod
+    def get_continue_count(cls, code):
+        count = cls.__get_max(code)
+        if count is None:
+            count = 0
+        count = count // 3
+        if count < 15:
+            count = 15
+        return count
+
+
+# 澶у崟澶勭悊鍣�
+class L2BigNumProcessor:
+    # 鏄惁闇�瑕佹牴鎹ぇ鍗曟挙鍗曪紝杩斿洖鏄惁闇�瑕佹挙鍗曚笌鎾ゅ崟淇″彿鐨勬暟鎹�
+    @classmethod
+    def __need_cancel_with_max_num(cls, code, max_num_info):
+        if max_num_info is None:
+            return False, None
+        # 濡傛灉鏄拱鍏ュ崟锛岄渶瑕佺湅浠栧墠闈㈠悓涓�绉掓槸鍚︽湁鎾ゅ崟
+        if int(max_num_info["val"]["operateType"]) == 0:
+            # 鍙湁涔版挙淇″彿鍦ㄤ拱鍏ヤ俊鍙蜂箣鍓嶇殑鍚屼竴绉掔殑鍗曟墠浼氭挙鍗曟儏鍐�
+            _map = local_today_num_operate_map.get(code)
+            if _map is not None:
+                cancel_datas = _map.get(
+                    "{}-{}-{}".format(max_num_info["val"]["num"], "1", max_num_info["val"]["price"]))
+
+                if cancel_datas is not None:
+                    for cancel_data in cancel_datas:
+                        if cancel_data["index"] > max_num_info["index"]:
+                            buy_index, buy_data = l2_data_util.get_buy_data_with_cancel_data(cancel_data,
+                                                                                             local_today_num_operate_map[
+                                                                                                 code])
+                            if buy_index is None:
+                                continue
+                            if buy_data["val"]["time"] != max_num_info["val"]["time"]:
+                                continue
+                            min_space, max_space = l2_data_util.compute_time_space_as_second(
+                                cancel_data["val"]["cancelTime"],
+                                cancel_data["val"][
+                                    "cancelTimeUnit"])
+                            if min_space < 60:
+                                L2TradeDataProcessor.cancel_debug(code, "鎵惧埌澶у崟鎾ゅ崟锛屼絾鎾ゅ崟闂撮殧鏃堕棿灏忎簬60s,鎾ゅ崟鏁版嵁-{}",
+                                                                  json.dumps(cancel_data))
+                                return True, cancel_data
+                            else:
+                                # 濡傛灉闂撮殧鏃堕棿澶т簬绛変簬60s锛岃繖鍒ゆ柇灏忕兢鎾や簨浠�
+                                L2TradeDataProcessor.cancel_debug(code, "鎵惧埌澶у崟鎾ゅ崟锛屼絾鎾ゅ崟闂撮殧鏃堕棿澶т簬60s,鎾ゅ崟鏁版嵁-{}",
+                                                                  json.dumps(cancel_data))
+                                return False, cancel_data
+            return False, None
+        else:
+            return True, None
+
+    # 璁$畻鏁伴噺鏈�澶х殑娑ㄥ仠涔�/娑ㄥ仠鎾�
+    @classmethod
+    def __compute_max_num(cls, code, start_index, end_index, max_num_info, buy_exec_time):
+        new_max_info = max_num_info
+        max_num = 0
+        if max_num_info is not None:
+            max_num = int(max_num_info["val"]["num"])
+        # 璁$畻澶у崟
+        total_data = local_today_datas[code]
+        for i in range(start_index, end_index + 1):
+            data = total_data[i]
+            val = data["val"]
+            if not L2DataUtil.is_limit_up_price_buy(val) and not L2DataUtil.is_limit_up_price_buy_cancel(
+                    val):
+                continue
+
+            # 涓嬪崟鏃堕棿涓庝拱鍏ユ墽琛屾椂闂翠箣宸ぇ浜�60s鐨勪笉鍋氬鐞�
+            if l2_data_util.get_time_as_seconds(val["time"]) - l2_data_util.get_time_as_seconds(buy_exec_time) > 1:
+                continue
+
+            if L2DataUtil.is_limit_up_price_buy(val):
+                pass
+            elif L2DataUtil.is_limit_up_price_buy_cancel(val):
+                min_space, max_space = l2_data_util.compute_time_space_as_second(val["cancelTime"],
+                                                                                 val["cancelTimeUnit"])
+                # 鍙兘澶勭悊1s鍐呯殑鎾ゅ崟
+                if min_space > 1:
+                    continue
+
+                # buy_index, buy_data = l2_data_util.get_buy_data_with_cancel_data(data,
+                #                                                                  local_today_num_operate_map.get(code))
+                # if buy_index is None:
+                #     continue
+                # if l2_data_util.get_time_as_seconds(buy_data["val"]["time"]) - l2_data_util.get_time_as_seconds(
+                #         buy_exec_time) > 1:
+                #     continue
+
+            num = int(total_data[i]["val"]["num"])
+            if num > max_num:
+                max_num = num
+                new_max_info = data
+        return new_max_info
+
+    @classmethod
+    def __save_big_num_pos(cls, code, index):
+        redis = _redisManager.getRedis()
+        redis.setex("big_num_pos-{}".format(code), tool.get_expire(), index)
+
+    @classmethod
+    def __get_big_num_pos(cls, code):
+        redis = _redisManager.getRedis()
+        index = redis.get("big_num_pos-{}".format(code))
+        if index is not None:
+            return int(index)
+        return index
+
+    @classmethod
+    def __del_big_num_pos(cls, code):
+        redis = _redisManager.getRedis()
+        redis.delete("big_num_pos-{}".format(code))
+
+    @classmethod
+    def __cancel_buy(cls, code, index):
+        L2TradeDataProcessor.debug(code, "鎾や拱锛岃Е鍙戜綅缃�-{}锛岃Е鍙戞潯浠讹細澶у崟锛屾暟鎹細{}", index, local_today_datas[code][index])
+        L2TradeDataProcessor.cancel_buy(code)
+        cls.__del_big_num_pos(code)
+
+    # 澶勭悊鏁版嵁涓殑澶у崟,杩斿洖鏄惁宸茬粡鎾ゅ崟鍜屾挙鍗曟暟鎹殑鏃堕棿
+    @classmethod
+    def process_cancel_with_big_num(cls, code, start_index, end_index):
+        total_data = local_today_datas[code]
+        # 濡傛灉鏃犱笅鍗曚俊鍙峰氨鏃犻渶澶勭悊
+        buy_single_index, buy_exec_index, compute_index, nums = TradePointManager.get_buy_compute_start_data(code)
+        if buy_single_index is None or buy_exec_index is None or buy_exec_index < 0:
+            return False, None
+        # 鍒ゆ柇鏄惁鏈夊ぇ鍗曡褰�
+        index = cls.__get_big_num_pos(code)
+        # 鏃犲ぇ鍗曡褰�
+        if index is None:
+            # 璁$畻澶у崟
+            new_max_info = cls.__compute_max_num(code, start_index, end_index, None,
+                                                 total_data[buy_exec_index]["val"]["time"])
+            if new_max_info is None:
+                return False, None
+            L2TradeDataProcessor.debug(code, "鑾峰彇鍒板ぇ鍗曚綅缃俊鎭細{}", json.dumps(new_max_info))
+            index = new_max_info["index"]
+            # 澶у崟鏄惁鏈夋挙鍗曚俊鍙�
+            need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, new_max_info)
+            if need_cancel:
+                # 闇�瑕佹挙鍗�
+                # 鎾ゅ崟
+                L2TradeDataProcessor.cancel_debug(code, "鏂版壘鍒板ぇ鍗�-{}锛岄渶瑕佹挙涔�", new_max_info["index"])
+                cls.__cancel_buy(code, index)
+                return True, cancel_data,
+
+            else:
+                # 鏃犻渶鎾ゅ崟
+                # 淇濆瓨澶у崟璁板綍
+                cls.__save_big_num_pos(code, index)
+                return False, None
+        else:
+            # 鏈夊ぇ鍗曡褰�
+            need_cancel = False
+            cancel_index = -1
+            need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, total_data[index])
+            # 闇�瑕佹挙鍗�
+            if need_cancel:
+                # 鎾ゅ崟
+                cls.__cancel_buy(code, cancel_index)
+                return True, cancel_data
+            # 鏃犻渶鎾ゅ崟
+            else:
+                # 璁$畻鏂扮殑澶у崟
+                max_num_data = cls.__compute_max_num(code, start_index, end_index, total_data[index],
+                                                     total_data[buy_exec_index]["val"]["time"])
+                if index == int(max_num_data["index"]):
+                    return False, cancel_data
+                L2TradeDataProcessor.debug(code, "鎵惧埌澶у崟浣嶇疆淇℃伅锛歿}", json.dumps(max_num_data))
+
+                # 澶у崟鏄惁鏈夋挙鍗曚俊鍙�
+                need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, max_num_data)
+                if need_cancel:
+                    # 闇�瑕佹挙鍗�
+                    # 鎾ゅ崟
+                    cls.__cancel_buy(code, max_num_data["index"])
+                    L2TradeDataProcessor.cancel_debug(code, "璺熻釜鍒板ぇ鍗曟棤鎾や拱淇″彿-{}锛屾柊璺熻釜鐨勫ぇ鍗曢渶瑕佹挙涔�-{}", index, max_num_data["index"])
+                    return True, cancel_data
+                else:
+                    # 鏃犻渶鎾ゅ崟
+                    # 淇濆瓨澶у崟璁板綍
+                    cls.__save_big_num_pos(code, max_num_data["index"])
+                    return False, cancel_data
+
+
+# 澶х兢鎾ゅぇ鍗曡窡韪�
+class L2BetchCancelBigNumProcessor:
+    @classmethod
+    def __get_recod(cls, code):
+        redis = _redisManager.getRedis()
+        _val = redis.get("betch_cancel_big_num-{}".format(code))
+        if _val is None:
+            return None, None
+        else:
+            datas = json.loads(_val)
+            return datas[0], datas[1]
+
+    @classmethod
+    def del_recod(cls, code):
+        redis = _redisManager.getRedis()
+        key = "betch_cancel_big_num-{}".format(code)
+        redis.delete(key)
+
+    @classmethod
+    def __save_recod(cls, code, max_big_num_info, big_nums_info):
+        redis = _redisManager.getRedis()
+        key = "betch_cancel_big_num-{}".format(code)
+        redis.setex(key, tool.get_expire(), json.dumps((max_big_num_info, big_nums_info)))
+
+    # 鏆傛椂寮冪敤
+    @classmethod
+    def need_cancel(cls, code, start_index, end_index):
+        # 鏄惁闇�瑕佹挙鍗�
+        max_big_num_info, big_nums_info = cls.__get_recod(code)
+        if big_nums_info is None:
+            # 鏃犲ぇ鍗曚俊鎭�
+            return True
+        nums_set = set()
+        index_set = set()
+
+        for d in big_nums_info:
+            nums_set.add(d[0])
+            index_set.add(d[1])
+
+        total_datas = local_today_datas[code]
+
+        count = 0
+        latest_buy_index = end_index
+        for index in range(start_index, end_index + 1):
+            if not nums_set.__contains__(total_datas[index]["val"]["num"]):
+                continue
+            buy_index, buy_data = l2_data_util.get_buy_data_with_cancel_data(total_datas[index],
+                                                                             local_today_num_operate_map[code])
+            if buy_index is None:
+                continue
+            if index_set.__contains__(buy_index):
+                count += buy_data["re"]
+                latest_buy_index = buy_index
+
+        # 鑾峰彇澶у崟鏁伴噺
+        total_count = 0
+        for i in index_set:
+            if i <= latest_buy_index:
+                total_count += total_datas[i]["re"]
+        # 澶у崟灏忎簬5绗旀棤鑴戞挙
+        if total_count <= 5:
+            return True
+
+        # 澶у崟鎾ゅ崟绗旀暟澶т簬鎬诲ぇ鍗曠瑪鏁扮殑1/5灏辨挙鍗�
+        if count / total_count >= 0.2:
+            return True
+        else:
+            return False
+
+        pass
+
+    # def need_cancel(cls, code, start_index, end_index):
+    #     total_datas = local_today_datas[code]
+    #     for index in range(start_index,end_index+1):
+    #         price = total_datas[index]["val"]["price"]
+    #         num = total_datas[index]["val"]["num"]
+    #         if total_datas[index]
+
+    # 杩囨椂
+    @classmethod
+    def process(cls, code, start_index, end_index):
+        # 澶勭悊澶у崟
+        # 鑾峰彇澶у崟鍒楄〃,澶у崟鏍煎紡涓�:((num,index,re),[(num,index,re),(num,index,re)])
+        total_datas = local_today_datas[code]
+        max_big_num_info, big_nums_info = cls.__get_recod(code)
+        # 瀵绘壘鏈�澶у��
+        for index in range(start_index, end_index + 1):
+            # 鍙鐞嗘定鍋滀拱涓庢定鍋滀拱鎾�
+            if not L2DataUtil.is_limit_up_price_buy(
+                    total_datas[index]["val"]):
+                continue
+            if max_big_num_info is None:
+                max_big_num_info = (
+                    int(total_datas[start_index]["val"]["num"]), total_datas[start_index]["index"])
+
+            if int(total_datas[index]["val"]["num"]) > max_big_num_info[0]:
+                max_big_num_info = (
+                    int(total_datas[index]["val"]["num"]), total_datas[index]["index"])
+        # 灏嗗ぇ浜庢渶澶у��90%鐨勬暟鎹姞鍏�
+        if max_big_num_info is not None:
+            min_num = round(max_big_num_info[0] * 0.9)
+
+            for index in range(start_index, end_index + 1):
+                # 鍙粺璁℃定鍋滀拱
+                if not L2DataUtil.is_limit_up_price_buy(
+                        total_datas[index]["val"]):
+                    continue
+
+                if int(total_datas[index]["val"]["num"]) >= min_num:
+                    if big_nums_info is None:
+                        big_nums_info = []
+                    big_nums_info.append((int(total_datas[index]["val"]["num"]), total_datas[index]["index"]))
+            # 绉婚櫎灏忎簬90%鐨勬暟鎹�
+            big_nums_info_new = []
+            index_set = set()
+            for d in big_nums_info:
+                if d[0] >= min_num:
+                    if not index_set.__contains__(d[1]):
+                        index_set.add(d[1])
+                        big_nums_info_new.append(d)
+            cls.__save_recod(code, max_big_num_info, big_nums_info_new)
+
+    # 鏈�鏂版柟娉�
+    @classmethod
+    def process_new(cls, code, start_index, end_index):
+        # 澶勭悊澶у崟
+        # 鑾峰彇澶у崟鍒楄〃,澶у崟鏍煎紡涓�:((num,index,re),[(num,index,re),(num,index,re)])
+        total_datas = local_today_datas[code]
+        max_big_num_info, big_nums_info = cls.__get_recod(code)
+        # 澶т簬绛変簬8000鎵嬫垨鑰呴噾棰�>=300涓囧氨鏄ぇ鍗�
+
+        for index in range(start_index, end_index + 1):
+            # 鍙粺璁℃定鍋滀拱
+            if not L2DataUtil.is_limit_up_price_buy(
+                    total_datas[index]["val"]):
+                continue
+            # 澶т簬绛変簬8000鎵嬫垨鑰呴噾棰� >= 300
+            # 涓囧氨鏄ぇ鍗�
+            if int(total_datas[index]["val"]["num"]) >= 8000 or int(total_datas[index]["val"]["num"]) * float(
+                    total_datas[index]["val"]["price"]) >= 30000:
+                if big_nums_info is None:
+                    big_nums_info = []
+                big_nums_info.append((int(total_datas[index]["val"]["num"]), total_datas[index]["index"]))
+        # 绉婚櫎灏忎簬90%鐨勬暟鎹�
+        big_nums_info_new = []
+        index_set = set()
+        if big_nums_info is not None:
+            for d in big_nums_info:
+                if not index_set.__contains__(d[1]):
+                    index_set.add(d[1])
+                    big_nums_info_new.append(d)
+            cls.__save_recod(code, max_big_num_info, big_nums_info_new)
 
 
 def __get_time_second(time_str):
@@ -1096,7 +1870,7 @@
                         index_2 = j
                         break
             if index_1 - index_0 == 1 and index_2 - index_1 == 1:
-                logger_l2_trade.info("杩炵画3涓定鍋滀拱鎾� {},{},{}".format(code, i, json.dumps(datas[i])))
+                # logger_l2_trade.info("杩炵画3涓定鍋滀拱鎾� {},{},{}".format(code, i, json.dumps(datas[i])))
                 return i
     return None
 
@@ -1192,4 +1966,4 @@
 
 
 if __name__ == "__main__":
-    L2TradeDataProcessor.test()
+    L2TradeDataProcessor.test1()

--
Gitblit v1.8.0