Administrator
2024-04-25 5944459decfb041cc599f1814c1fbf9f23e090dd
F撤阈值重新定义/新G撤实现
7个文件已修改
268 ■■■■■ 已修改文件
constant.py 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/cancel_buy_strategy.py 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_manager_new.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_transaction_data_processor.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/l2_trade_test.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/test.py 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/trade_result_manager.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
constant.py
@@ -147,7 +147,10 @@
F_CANCEL_CACEL_RATE = 0.69
# G撤单
G_CANCEL_RATE = 0.59
G_CANCEL_RATE = 0.69
# G撤加红
G_CANCEL_RATE_WITH_MUST_BUY = 0.9
# 行情好时的撤单比例
G_CANCEL_RATE_FOR_GOOD_MARKET = 0.59
l2/cancel_buy_strategy.py
@@ -11,7 +11,7 @@
import time
import constant
from code_attribute import big_money_num_manager, gpcode_manager
from code_attribute import big_money_num_manager, gpcode_manager, code_volumn_manager
import l2_data_util
from db import redis_manager_delegate as redis_manager
from db.redis_manager_delegate import RedisUtils
@@ -40,7 +40,7 @@
    LCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index=buy_single_index,
                                                       is_default=is_default)
    HourCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index)
    GCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index, is_default)
    NewGCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index, is_default)
    FCancelBigNumComputer().set_real_order_index(code, index, is_default)
@@ -1711,6 +1711,24 @@
    def cancel_success(self, code):
        self.clear(code)
    def __get_fast_deal_threshold_value(self, code):
        """
        获取 F撤阈值
        @param code:
        @return:(金额(单位:W),笔数)
        """
        max60, yesterday = code_volumn_manager.get_histry_volumn(code)
        if max60:
            num = max60[0]
            limit_up_price = gpcode_manager.get_limit_up_price(code)
            if limit_up_price:
                money_y = round((num * float(limit_up_price))/1e8,1)
                money =int(200*money_y + 280)
                count = int(money_y*10)//10 + 3
                return money,count
        # 默认值
        return 300,3
    # 下单3分钟内距离下单位置不足3笔(包含正在成交)且不到300w就需要撤单
    def need_cancel_for_deal_fast(self, code, trade_index=None):
        if trade_index is None:
@@ -1736,7 +1754,7 @@
        if tool.trade_time_sub(tool.get_now_time_str(), total_datas[real_order_index]['val']['time']) > 3 * 60:
            return False, "下单超过180s"
        THRESHOLD_COUNT = 3
        THRESHOLD_MONEY_W, THRESHOLD_COUNT = self.__get_fast_deal_threshold_value(code)
        total_left_count = 0
        total_left_num = 0
@@ -1764,8 +1782,8 @@
                    total_left_num -= dealing_info[1] // 100
        limit_up_price = gpcode_manager.get_limit_up_price(code)
        if total_left_count <= 1 or (total_left_count <= THRESHOLD_COUNT and limit_up_price and total_left_num * float(
                limit_up_price) < 300 * 100):
            return True, f"剩余笔数({total_left_count})/金额({round(total_left_num * float(limit_up_price) * 100)})不足,成交进度:{trade_index},真实下单位置:{real_order_index}"
                limit_up_price) < THRESHOLD_MONEY_W * 100):
            return True, f"剩余笔数({total_left_count})/金额({round(total_left_num * float(limit_up_price) * 100)})不足,成交进度:{trade_index},真实下单位置:{real_order_index} 阈值:({THRESHOLD_MONEY_W},{THRESHOLD_COUNT}) "
        return False, f"不满足撤单条件: 成交进度-{trade_index} 真实下单位置-{real_order_index} total_left_count-{total_left_count} total_left_num-{total_left_num}"
    # 距离太近,封单不足,有大单50w大单砸下来就撤
@@ -1961,6 +1979,7 @@
        origin_watch_index = self.__watch_indexes_dict.get(code)
        if origin_watch_index is None:
            origin_watch_index = set()
        # 不需要备用
        origin_watch_index_by = self.__watch_indexes_by_dict.get(code)
        if origin_watch_index_by is None:
            origin_watch_index_by = set()
@@ -2202,6 +2221,204 @@
    def cancel_success(self, code):
        self.clear(code)
