From be73e2b78857adaf006063275726b69c4c60f0d7 Mon Sep 17 00:00:00 2001 From: Administrator <admin@example.com> Date: 星期三, 12 十月 2022 11:54:25 +0800 Subject: [PATCH] 买撤策略修改;加入报警功能 --- l2_data_manager.py | 134 +++++++++++++++++++++++++++++++++----------- 1 files changed, 101 insertions(+), 33 deletions(-) diff --git a/l2_data_manager.py b/l2_data_manager.py index 4fc09c3..c19499f 100644 --- a/l2_data_manager.py +++ b/l2_data_manager.py @@ -17,6 +17,7 @@ import l2_trade_factor import redis_manager +import ths_industry_util import tool import trade_manager from log import logger_l2_trade, logger_l2_trade_cancel, logger_l2_trade_buy, logger_l2_process @@ -283,10 +284,10 @@ def get_add_data(cls, code, datas, _start_index): if datas is not None and len(datas) < 1: return [] - last_key = "" - __latest_datas = local_latest_datas.get(code) - if __latest_datas is not None and len(__latest_datas) > 0: - last_key = __latest_datas[-1]["key"] + last_data = None + latest_datas_ = local_latest_datas.get(code) + if latest_datas_ is not None and len(latest_datas_) > 0: + last_data = latest_datas_[-1] count = 0 start_index = -1 @@ -294,13 +295,19 @@ # 璁剧疆add_data鐨勫簭鍙� for n in reversed(datas): count += 1 - if n["key"] == last_key: + if n["key"] == (last_data["key"] if last_data is not None else ""): start_index = len(datas) - count break _add_datas = [] - if len(last_key) > 0: - if start_index < 0 or start_index + 1 >= len(datas): + if last_data is not None: + if start_index < 0: + if L2DataUtil.get_time_as_second(datas[0]["val"]["time"]) >= L2DataUtil.get_time_as_second( + last_data["val"]["time"]): + _add_datas = datas + else: + _add_datas = [] + elif start_index + 1 >= len(datas): _add_datas = [] else: _add_datas = datas[start_index + 1:] @@ -356,6 +363,9 @@ else: limitPrice = 0 item["limitPrice"] = "{}".format(limitPrice) + # 涓嶉渶瑕侀潪娑ㄥ仠鏁版嵁/闈炶穼鍋滄暟鎹� + if int(item["limitPrice"]) == 0: + continue operateType = item["operateType"] cancelTime = item["cancelTime"] cancelTimeUnit = item["cancelTimeUnit"] @@ -471,9 +481,6 @@ # 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 鏆傛椂鍏抽棴澶勭悊 @@ -481,13 +488,13 @@ # 鍒ゆ柇鏄惁宸茬粡鎸傚崟 state = trade_manager.get_trade_state(code) start_index = len(total_datas) - len(add_datas) - end_index = len(total_datas)-1 + 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, start_index,end_index, capture_timestamp) + cls.__process_order(code, start_index, end_index, capture_timestamp) else: # 鏈寕鍗� - cls.__process_not_order(code,start_index,end_index,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) # 淇濆瓨鏁版嵁 @@ -497,10 +504,12 @@ cls.unreal_buy_dict.pop(code) @classmethod - def __compute_big_money_data(cls, code, add_datas): + def __compute_big_money_data(cls, code, start_index, end_index): # 璁$畻澶у崟 + total_datas = local_today_datas[code] num = 0 - for data in add_datas: + for index in range(start_index, end_index + 1): + data = total_datas[index] if l2_trade_factor.L2TradeFactorSourceDataUtil.is_big_money(data): if int(data["val"]["operateType"]) == 0: num += data["re"] @@ -693,6 +702,14 @@ @classmethod def __buy(cls, code, capture_timestamp, last_data, last_data_index): + can, reason = cls.__can_buy(code) + # 涓嶈兘璐拱 + if not can: + cls.debug(code, "涓嶅彲浠ヤ笅鍗曪紝鍘熷洜锛歿}", reason) + return + else: + cls.debug(code, "鍙互涓嬪崟锛屽師鍥狅細{}", reason) + # 鍒犻櫎铏氭嫙涓嬪崟 if code in cls.unreal_buy_dict: cls.unreal_buy_dict.pop(code) @@ -705,6 +722,36 @@ except Exception as e: cls.debug(code, "鎵ц涔板叆寮傚父:{}", str(e)) pass + + # 鏄惁鍙互涔� + @classmethod + def __can_buy(cls, code): + limit_up_time = limit_up_time_manager.get_limit_up_time(code) + if limit_up_time is not None and L2DataUtil.get_time_as_second(limit_up_time) >= L2DataUtil.get_time_as_second( + "14:30:00"): + return False, "14:30鍚庢定鍋滅殑涓嶈兘涔帮紝娑ㄥ仠鏃堕棿涓簕}".format(limit_up_time) + + # 鍚屼竴鏉垮潡涓�佷簩鍚庨潰鐨勪笉鑳戒拱 + industry, codes = ths_industry_util.get_same_industry_codes(code, gpcode_manager.get_gp_list()) + if industry is None: + return True, "娌℃湁鑾峰彇鍒拌涓�" + codes_index = limit_up_time_manager.sort_code_by_limit_time(codes) + if codes_index is not None and codes_index.get(code) is not None and codes_index.get(code) > 1: + return False, "鍚屼竴鏉垮潡涓�佷笁,鑰佸洓,...涓嶈兘涔�" + + # 13:00鍚庢定鍋滐紝鏈澘鍧椾腑娑ㄥ仠绁ㄦ暟<29涓嶈兘涔� + limit_up_time = limit_up_time_manager.get_limit_up_time(code) + if limit_up_time is not None: + if int(limit_up_time.replace(":", "")) >= 130000 and global_util.industry_hot_num.get(industry) is not None: + if global_util.industry_hot_num.get(industry) < 29: + return False, "13:00鍚庢定鍋滐紝鏈澘鍧椾腑娑ㄥ仠绁ㄦ暟<29涓嶈兘涔�" + # 鑰佷簩锛屾湰鏉垮潡涓定鍋滅エ鏁�<29 涓嶈兘涔� + if codes_index.get(code) is not None and codes_index.get(code) == 1 and global_util.industry_hot_num.get( + industry) is not None: + if global_util.industry_hot_num.get(industry) < 29: + return False, "鑰佷簩锛屾湰鏉垮潡涓定鍋滅エ鏁�<29涓嶈兘涔�" + # 鍙互涓嬪崟 + return True, None @classmethod def __cancel_buy(cls, code): @@ -731,6 +778,7 @@ cls.unreal_buy_dict.pop(code) else: cls.__cancel_buy(code) + L2BigNumProcessor.del_big_num_pos(code) @classmethod def __start_compute_buy(cls, code, compute_start_index, compute_end_index, threshold_money, capture_time, @@ -753,11 +801,14 @@ new_get_pos = True cls.debug(code, "鑾峰彇鍒颁拱鍏ヤ俊鍙疯捣濮嬬偣锛歿} 鏁版嵁锛歿}", buy_single_index, total_datas[buy_single_index]) limit_up_time_manager.save_limit_up_time(code, total_datas[buy_single_index]["val"]["time"]) - + # 閲嶇疆澶у崟璁$畻 + big_money_num_manager.reset(code) if buy_single_index is None: # 鏈幏鍙栧埌涔板叆淇″彿锛岀粓姝㈢▼搴� return None + # TODO 鍙兘瀛樺湪闂 璁$畻澶у崟鏁伴噺 + cls.__compute_big_money_data(code, max(compute_start_index, buy_single_index), compute_end_index) # 涔板叆绾拱棰濈粺璁� compute_index, buy_nums, rebegin_buy_pos = cls.__sum_buy_num_for_order_3(code, max(buy_single_index, compute_start_index), @@ -792,7 +843,7 @@ compute_index) # 璁$畻澶х兢鎾ょ殑澶у崟 L2BetchCancelBigNumProcessor.process_new(code, buy_single_index, compute_index) - + # 杩炵画娑ㄥ仠鏁拌绠� L2ContinueLimitUpCountManager.process(code, buy_single_index, compute_index) # 鏁版嵁鏄惁澶勭悊瀹屾瘯 @@ -846,7 +897,8 @@ if L2DataUtil.get_time_as_second(_val["time"]) < second_930: continue - 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 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 @@ -925,10 +977,6 @@ return start, end_index else: return None, None - - # 鏄惁鍙互涓嬪崟 - def __is_can_order(self): - pass # 铏氭嫙涓嬪崟 def __unreal_order(self): @@ -1264,14 +1312,22 @@ def test1(cls): code = "000593" load_l2_data(code, True) - print( cls.__compute_order_begin_pos(code,232,3,239)) + print(cls.__compute_order_begin_pos(code, 232, 3, 239)) @classmethod def test2(cls): - code = "000677" + code = "600082" load_l2_data(code, True) cls.random_key[code] = random.randint(0, 100000) - L2BetchCancelBigNumProcessor.process_new(code, 57, 150) + need_cancel, cancel_data = L2BigNumProcessor.process_cancel_with_big_num(code, 121, 123) + + @classmethod + def test_can_order(cls): + code = "002393" + + global_util.load_industry() + limit_up_time_manager.load_limit_up_time() + print(cls.__can_buy(code)) # 杩炵画娑ㄥ仠涔板崟鏁版渶澶у�肩鐞嗗櫒 @@ -1396,7 +1452,7 @@ class L2BigNumProcessor: # 鏄惁闇�瑕佹牴鎹ぇ鍗曟挙鍗曪紝杩斿洖鏄惁闇�瑕佹挙鍗曚笌鎾ゅ崟淇″彿鐨勬暟鎹� @classmethod - def __need_cancel_with_max_num(cls, code, max_num_info): + def __need_cancel_with_max_num(cls, code, max_num_info, start_index, end_index): if max_num_info is None: return False, None # 濡傛灉鏄拱鍏ュ崟锛岄渶瑕佺湅浠栧墠闈㈠悓涓�绉掓槸鍚︽湁鎾ゅ崟 @@ -1409,6 +1465,9 @@ if cancel_datas is not None: for cancel_data in cancel_datas: + # 鍙兘鍦ㄥ綋鍓嶈瀹氱殑鏁版嵁鑼冨洿鏌ユ壘锛屼互闃插嚭鐜伴噸澶嶆煡鎵� + if cancel_data["index"] < start_index or cancel_data["index"] > end_index: + continue 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[ @@ -1417,6 +1476,7 @@ 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"][ @@ -1491,7 +1551,7 @@ return index @classmethod - def __del_big_num_pos(cls, code): + def del_big_num_pos(cls, code): redis = _redisManager.getRedis() redis.delete("big_num_pos-{}".format(code)) @@ -1499,7 +1559,6 @@ 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 @@ -1521,12 +1580,12 @@ 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) + need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, new_max_info, start_index, end_index) if need_cancel: # 闇�瑕佹挙鍗� # 鎾ゅ崟 L2TradeDataProcessor.cancel_debug(code, "鏂版壘鍒板ぇ鍗�-{}锛岄渶瑕佹挙涔�", new_max_info["index"]) - cls.__cancel_buy(code, index) + cls.__cancel_buy(code, new_max_info["index"]) return True, cancel_data, else: @@ -1538,7 +1597,7 @@ # 鏈夊ぇ鍗曡褰� need_cancel = False cancel_index = -1 - need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, total_data[index]) + need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, total_data[index], start_index, end_index) # 闇�瑕佹挙鍗� if need_cancel: # 鎾ゅ崟 @@ -1554,7 +1613,8 @@ L2TradeDataProcessor.debug(code, "鎵惧埌澶у崟浣嶇疆淇℃伅锛歿}", json.dumps(max_num_data)) # 澶у崟鏄惁鏈夋挙鍗曚俊鍙� - need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, max_num_data) + need_cancel, cancel_data = cls.__need_cancel_with_max_num(code, max_num_data, max_num_data["index"], + end_index) if need_cancel: # 闇�瑕佹挙鍗� # 鎾ゅ崟 @@ -1566,6 +1626,13 @@ # 淇濆瓨澶у崟璁板綍 cls.__save_big_num_pos(code, max_num_data["index"]) return False, cancel_data + + @classmethod + def test(cls): + code = "000036" + load_l2_data(code, True) + new_max_info = cls.__compute_max_num(code, 470, 476, None, "09:32:59") + print(new_max_info) # 澶х兢鎾ゅぇ鍗曡窡韪� @@ -1627,6 +1694,7 @@ for i in index_set: if i <= latest_buy_index: total_count += total_datas[i]["re"] + L2TradeDataProcessor.debug(code, "澶х兢鎾ゅぇ鍗曟暟閲忥細{}/{}", count, total_count) # 澶у崟灏忎簬5绗旀棤鑴戞挙 if total_count <= 5: return True @@ -1967,4 +2035,4 @@ if __name__ == "__main__": - L2TradeDataProcessor.test1() + L2TradeDataProcessor.test_can_order() -- Gitblit v1.8.0