| | |
| | | limit_up_price, min_money) |
| | | |
| | | # 下单后3秒,排撤比例≥65%则撤掉,视为P撤的一种,排得太后了。 |
| | | if sub_time > 3 and not self.__far_away_computed_cache.get(code): |
| | | self.__far_away_computed_cache[code] = True |
| | | # 成交进度位到真实下单位的位置过远 |
| | | total_count_, total_num_ = L2DataComputeUtil.compute_left_buy_order(code, trade_index, real_order_index, |
| | | limit_up_price, 500000) |
| | | # 获取买1金额 |
| | | buy1_money = code_price_manager.Buy1PriceManager().get_latest_buy1_money(code) |
| | | if buy1_money: |
| | | if total_num_ * limit_up_price * 100 > buy1_money * 0.65: |
| | | return True, f"P撤:成交位置距离下单位置太远 成交位-{trade_index} 下单位-{real_order_index} 买1-{buy1_money}" |
| | | # if sub_time > 3 and not self.__far_away_computed_cache.get(code): |
| | | # self.__far_away_computed_cache[code] = True |
| | | # # 成交进度位到真实下单位的位置过远 |
| | | # total_count_, total_num_ = L2DataComputeUtil.compute_left_buy_order(code, trade_index, real_order_index, |
| | | # limit_up_price, 500000) |
| | | # # 获取买1金额 |
| | | # buy1_money = code_price_manager.Buy1PriceManager().get_latest_buy1_money(code) |
| | | # if buy1_money: |
| | | # if total_num_ * limit_up_price * 100 > buy1_money * 0.65: |
| | | # return True, f"P撤:成交位置距离下单位置太远 成交位-{trade_index} 下单位-{real_order_index} 买1-{buy1_money}" |
| | | min_time_s, max_time_s = 2, 30 |
| | | if total_num * limit_up_price >= 299 * 100: |
| | | min_time_s, max_time_s = 30, 60 |
| | |
| | | from l2.place_order_single_data_manager import L2TradeSingleDataProcessor |
| | | from log_module import async_log_util, log_export |
| | | from third_data import kpl_data_manager, block_info |
| | | from utils import global_util, ths_industry_util, tool, buy_condition_util |
| | | from utils import global_util, ths_industry_util, tool, buy_condition_util, buy_strategy_util |
| | | import l2_data_util |
| | | from db import redis_manager_delegate as redis_manager |
| | | from third_data.code_plate_key_manager import CodePlateKeyBuyManager, KPLCodeJXBlockManager |
| | |
| | | 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"距离上次挂单小于1000ms" |
| | | return False, True, f"距离上次挂单小于时间限制" |
| | | 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: |
| | |
| | | if not buy1_money: |
| | | buy1_money = 1 |
| | | deal_rate = round(total_deal_money / buy1_money, 2) |
| | | if deal_rate < 0.05: |
| | | if deal_rate < 0.15: |
| | | # 判断成交进度到当前数据的笔数,如果少于10笔且还有未成交的大单(>=299)就可以下单 |
| | | trade_index, is_default = cls.__TradeBuyQueue.get_traded_index(code) |
| | | if trade_index is None: |
| | | trade_index = 0 |
| | | total_count = 0 |
| | | total_big_count = 0 |
| | | for i in range(trade_index + 1, total_data[-1]["index"] + 1): |
| | | data = total_data[i] |
| | | val = data["val"] |
| | | if not L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | money = val["num"] * float(val["price"]) |
| | | if money < 5000: |
| | | continue |
| | | |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2( |
| | | code, |
| | | i, |
| | | total_data, |
| | | local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if left_count > 0: |
| | | total_count += 1 |
| | | if money > 29900: |
| | | total_big_count += 1 |
| | | if total_count > 10: |
| | | break |
| | | if total_count > 10 or total_big_count < 1: |
| | | return False, True, f"板上放量成交金额不足,近2s总成交比例({deal_rate}):{total_deal_money}/{buy1_money}小于0.05,未成交数量-{total_count},大单数量-{total_big_count}" |
| | | 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 tool.is_sh_code(code): |
| | | deal_big_order_count = BigOrderDealManager().get_total_buy_count(code) |
| | |
| | | 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: |
| | |
| | | if buy_count > THRESHOLD_BUY_COUNT: |
| | | break |
| | | if buy_count > THRESHOLD_BUY_COUNT: |
| | | HuaXinSellOrderStatisticManager.clear_latest_deal_volume(code) |
| | | cls.__next_buy_time_dict[code] = t.time() + 1 |
| | | return False, True, f"执行位批次数据量({buy_count})大于{THRESHOLD_BUY_COUNT} {range_indexes[0]}-{range_indexes[1]}" |
| | | # 判断是否为量化 |
| | | 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: |
| | |
| | | from code_attribute import global_data_loader |
| | | from settings.trade_setting import TradeBlockBuyModeManager |
| | | from third_data.history_k_data_util import HistoryKDatasUtils |
| | | from utils import tool |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | pass |
| | | global_data_loader.load_zyltgb_volume_from_db() |
| | |
| | | from log_module.log import logger_l2_error |
| | | from trade.trade_data_manager import PlaceOrderCountManager |
| | | from trade.trade_queue_manager import THSBuy1VolumnManager |
| | | from utils import tool, buy_condition_util |
| | | |
| | | __thsBuy1VolumnManager = THSBuy1VolumnManager() |
| | | |
| | |
| | | def can_place_order_for_cancel_time(code, buy_exec_data): |
| | | if code not in __latest_cancel_l2_data_dict: |
| | | return True |
| | | if L2DataUtil.time_sub_as_ms(buy_exec_data["val"], __latest_cancel_l2_data_dict[code]["val"]) >= 1000: |
| | | threshold_time_space = buy_condition_util.get_cancel_and_buy_space_time(code) |
| | | if L2DataUtil.time_sub_as_ms(buy_exec_data["val"], __latest_cancel_l2_data_dict[code]["val"]) >= threshold_time_space: |
| | | return True |
| | | return False |
| | | |
| | |
| | | # 返回:(最大买入,最优自由流通最小,最优自由流通最大) |
| | | from settings.trade_setting import MarketSituationManager |
| | | |
| | | |
| | | # 获取自由流通市值的阈值范围 |
| | | # (最小流通,最大流通,优秀开始,优秀结束,最优开始,最优结束,最大可买) |
| | | from utils import tool |
| | | |
| | | |
| | | def get_zyltgb_threshold(market_sitation: int): |
| | | if market_sitation == MarketSituationManager.SITUATION_GOOD: |
| | | return 31, 100, 40, 100, 40, 80, 100 |
| | |
| | | def get_volume_rate_by_level(level: int): |
| | | volume_rates = [0, 0.19, 0.49, 0.89] |
| | | return volume_rates[level] |
| | | |
| | | |
| | | def get_cancel_and_buy_space_time(code): |
| | | return 50 if tool.is_sz_code(code) else 250 |
New file |
| | |
| | | """ |
| | | 买入策略帮助类 |
| | | """ |
| | | from code_attribute import gpcode_manager |
| | | from l2 import l2_data_util, l2_data_source_util |
| | | from utils import tool |
| | | |
| | | |
| | | def is_has_small_batch_cancel(code, start_index, end_index): |
| | | """ |
| | | 是否有小群撤单:有连续10笔涨停撤单且连续10笔涨停撤单中小于2笔涨停买单 |
| | | @param code: |
| | | @param total_datas: |
| | | @param start_index: |
| | | @param end_index: |
| | | @return: |
| | | """ |
| | | # 从end_index找到start_index |
| | | limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) |
| | | min_num = int(round(5000 / limit_up_price)) |
| | | total_datas = l2_data_util.local_today_datas.get(code) |
| | | end_time_with_ms = l2_data_util.L2DataUtil.get_time_with_ms(total_datas[end_index]["val"]) |
| | | buy_count = 0 |
| | | cancel_count = 0 |
| | | for i in range(end_index - 1, start_index - 1, -1): |
| | | data = total_datas[i] |
| | | val = data["val"] |
| | | if val["num"] < min_num: |
| | | continue |
| | | |
| | | if not l2_data_util.L2DataUtil.is_limit_up_price_buy_cancel(val): |
| | | if l2_data_util.L2DataUtil.is_limit_up_price_buy(val): |
| | | if cancel_count > 0: |
| | | # 当统计到一个涨停买撤的时候才能统计买 |
| | | buy_count += 1 |
| | | if buy_count > 1: |
| | | break |
| | | continue |
| | | # 与当前时间相差3s的结束 |
| | | if tool.trade_time_sub_with_ms(end_time_with_ms, l2_data_util.L2DataUtil.get_time_with_ms(val)) > 3000: |
| | | break |
| | | |
| | | cancel_count += 1 |
| | | if cancel_count >= 10: |
| | | break |
| | | if cancel_count >= 10 and buy_count < 2: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | def is_cancel_rate_reieved(code, threshhold_rate, start_index, end_index): |
| | | # 统计总共的涨停买 |
| | | limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) |
| | | min_num = int(round(5000 / limit_up_price)) |
| | | total_datas = l2_data_util.local_today_datas.get(code) |
| | | buyno_map = l2_data_util.local_today_buyno_map.get(code) |
| | | buy_count = 0 |
| | | for i in range(start_index, end_index): |
| | | data = total_datas[i] |
| | | val = data["val"] |
| | | if not l2_data_util.L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | if val["num"] < min_num: |
| | | continue |
| | | buy_count += 1 |
| | | # 统计总共的涨停买撤 |
| | | cancel_count = 0 |
| | | for i in range(start_index, end_index): |
| | | data = total_datas[i] |
| | | val = data["val"] |
| | | if not l2_data_util.L2DataUtil.is_limit_up_price_buy_cancel(val): |
| | | continue |
| | | if val["num"] < min_num: |
| | | continue |
| | | |
| | | buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data_v2(val, buyno_map) |
| | | if buy_index and start_index <= buy_index: |
| | | cancel_count += 1 |
| | | if buy_count == 0: |
| | | return False |
| | | if round(cancel_count / buy_count, 2) > threshhold_rate: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | def is_near_by_trade_index(code, trade_index): |
| | | """ |
| | | 是否距离成交位近 |
| | | @param code: |
| | | @param trade_index: |
| | | @return: |
| | | """ |
| | | total_data = l2_data_util.local_today_datas.get(code) |
| | | total_count = 0 |
| | | total_big_count = 0 |
| | | for i in range(trade_index + 1, total_data[-1]["index"] + 1): |
| | | data = total_data[i] |
| | | val = data["val"] |
| | | if not l2_data_util.L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | money = val["num"] * float(val["price"]) |
| | | if money < 5000: |
| | | continue |
| | | |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2( |
| | | code, |
| | | i, |
| | | total_data, |
| | | l2_data_util.local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if left_count > 0: |
| | | total_count += 1 |
| | | if money > 29900: |
| | | total_big_count += 1 |
| | | if total_count > 10: |
| | | break |
| | | if total_count > 10 or total_big_count < 1: |
| | | return False, f"未成交数量-{total_count},大单数量-{total_big_count}" |
| | | return True, "" |