# ---------------------------------新G撤-------------------------------
class NewGCancelBigNumComputer:
    __real_place_order_index_dict = {}
    __trade_progress_index_dict = {}
    __watch_indexes_dict = {}
    # 最新处理的卖单
    __latest_process_sell_order_no_dict = {}
    __instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = super(NewGCancelBigNumComputer, cls).__new__(cls, *args, **kwargs)
        return cls.__instance
    def set_real_place_order_index(self, code, index, buy_single_index, is_default):
        self.__real_place_order_index_dict[code] = (index, is_default)
        start_index = buy_single_index
        if code in self.__trade_progress_index_dict:
            start_index = self.__trade_progress_index_dict.get(code)
        self.__commpute_watch_indexes(code, start_index, (index, is_default), from_real_order_index_changed=True)
    def clear(self, code=None):
        if code:
            if code in self.__real_place_order_index_dict:
                self.__real_place_order_index_dict.pop(code)
            if code in self.__watch_indexes_dict:
                self.__watch_indexes_dict.pop(code)
            if code in self.__trade_progress_index_dict:
                self.__trade_progress_index_dict.pop(code)
        else:
            self.__real_place_order_index_dict.clear()
            self.__watch_indexes_dict.clear()
            self.__trade_progress_index_dict.clear()
    # recompute:是否重新计算
    def __commpute_watch_indexes(self, code, traded_index, real_order_index_info, from_real_order_index_changed=False,
                                 recompute=False):
        if traded_index is None or real_order_index_info is None:
            return
        real_order_index, is_default = real_order_index_info[0], real_order_index_info[1]
        origin_watch_index = self.__watch_indexes_dict.get(code)
        if origin_watch_index is None:
            origin_watch_index = set()
        # 重新计算需要清除之前的数据
        if recompute:
            origin_watch_index.clear()
        start_index = traded_index
        if traded_index in origin_watch_index:
            # 正在成交的是已经囊括了的大单
            start_index = traded_index + 1
        total_datas = local_today_datas.get(code)
        watch_indexes = set()
        for i in range(start_index, real_order_index):
            # 判断是否有未撤的大单
            data = total_datas[i]
            val = data["val"]
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            if val["num"] * float(val["price"]) < 29900:
                continue
            # 是否已撤单
            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code, i,
                                                                                                     total_datas,
                                                                                                     local_today_canceled_buyno_map.get(
                                                                                                         code))
            if left_count > 0:
                watch_indexes.add(i)
        if watch_indexes:
            # 还有300万以上的大单没有撤单
            if from_real_order_index_changed or recompute:
                # 真实下单位改变后才会更新
                final_watch_indexes = origin_watch_index | watch_indexes
                self.__watch_indexes_dict[code] = final_watch_indexes
                l2_log.g_cancel_debug(code, f"大单监听:{final_watch_indexes} 是否重新计算:{recompute}")
    def set_trade_progress(self, code, buy_single_index, index):
        if self.__trade_progress_index_dict.get(code) != index:
            self.__trade_progress_index_dict[code] = index
            self.__commpute_watch_indexes(code, index, self.__real_place_order_index_dict.get(code))
    def need_cancel(self, code, buy_exec_index, start_index, end_index):
        if code not in self.__real_place_order_index_dict:
            return False, None, "没有找到真实下单位"
        real_place_order_index, is_default = self.__real_place_order_index_dict.get(code)
        total_datas = local_today_datas.get(code)
        # if tool.trade_time_sub(total_datas[end_index]["val"]["time"], total_datas[buy_exec_index]['val']['time']) > 180:
        #     return False, None, "超过180s的生效时间"
        watch_indexes = self.__watch_indexes_dict.get(code)
        if watch_indexes is None:
            watch_indexes = set()
        if len(watch_indexes) < 3:
            return False, None, "大于等于3个大单生效"
        need_compute = False
        for i in range(start_index, end_index + 1):
            data = total_datas[i]
            val = data["val"]
            if not L2DataUtil.is_limit_up_price_buy_cancel(val):
                continue
            if val["num"] * float(val["price"]) < 5000:
                continue
            buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data_v2(data,
                                                                                                local_today_buyno_map.get(
                                                                                                    code))
            if buy_index is not None and buy_index < real_place_order_index and (buy_index in watch_indexes):
                if buy_index in watch_indexes:
                    # 大单撤需要重新计算大单撤单比例
                    need_compute = True
                    break
        if need_compute and watch_indexes:
            canceled_indexes = set()
            for index in watch_indexes:
                cancel_data = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_canceled_data_v2(code, index,
                                                                                                      total_datas,
                                                                                                      local_today_canceled_buyno_map.get(
                                                                                                          code))
                if cancel_data:
                    canceled_indexes.add(cancel_data["index"])
            cancel_rate = round(len(canceled_indexes) / len(watch_indexes), 2)
            threshhold_rate = constant.G_CANCEL_RATE
            situation = trade_manager.MarketSituationManager().get_situation_cache()
            if situation == trade_manager.MarketSituationManager.SITUATION_GOOD:
                threshhold_rate = constant.G_CANCEL_RATE_FOR_GOOD_MARKET
            if gpcode_manager.MustBuyCodesManager().is_in_cache(code):
                threshhold_rate = constant.G_CANCEL_RATE_WITH_MUST_BUY
            if cancel_rate > threshhold_rate:
                canceled_indexes_list = list(canceled_indexes)
                canceled_indexes_list.sort()
                return True, total_datas[canceled_indexes_list[-1]], f"撤单比例:{cancel_rate}"
        return False, None, ""
    def place_order_success(self, code):
        self.clear(code)
    def cancel_success(self, code):
        self.clear(code)
    # B撤单
    # 剩余一个大单撤半截就撤单
    def need_cancel_for_b(self, code, start_index, end_index):
        real_place_order_info = self.__real_place_order_index_dict.get(code)
        if not real_place_order_info or real_place_order_info[1]:
            # 没有真实下单位置
            return False, None, "没有真实下单位置"
        trade_index, is_default = TradeBuyQueue().get_traded_index(code)
        if trade_index is None:
            return False, None, "未获取到成交进度位"
        total_datas = local_today_datas.get(code)
        buyno_map = local_today_buyno_map.get(code)
        cancel_half_index = None
        for i in range(start_index, end_index + 1):
            data = total_datas[i]
            val = data['val']
            if not L2DataUtil.is_limit_up_price_buy_cancel(val):
                continue
            orderNo = val['orderNo']
            buy_data = buyno_map.get(f"{orderNo}")
            if not buy_data:
                continue
            # 判断大单
            if buy_data["val"]["num"] * float(buy_data["val"]["price"]) < 29900:
                continue
            # 判断是否撤半截
            if buy_data["val"]["num"] > val["num"]:
                cancel_half_index = i
                break
        if cancel_half_index is None:
            return False, None, "没有撤半截"
        # 有大单撤半截桩
        # 计算是否还剩下大单
        total_big_num_count = 0
        for i in range(trade_index, real_place_order_info[0]):
            data = total_datas[i]
            val = data['val']
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            if val["num"] * float(val["price"]) < 29900:
                continue
            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code, i,
                                                                                                     total_datas,
                                                                                                     local_today_canceled_buyno_map.get(
                                                                                                         code))
            if left_count > 0:
                total_big_num_count += 1
                break
        if total_big_num_count == 0:
            # 没有剩下大单
            return True, total_datas[cancel_half_index], f"B撤:撤单索引-{cancel_half_index}"
        return False, None, "还有大单没撤单"
