Administrator
2024-08-14 a51d5c5cfadafdc2cf75ca581d212c1d7c8e12ca
买入策略修改
5个文件已修改
1个文件已添加
217 ■■■■ 已修改文件
l2/cancel_buy_strategy.py 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_manager_new.py 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/test.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/trade_result_manager.py 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/buy_condition_util.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/buy_strategy_util.py 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/cancel_buy_strategy.py
@@ -435,16 +435,16 @@
                                                                          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
l2/l2_data_manager_new.py
@@ -15,7 +15,7 @@
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
@@ -913,7 +913,7 @@
        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:
@@ -942,36 +942,24 @@
                    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)
@@ -993,7 +981,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:
@@ -1027,9 +1015,20 @@
                    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:
test/test.py
@@ -1,3 +1,4 @@
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
@@ -20,4 +21,4 @@
if __name__ == "__main__":
    pass
    global_data_loader.load_zyltgb_volume_from_db()
trade/trade_result_manager.py
@@ -14,6 +14,7 @@
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()
@@ -137,7 +138,8 @@
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
utils/buy_condition_util.py
@@ -5,9 +5,11 @@
# 返回:(最大买入,最优自由流通最小,最优自由流通最大)
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
@@ -19,3 +21,7 @@
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
utils/buy_strategy_util.py
New file
@@ -0,0 +1,119 @@
"""
买入策略帮助类
"""
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, ""