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