# ---------------------------------独苗撤-------------------------------
class UCancelBigNumComputer:
l2/l2_data_manager_new.py
@@ -22,7 +22,7 @@
from l2 import l2_data_manager, l2_log, l2_data_source_util, code_price_manager, \
    transaction_progress, cancel_buy_strategy, place_order_single_data_manager
from l2.cancel_buy_strategy import SCancelBigNumComputer, HourCancelBigNumComputer, DCancelBigNumComputer, \
    LCancelBigNumComputer, LatestCancelIndexManager, LCancelRateManager, GCancelBigNumComputer
    LCancelBigNumComputer, LatestCancelIndexManager, LCancelRateManager, GCancelBigNumComputer, NewGCancelBigNumComputer
from l2.l2_data_manager import L2DataException, OrderBeginPosInfo
from l2.l2_data_util import local_today_datas, L2DataUtil, local_today_num_operate_map, local_today_buyno_map, \
    local_latest_datas, local_today_canceled_buyno_map, local_today_sellno_map
@@ -224,7 +224,7 @@
    __SCancelBigNumComputer = SCancelBigNumComputer()
    __HourCancelBigNumComputer = HourCancelBigNumComputer()
    __LCancelBigNumComputer = LCancelBigNumComputer()
    __GCancelBigNumComputer = GCancelBigNumComputer()
    __GCancelBigNumComputer = NewGCancelBigNumComputer()
    __TradeStateManager = trade_manager.TradeStateManager()
    __CodesTradeStateManager = trade_manager.CodesTradeStateManager()
    __PauseBuyCodesManager = gpcode_manager.PauseBuyCodesManager()
