huaxin_client/l1_api_client.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
l2/cancel_buy_strategy.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
l2/l2_data_manager_new.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
l2/l2_transaction_data_processor.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
test/test.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
trade/current_price_process_manager.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
utils/buy_strategy_util.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
huaxin_client/l1_api_client.py
@@ -39,7 +39,6 @@ if request_id in self.__result_cache: return self.__result_cache time.sleep(0.002) print("ReqReqQryShareCalendar:", results) except Exception as e: logging.exception(e) l2/cancel_buy_strategy.py
@@ -355,6 +355,8 @@ try: if code in self.__max_buy_order_num_cache: max_num = self.__max_buy_order_num_cache[code] if max_num and tool.is_ge_code(code): max_num = max_num * 6.6 details = HuaXinSellOrderStatisticManager.get_latest_3s_continue_deal_volumes(code) threshold_num = int(max_num * 0.5 * 100) count = 0 l2/l2_data_manager_new.py
@@ -260,6 +260,9 @@ # 下次买的时间 __next_buy_time_dict = {} # 中断本批次买入数据处理 __break_current_batch_data_for_buy_dict = {} # 获取代码评分 @classmethod def get_code_scores(cls): @@ -518,6 +521,7 @@ # 处理未挂单 @classmethod def __process_not_order(cls, code, start_index, end_index, capture_time, is_first_code): cls.__break_current_batch_data_for_buy_dict[code] = False __start_time = round(t.time() * 1000) # 获取阈值 threshold_money, msg = cls.__get_threshmoney(code) @@ -728,6 +732,8 @@ l2_log.debug(code, "不可以下单,原因:{}", reason) trade_record_log_util.add_cant_place_order_log(code, reason) if need_clear_data: # 中断买入 cls.__break_current_batch_data_for_buy_dict[code] = True trade_result_manager.real_cancel_success(code, order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index, local_today_datas.get(code)) @@ -910,59 +916,67 @@ if int(limit_up_time.replace(":", "")) < int("093000"): return False, True, f"上证开一09:32之前不下单" # ------------挂单时间约束---------- order_begin_pos = cls.__get_order_begin_pos( code) if not trade_result_manager.can_place_order_for_cancel_time(code, total_data[order_begin_pos.buy_exec_index]): return False, True, f"距离上次挂单小于时间限制" # ------------板块约束------------- if not cls.__WantBuyCodesManager.is_in_cache(code): # 想买单无板块约束 block_buy_result = buy_strategy_util.is_block_can_buy(code, cls.__get_can_buy_block(code)) if not block_buy_result[0]: return block_buy_result if constant.L2_SOURCE_TYPE == constant.L2_SOURCE_TYPE_HUAXIN: # ---------------------判断是否为板上放量---------------------- trade_price = current_price_process_manager.get_trade_price(code) if trade_price is None: return False, True, f"尚未获取到当前成交价" # 判断是否为板上放量: # 1.当前成交价为涨停价 # 2.总卖额为0 # 2.距离最近的非板上成交的时间大于一个阈值 if abs(limit_up_price - float(trade_price)) < 0.001: # 获取最近的非涨停价成交时间 not_limit_up_info = current_price_process_manager.get_trade_not_limit_up_info(code) if not not_limit_up_info or tool.trade_time_sub(total_data[-1]['val']['time'], not_limit_up_info[1]) > 10: # 获取最近2s的成交 deal_list = HuaXinSellOrderStatisticManager.get_latest_2s_continue_deal_volumes(code) total_deal_volume = 0 if deal_list: total_deal_volume = sum([x[1] for x in deal_list]) total_deal_money = int(total_deal_volume * float(limit_up_price)) # 获取买1的封单额 not_limit_up_trade_time_with_ms = current_price_process_manager.get_trade_not_limit_up_time_with_ms( code) threshold_time_space = buy_condition_util.get_cancel_and_buy_space_time(code) if not not_limit_up_trade_time_with_ms or tool.trade_time_sub_with_ms( L2DataUtil.get_time_with_ms(total_data[-1]['val']), not_limit_up_trade_time_with_ms) >= threshold_time_space: # 判断成交进度到当前数据的笔数,如果少于10笔且还有未成交的大单(>=299)就可以下单 trade_index, is_default = cls.__TradeBuyQueue.get_traded_index(code) if trade_index is None: trade_index = 0 can_place_order, msg = buy_strategy_util.is_near_by_trade_index(code, trade_index) if not can_place_order: try: # 不能下单,判断小群撤是否可以下 if buy_strategy_util.is_has_small_batch_cancel(code, trade_index, order_begin_pos.buy_single_index): # 判断撤单比例是否足够 if not buy_strategy_util.is_cancel_rate_reieved(code, 0.69, trade_index, order_begin_pos.buy_single_index): return False, True, f"板上放量距离远({not_limit_up_trade_time_with_ms}),有小群撤, 整体撤单比例不足({trade_index}-{order_begin_pos.buy_single_index})" else: return False, True, f"板上放量距离远({not_limit_up_trade_time_with_ms}),没有小群撤({trade_index}-{order_begin_pos.buy_single_index})" except Exception as e: l2_log.info(code, logger_l2_error, f"板上放量({not_limit_up_trade_time_with_ms})不足异常:{str(e)}") return False, True, f"板上放量计算异常" # -------是否距离成交进度位太远-------- buy1_money = code_price_manager.Buy1PriceManager().get_latest_buy1_money(code) buy1_price = code_price_manager.Buy1PriceManager().get_buy1_price(code) if buy1_price and abs(limit_up_price - buy1_price) > 0.0001: # 买1未涨停 buy1_money = 0 if not buy1_money: buy1_money = 1 deal_rate = round(total_deal_money / buy1_money, 2) if deal_rate < 0.5: # 判断成交进度到当前数据的笔数,如果少于10笔且还有未成交的大单(>=299)就可以下单 trade_index, is_default = cls.__TradeBuyQueue.get_traded_index(code) if trade_index is None: trade_index = 0 can_place_order, msg = buy_strategy_util.is_near_by_trade_index(code, trade_index) if not can_place_order: try: # 不能下单,判断小群撤是否可以下 if buy_strategy_util.is_has_small_batch_cancel(code, trade_index, order_begin_pos.buy_single_index): # 判断撤单比例是否足够 if not buy_strategy_util.is_cancel_rate_reieved(code, 0.69, trade_index, order_begin_pos.buy_single_index): return False, True, f"板上放量不足,有小群撤, 整体撤单比例不足({trade_index}-{order_begin_pos.buy_single_index})" else: return False, True, f"板上放量不足,且没有小群撤({trade_index}-{order_begin_pos.buy_single_index})" except Exception as e: l2_log.info(code, logger_l2_error, "板上放量不足异常:{}", str(e)) return False, True, f"板上放量不足" # 上证下单需要有成交大单(包含主动买与被动买)或者挂买的大单 if buy_strategy_util.is_far_away_from_trade_index(code, trade_index, buy1_money): return False, True, f"距离成交进度位太远:成交进度-{trade_index} 买1-{buy1_money}" # ------------------上证下单需要有成交大单(包含主动买与被动买)或者挂买的大单----------------- if tool.is_sh_code(code): deal_big_order_count = BigOrderDealManager().get_total_buy_count(code) if deal_big_order_count < 1: @@ -983,7 +997,7 @@ if left_count < 1: return False, False, f"没有已挂或者成交的大单" place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code) # 第一和第二次下单都必须要有至少一笔未成交的大单 # ------------------第一和第二次下单都必须要有至少一笔未成交的大单-------------------------- # 计算大单 total_datas = local_today_datas.get(code) if place_order_count < 2: @@ -997,47 +1011,16 @@ if left_count < 1: return False, False, f"第{place_order_count + 1}下单无待成交的大单" # 执行位那一戳数据要小于20条数据 THRESHOLD_BUY_COUNT = 20 buy_count = 0 min_num = int(5000 / limit_up_price) # -------判断是否是量化下单,如果是就不跟到下单-------- # 重要:量化下单会增加下单次数,板块下单中有下单次数的使用,所以板块需要在量化判断之前 # 只有板块满足下单之后才能判断其它条件 range_indexes = cls.__processing_data_indexes.get(code) trade_index, is_default = transaction_progress.TradeBuyQueue().get_traded_index(code) if trade_index is None: trade_index = 0 if range_indexes: # 获取成交进度位 for i in range(range_indexes[0], range_indexes[1] + 1): val = total_datas[i]["val"] if not L2DataUtil.is_limit_up_price_buy(val): continue if val["num"] < min_num: continue buy_count += 1 if buy_count > THRESHOLD_BUY_COUNT: break if buy_count > THRESHOLD_BUY_COUNT: # 判断是否为量化 time_as_ms = tool.trade_time_sub_with_ms( L2DataUtil.get_time_with_ms(total_datas[range_indexes[1]]["val"]), L2DataUtil.get_time_with_ms(total_datas[range_indexes[0]]["val"])) if time_as_ms <= 10 if tool.is_sz_code(code) else 100: # 深证10ms内,上证100ms内就判定为量化 HuaXinSellOrderStatisticManager.clear_latest_deal_volume(code) cls.__next_buy_time_dict[code] = t.time() + buy_condition_util.get_cancel_and_buy_space_time( code) / 1000 # 如果是首次下单,增加一次下单次数 place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code) if place_order_count == 0: trade_data_manager.PlaceOrderCountManager().place_order(code) return False, True, f"执行位批次数据量({buy_count})大于{THRESHOLD_BUY_COUNT} {range_indexes[0]}-{range_indexes[1]}" # 暂时注释想买单功能 if not cls.__WantBuyCodesManager.is_in_cache(code): # if cls.__TradeTargetCodeModeManager.get_mode_cache() == TradeTargetCodeModeManager.MODE_ONLY_BUY_WANT_CODES: # return False, True, f"只买想买单中的代码" return cls.can_buy_first_new(code, limit_up_price) else: return True, False, "在想买单中" is_quantization_result = buy_strategy_util.is_quantization(code, range_indexes[0], range_indexes[1]) if is_quantization_result[0]: cls.__next_buy_time_dict[code] = is_quantization_result[1] return False, True, is_quantization_result[2] return True, False, "满足下单条件" # 获取可以买的板块 @classmethod @@ -1348,6 +1331,10 @@ is_first_code, new_add=True): # 中断当前批次买入数据处理 if cls.__break_current_batch_data_for_buy_dict.get(code): return # 判断下次买入时间是否正确 if code in cls.__next_buy_time_dict and t.time() < cls.__next_buy_time_dict[code]: return l2/l2_transaction_data_processor.py
@@ -84,8 +84,7 @@ limit_up_price = round(float(limit_up_price), 2) # 设置成交价 try: current_price_process_manager.set_trade_price(code, datas[-1][1], l2_huaxin_util.convert_time(datas[-1][3]), limit_up_price) current_price_process_manager.set_trade_price(code, datas[-1][1]) except: pass total_datas = l2_data_util.local_today_datas.get(code) @@ -101,6 +100,18 @@ big_sell_order_info = None try: # 统计上板时间 try: for d in datas: if d[6] > d[7]: # 主动买 if d[1] == limit_up_price: # 涨停 current_price_process_manager.set_latest_not_limit_up_time(code, l2_huaxin_util.convert_time( d[3], with_ms=True)) except: pass # 统计卖单 big_sell_order_info = HuaXinSellOrderStatisticManager.add_transaction_datas(code, datas, limit_up_price) @@ -120,7 +131,7 @@ # 判断时间是否与本地时间相差5s以上 if tool.trade_time_sub(tool.get_now_time_str(), l2_huaxin_util.convert_time(datas[-1][3])) > 10: now_seconds = int(tool.get_now_time_str().replace(":", "")) if now_seconds < int("093200"): #or int("130000") <= now_seconds < int("130200"): if now_seconds < int("093200"): # or int("130000") <= now_seconds < int("130200"): need_cancel, cancel_msg = True, f"成交时间与本地时间相差10S以上,{l2_huaxin_util.convert_time(datas[-1][3])}" if need_cancel: L2TradeDataProcessor.cancel_buy(code, cancel_msg) test/test.py
@@ -21,4 +21,4 @@ if __name__ == "__main__": global_data_loader.load_zyltgb_volume_from_db() print(1e7) trade/current_price_process_manager.py
@@ -46,7 +46,7 @@ rate = round((price - pricePre) * 100 / pricePre, 2) if tool.is_ge_code(code): # 创业板的涨幅需要打折 rate = rate/2 rate = rate / 2 if rate >= 0 and not trade_manager.ForbiddenBuyCodeByScoreManager().is_in_cache(code): # 暂存涨幅为正的代码 _code_list.append((rate, code, 1 if is_want_buy else 0)) @@ -165,12 +165,19 @@ # 设置成交价 def set_trade_price(code, price, time_str, limit_up_price): def set_trade_price(code, price): __trade_price_dict[code] = price # 需要记录最近一次非涨停价成交的时间 if limit_up_price and abs(limit_up_price - price) > 0.001: # 非涨停价成交 __trade_price_not_limit_up_info_dict[code] = (price, time_str) def set_latest_not_limit_up_time(code, time_str_with_ms): """ 记录最近的一次上板时间(最近的一笔主动买就是上板时间) @param code: @param time_str: @return: """ __trade_price_not_limit_up_info_dict[code] = time_str_with_ms # 获取成交价 @@ -178,10 +185,10 @@ return __trade_price_dict.get(code) def get_trade_not_limit_up_info(code): def get_trade_not_limit_up_time_with_ms(code): """ 获取最近的非涨停价成交的信息 获取最近的非板上成交的时间 @param code: @return:(价格,时间) @return:(价格, 时间) """ return __trade_price_not_limit_up_info_dict.get(code) utils/buy_strategy_util.py
@@ -1,9 +1,15 @@ """ 买入策略帮助类 """ import time from code_attribute import gpcode_manager from l2 import l2_data_util, l2_data_source_util from utils import tool from l2 import l2_data_util, l2_data_source_util, transaction_progress from l2.l2_data_util import L2DataUtil from l2.l2_transaction_data_manager import HuaXinSellOrderStatisticManager from settings.trade_setting import MarketSituationManager, TradeBlockBuyModeManager from trade import trade_data_manager from utils import tool, buy_condition_util, global_util def is_has_small_batch_cancel(code, start_index, end_index): @@ -49,6 +55,14 @@ def is_cancel_rate_reieved(code, threshhold_rate, start_index, end_index): """ 撤单比例是否达到某一个阈值 @param code: @param threshhold_rate: @param start_index: @param end_index: @return: """ # 统计总共的涨停买 limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) min_num = int(round(5000 / limit_up_price)) @@ -80,6 +94,43 @@ return False if round(cancel_count / buy_count, 2) > threshhold_rate: return True return False def is_far_away_from_trade_index(code, trade_index, buy1_money): """ 是否距离成交进度位太远 @param code: @param trade_index: @param buy1_money: @return: """ if buy1_money < 1e7: # 买1大于1千万才能计算 return False limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) min_num = int(round(5000 / limit_up_price)) threshhold_num = int(round(buy1_money * 0.5 / 100 / limit_up_price)) total_datas = l2_data_util.local_today_datas.get(code) end_index = total_datas[-1]["index"] total_num = 0 canceled_buyno_map = l2_data_util.local_today_canceled_buyno_map.get( code) for i in range(trade_index, end_index + 1): data = total_datas[i] val = data["val"] if not L2DataUtil.is_limit_up_price_buy(val): continue if val["num"] < min_num: continue left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2( code, i, total_datas, canceled_buyno_map) if left_count > 0: total_num += val["num"] if total_num > threshhold_num: return True return False @@ -117,3 +168,113 @@ if total_count > 10 or total_big_count < 1: return False, f"未成交数量-{total_count},大单数量-{total_big_count}" return True, "" def is_quantization(code, start_index, end_index): """ 是否是量化单 @param code: @param satrt_index: @param end_index: @return:(是否是量化, 下次可以下单时间) """ THRESHOLD_BUY_COUNT = 20 if end_index - start_index + 1 < THRESHOLD_BUY_COUNT: # 总数小于阈值 return False, None total_datas = l2_data_util.local_today_datas.get(code) limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) buy_count = 0 min_num = int(5000 / limit_up_price) trade_index, is_default = transaction_progress.TradeBuyQueue().get_traded_index(code) if trade_index is None: trade_index = 0 # 获取成交进度位 for i in range(start_index, end_index + 1): val = total_datas[i]["val"] if not L2DataUtil.is_limit_up_price_buy(val): continue if val["num"] < min_num: continue buy_count += 1 if buy_count > THRESHOLD_BUY_COUNT: break if buy_count > THRESHOLD_BUY_COUNT: # 判断是否为量化 time_as_ms = tool.trade_time_sub_with_ms( L2DataUtil.get_time_with_ms(total_datas[end_index]["val"]), L2DataUtil.get_time_with_ms(total_datas[start_index]["val"])) if time_as_ms <= 10 if tool.is_sz_code(code) else 100: # 深证10ms内,上证100ms内就判定为量化 HuaXinSellOrderStatisticManager.clear_latest_deal_volume(code) next_buy_time = time.time() + buy_condition_util.get_cancel_and_buy_space_time( code) / 1000 # 如果是首次下单,增加一次下单次数 place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code) if place_order_count == 0: trade_data_manager.PlaceOrderCountManager().place_order(code) return True, next_buy_time, f"执行位批次数据量({buy_count})大于{THRESHOLD_BUY_COUNT} {start_index}-{end_index}" return False, None else: return False, None def is_block_can_buy(code, can_buy_result): """ 板块是否可买 @param code: @param can_buy_result: @return: """ now_timestamp = int(tool.get_now_time_str().replace(":", "")) # 判断板块 # (可以买的板块列表, 是否是独苗, 消息简介,可买的强势主线, 板块关键词) if can_buy_result is None: return False, True, "尚未获取到板块信息" # 是否是强势30分钟 is_in_strong_time_30 = now_timestamp <= int("100000") # 获取市场行情 situation = MarketSituationManager().get_situation_cache() zylt_threshold_as_yi = buy_condition_util.get_zyltgb_threshold(situation) zyltgb_as_yi = round(global_util.zyltgb_map.get(code) / 100000000, 2) if zyltgb_as_yi < zylt_threshold_as_yi[0]: return False, True, f"{zylt_threshold_as_yi[0]}亿以下的都不买({zyltgb_as_yi})" # 测试时可取消注释 # if 1 > 0: # return True, False, "买所有" if zyltgb_as_yi >= zylt_threshold_as_yi[1]: return False, True, f"{zylt_threshold_as_yi[1]}亿以上的都不买({zyltgb_as_yi})" msg_list = [] if is_in_strong_time_30: msg_list.append("强势30分钟") # 独苗 if not can_buy_result[0] and can_buy_result[1]: msg_list.append("独苗") return True, False, "强势30分钟,独苗" elif not can_buy_result[0]: return False, True, f"强势30分钟,非独苗不满足身位:{can_buy_result[2]}" else: msg_list.append("非独苗") # 后排,满足自由流通市值需要下单 return True, False, can_buy_result[2] else: place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code) if place_order_count > 0: return True, False, "之前下过单" if not can_buy_result[0]: # 没有板块 if can_buy_result[1]: # 是独苗 if not TradeBlockBuyModeManager().can_buy_unique_block(): # 不能买独苗 return False, True, f"非强势30分钟,独苗,不满足身位:{can_buy_result[2]}" else: # 非独苗,没有可以买入的板块 return False, True, f"非强势30分钟,非独苗,不满足身位:{can_buy_result[2]}" return True, False, can_buy_result[2]