l2/l2_transaction_data_processor.py
@@ -5,7 +5,7 @@
from code_attribute import gpcode_manager
from l2 import l2_data_util, l2_data_manager, transaction_progress
from l2.cancel_buy_strategy import FCancelBigNumComputer, LCancelBigNumComputer, LCancelRateManager, \
    GCancelBigNumComputer, SCancelBigNumComputer, HourCancelBigNumComputer
    GCancelBigNumComputer, SCancelBigNumComputer, HourCancelBigNumComputer, NewGCancelBigNumComputer
from l2.l2_data_manager_new import L2TradeDataProcessor
from l2.l2_data_util import L2DataUtil
from l2.l2_transaction_data_manager import HuaXinBuyOrderManager, HuaXinSellOrderStatisticManager, BigOrderDealManager
@@ -133,7 +133,7 @@
                async_log_util.info(logger_l2_trade_buy_queue, "获取成交位置成功: code-{} index-{}", code,
                                    buy_progress_index)
                if is_placed_order:
                    GCancelBigNumComputer().set_trade_progress(code, order_begin_pos.buy_single_index,
                    NewGCancelBigNumComputer().set_trade_progress(code, order_begin_pos.buy_single_index,
                                                               buy_progress_index)
                    LCancelBigNumComputer().set_trade_progress(code, order_begin_pos.buy_single_index,
                                                               buy_progress_index,
test/l2_trade_test.py
@@ -270,7 +270,7 @@
        l2.l2_data_util.load_l2_data(code)
        total_datas = l2.l2_data_util.local_today_datas.get(code)
        TradeBuyQueue.get_traded_index = mock.Mock(return_value=(1000, False))
        cancel_buy_strategy.GCancelBigNumComputer().set_real_place_order_index(code, 1015, 10000, False)
        cancel_buy_strategy.NewGCancelBigNumComputer().set_real_place_order_index(code, 1015, 10000, False)
        cancel_buy_strategy.GCancelBigNumComputer().set_trade_progress(code, 1000, 1000)
        result = cancel_buy_strategy.GCancelBigNumComputer().need_cancel_for_b(code, 1020, 1077)
        print(result)
test/test.py
@@ -1,12 +1,8 @@
if __name__ == "__main__":
    left_money_w = -3900
    for w in [-3900, -3600, -3300,-3000, -2700, -2400,-2100,-900,3900,3900,4200,4500]:
        if w > 0:
            rate = ((w + 300) // 900) * 2
        else:
            rate = ((w + 599) // 900) * 2
        if rate < -10:
            rate = -10
        if rate > 10:
            rate = 10
        print(w, rate)
    num = 25070171
    limit_up_price = 5.1
    if limit_up_price:
        money_y = round((num * float(limit_up_price)) / 1e8, 1)
        money = int(200 * money_y + 280)
        count = int(money_y * 10) // 10 + 3
        print( money, count)
trade/trade_result_manager.py
@@ -4,7 +4,7 @@
from code_attribute.gpcode_manager import MustBuyCodesManager
from l2 import l2_data_manager, place_order_single_data_manager
from l2.cancel_buy_strategy import HourCancelBigNumComputer, SCancelBigNumComputer, \
    LCancelBigNumComputer, DCancelBigNumComputer, GCancelBigNumComputer, FCancelBigNumComputer
    LCancelBigNumComputer, DCancelBigNumComputer, GCancelBigNumComputer, FCancelBigNumComputer, NewGCancelBigNumComputer
from l2.l2_data_manager import OrderBeginPosInfo
from l2.l2_data_util import local_today_datas, local_today_num_operate_map, L2DataUtil
from l2.l2_sell_manager import L2MarketSellManager
@@ -30,7 +30,7 @@
    l2_data_manager.TradePointManager().delete_buy_point(code)
    SCancelBigNumComputer().cancel_success(code)
    LCancelBigNumComputer().cancel_success(code)
    GCancelBigNumComputer().cancel_success(code)
    NewGCancelBigNumComputer().cancel_success(code)
    # dask.compute(f1, f2, f5, f6, f7, f8)
@@ -71,7 +71,7 @@
    def g_cancel(code):
        try:
            GCancelBigNumComputer().place_order_success(code)
            NewGCancelBigNumComputer().place_order_success(code)
        except Exception as e:
            logging.exception(e)
            logger_l2_error.exception(e)
@@ -116,7 +116,7 @@
    SCancelBigNumComputer().cancel_success(code)
    LCancelBigNumComputer().cancel_success(code)
    FCancelBigNumComputer().cancel_success(code)
    GCancelBigNumComputer().cancel_success(code)
    NewGCancelBigNumComputer().cancel_success(code)
    # 记录最近的撤单时间
    if from_real_cancel:
        __latest_cancel_l2_data_dict[code] = total_datas[-1]