Administrator
2023-06-25 4bd794d517a60ecd91dda4cb8236453582180649
结构优化/初步完成D撤与L撤/H撤策略修改
1个文件已删除
9个文件已修改
2个文件已添加
555 ■■■■ 已修改文件
constant.py 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
init.py 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/cancel_buy_strategy.py 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/huaxin/l2_huaxin_util.py 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_manager_new.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_source_util.py 99 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_util.py 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_huaxin_util.py 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2_data_util.py 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server.py 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/huaxin/huaxin_transaction_manager.py 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/trade_result_manager.py 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
constant.py
@@ -46,3 +46,19 @@
API_TRADE_ENABLE = True
# 每只票买的金额
BUY_MONEY_PER_CODE = 8000
# L2数据来源
L2_SOURCE_TYPE_THS = "ths"
L2_SOURCE_TYPE_HUAXIN = "huaxin"
L2_SOURCE_TYPE = L2_SOURCE_TYPE_THS
# D撤单
# 守护时间
D_CANCEL_EXPIRE_TIME = 120
D_CANCEL_RATE = 0.5
# L撤
L_CANCEL_MAX_WATCH_COUNT = 5
# 撤单比例
L_CANCEL_RATE = 0.6
# 最小金额
L_CANCEL_MIN_MONEY = 98
init.py
@@ -28,7 +28,7 @@
from third_data.history_k_data_util import HistoryKDatasUtils
from trade import trade_gui, l2_trade_util, trade_manager
from l2.cancel_buy_strategy import L2LimitUpSellStatisticUtil
from l2.cancel_buy_strategy import L2LimitUpSellStatisticUtil, LCancelBigNumComputer
from log import logger_juejin_tick, logger_system
from trade.trade_data_manager import CodeActualPriceProcessor
from trade.trade_queue_manager import JueJinBuy1VolumnManager
@@ -87,6 +87,8 @@
        # 清空暂停交易代码
        gpcode_manager.PauseBuyCodesManager.clear()
        LCancelBigNumComputer.clear()
# 每日初始化
def everyday_init():
l2/cancel_buy_strategy.py
@@ -350,8 +350,10 @@
        # 守护30s以外的数据
        if time_space <= constant.S_CANCEL_EXPIRE_TIME:
            return False, None
            # 获取成交进度
        # 获取成交进度
        origin_progress_index, latest_progress_index = cls.__get_traded_progress(code)
        if latest_progress_index is None:
            latest_progress_index = -1
        # 监听的数据
        watch_indexs_dict = {}
        total_nums = 0
@@ -371,6 +373,8 @@
        if datas:
            for indexs in datas:
                index = indexs[0]
                if index < latest_progress_index:
                    continue
                watch_indexs_dict[index] = indexs
                total_nums += total_data[index]["val"]["num"] * indexs[2]
@@ -383,6 +387,18 @@
        process_index = start_index
        # 是否有观测的数据撤单
        has_watch_canceled = False
        # 获取之前已经撤单的数据
        old_canceld_indexs = cls.__get_watch_canceled_index(code)
        # 重新计算撤单
        cancel_num = 0
        if old_canceld_indexs:
            for d in old_canceld_indexs:
                nx = int(d.split("-")[0])
                num = int(d.split("-")[1])
                if nx < latest_progress_index:
                    continue
                cancel_num += total_data[nx]["re"] * num
        try:
            for i in range(start_index, end_index + 1):
                if i <= processed_index:
@@ -426,7 +442,8 @@
                now_rate = round(cancel_num / total_nums, 4)
                if now_rate < cancel_rate_threshold and cancel_rate_threshold - now_rate < 0.1:
                    # 距离撤单在5%以内
                    kp_client_msg_manager.add_msg(code, f"逼近H撤({now_rate*100}%/{cancel_rate_threshold*100}%),需要人工判别。")
                    kp_client_msg_manager.add_msg(code,
                                                  f"逼近H撤({now_rate * 100}%/{cancel_rate_threshold * 100}%),需要人工判别。")
        return False, None
@@ -626,6 +643,173 @@
        return watch_indexs_dict, cls.__get_watch_canceled_index(code)
# ---------------------------------D撤-------------------------------
# 计算 成交位->真实下单位置 总共还剩下多少手没有撤单
# 成交位变化之后重新计算
class DCancelBigNumComputer:
    __redis_manager = redis_manager.RedisManager(0)
    @classmethod
    def __getRedis(cls):
        return cls.__redis_manager.getRedis()
    @classmethod
    def __set_real_order_index(cls, code, index):
        cls.__getRedis().setex(f"d_cancel_real_order_index-{code}", index)
    @classmethod
    def __get_real_order_index(cls, code):
        val = cls.__getRedis().get(f"d_cancel_real_order_index-{code}")
        if val:
            return int(val)
        return None
    # 设置成交位
    @classmethod
    def set_trade_progress(cls, code, index, buy_exec_index, total_data, local_today_num_operate_map, m_value,
                           limit_up_price):
        # 离下单执行位2分钟内的有效
        if tool.trade_time_sub(total_data[-1]['val']['time'], total_data[buy_exec_index]['val']['time']) > constant.D_CANCEL_EXPIRE_TIME:
            return False, "超过D撤守护时间"
        real_order_index = cls.__get_real_order_index(code)
        if not real_order_index:
            return False, "尚未获取到真实下单位置"
        left_num = 0
        for i in range(index, real_order_index + 1):
            data = total_data[i]
            val = data['val']
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            if val['num'] * val['price'] < 5900:
                continue
            left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count(code, i,
                                                                                                  total_data,
                                                                                                  local_today_num_operate_map)
            left_num += val['num'] * left_count
        # 剩下的不足动态M值的1/2
        rate = round(limit_up_price * left_num * 100 / m_value, 3)
        if rate < constant.D_CANCEL_RATE:
            return True, f"D撤比例为:{rate}"
        return False, ""
    # 设置真实的下单位置
    @classmethod
    def set_real_order_index(cls, code, index):
        pass
# ---------------------------------L撤-------------------------------
# 计算成交位置之后的大单(特定笔数)的撤单比例
class LCancelBigNumComputer:
    __redis_manager = redis_manager.RedisManager(0)
    __last_trade_progress_dict = {}
    @classmethod
    def __getRedis(cls):
        return cls.__redis_manager.getRedis()
    @classmethod
    def __add_watch_index(cls, code, index):
        cls.__getRedis().sadd(f"l_cancel_watch_index-{code}", index)
        cls.__getRedis().expire(f"l_cancel_watch_index-{code}", tool.get_expire())
    @classmethod
    def __del_watch_index(cls, code, index):
        cls.__getRedis().srem(f"l_cancel_watch_index-{code}", index)
    @classmethod
    def __get_watch_indexes(cls, code):
        return cls.__getRedis().smembers(f"l_cancel_watch_index-{code}")
    @classmethod
    def del_watch_index(cls, code):
        cls.__getRedis().delete(f"l_cancel_watch_index-{code}")
    @classmethod
    def clear(cls):
        keys = cls.__getRedis().keys(f"l_cancel_watch_index-*")
        for k in keys:
            cls.__getRedis().delete(k)
    # 设置成交位置,成交位置变化之后相应的监听数据也会发生变化
    @classmethod
    def set_trade_progress(cls, code, index, total_data):
        old_watch_indexes = cls.__get_watch_indexes(code)
        if cls.__last_trade_progress_dict.get(code) == index and len(
                old_watch_indexes) >= constant.L_CANCEL_MAX_WATCH_COUNT:
            # 成交进度尚未发生变化且已经监听到了足够的数据
            return
        watch_indexes = set()
        for i in range(index + 1, total_data[-1]["index"] + 1):
            data = total_data[i]
            val = data['val']
            if not L2DataUtil.is_limit_up_price_buy(val):
                continue
            if val["num"] * float(val["price"]) <= constant.L_CANCEL_MIN_MONEY * 100:
                continue
            cancel_datas = local_today_num_operate_map.get(
                "{}-{}-{}".format(val["num"], "1", val["price"]))
            canceled = False
            if cancel_datas:
                for cancel_data in cancel_datas:
                    buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data(code, cancel_data,
                                                                                                     local_today_num_operate_map)
                    if buy_index == index:
                        canceled = True
                        break
            if not canceled:
                watch_indexes.add(index)
                if len(watch_indexes) >= constant.L_CANCEL_MAX_WATCH_COUNT:
                    break
        # 数据维护
        add_indexes = watch_indexes - old_watch_indexes
        delete_indexes = old_watch_indexes - watch_indexes
        for i in add_indexes:
            cls.__add_watch_index(code, i)
        for i in delete_indexes:
            cls.__del_watch_index(code, i)
    @classmethod
    def need_cancel(cls, code, buy_exec_index, start_index, end_index, total_data, local_today_num_operate_map,
                    is_first_code):
        time_space = tool.trade_time_sub(total_data[start_index]["val"]["time"],
                                         total_data[buy_exec_index]["val"]["time"])
        # 守护30s以外的数据
        if time_space <= constant.S_CANCEL_EXPIRE_TIME:
            return False, None
        watch_indexes = cls.__get_watch_indexes(code)
        if not watch_indexes:
            return False, None
        for i in range(start_index, end_index + 1):
            data = total_data[i]
            val = data["val"]
            if L2DataUtil.is_limit_up_price_buy_cancel(val):
                # 查询买入位置
                buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data(code, data,
                                                                                                 local_today_num_operate_map)
                if buy_index is not None and buy_index in watch_indexes:
                    # 计算撤单比例
                    canceled_count = 0
                    total_count = 0
                    for wi in watch_indexes:
                        left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count(code,
                                                                                                              wi,
                                                                                                              total_data,
                                                                                                              local_today_num_operate_map)
                        canceled_count += (total_data[wi]["re"] - left_count)
                        total_count += total_data[wi]["re"]
                    if canceled_count / total_count >= constant.L_CANCEL_RATE:
                        return True, data
        return False, None
# --------------------------------封单额变化撤------------------------
# 涨停封单额统计
class L2LimitUpMoneyStatisticUtil:
l2/huaxin/l2_huaxin_util.py
New file
@@ -0,0 +1,89 @@
"""
华鑫LV2处理工具类
"""
# 处理逐笔委托
# item逐笔委托
# (data['SecurityID'], data['Price'], data['Volume'], data['Side'], data['OrderType'],
# data['OrderTime'],data['MainSeq'], data['SubSeq'], data['OrderNO'], data['OrderStatus'])
import decimal
import tool
from l2.l2_data_util import L2DataUtil
def __convert_order(item, limit_up_price):
    time_str = f"{item[5]}"
    if time_str.startswith("9"):
        time_str = f"0{time_str}"
    time_ = f"{time_str[0:2]}:{time_str[2:4]}:{time_str[4:6]}"
    price = item["Price"]
    if price <= 0:
        # 深证的买撤无价格数据,需要去查找价格数据,暂时设置为涨停价
        price = limit_up_price
    limitPrice = 1 if abs(limit_up_price - price) < 0.001 else 0
    operateType = 0
    if item[''] == 'D':
        if item[3] == '1':
            # 买撤
            operateType = 1
        else:
            # 卖撤
            operateType = 3
    else:
        if item[3] == '1':
            # 买
            operateType = 0
        else:
            # 卖
            operateType = 2
    return {"time": time_, "price": price, "num": item[2] // 100, "limitPrice": limitPrice,
            "operateType": operateType, "cancelTime": 0, "cancelTimeUnit": 0, "orderNo": item[8],
            "mainSeq": item[6], "subSeq": item[7]}
# 处理l2数据
def __format_l2_data(origin_datas, code, limit_up_price):
    datas = []
    dataIndexs = {}
    same_time_num = {}
    for item in origin_datas:
        # 解析数据
        time = item["time"]
        if time in same_time_num:
            same_time_num[time] = same_time_num[time] + 1
        else:
            same_time_num[time] = 1
        price = item["price"]
        num = item["num"]
        limitPrice = item["limitPrice"]
        # 涨停价
        if limit_up_price is not None:
            if abs(price - limit_up_price) < 0.001:
                limitPrice = 1
            else:
                limitPrice = 0
            item["limitPrice"] = "{}".format(limitPrice)
        operateType = item["operateType"]
        # 不需要非涨停买与买撤
        if int(item["limitPrice"]) != 1 and (int(operateType) == 0 or int(operateType) == 1):
            continue
        key = "{}-{}-{}".format(code, item["mainSeq"], item["subSeq"])
        if key in dataIndexs:
            # 数据重复次数+1
            datas[dataIndexs[key]]['re'] = datas[dataIndexs[key]]['re'] + 1
        else:
            # 数据重复次数默认为1
            datas.append({"key": key, "val": item, "re": 1})
            dataIndexs.setdefault(key, len(datas) - 1)
    # TODO 测试的时候开启,方便记录大单数据
    # l2_data_util.save_big_data(code, same_time_num, data)
    return datas
def get_format_l2_datas(code, origin_datas, limit_up_price):
    # 先转变数据格式
    datas = [__convert_order(x, limit_up_price) for x in origin_datas]
    return __format_l2_data(datas, code, limit_up_price)
l2/l2_data_manager_new.py
@@ -15,6 +15,7 @@
from db import redis_manager
import ths_industry_util
import tool
from l2.huaxin import l2_huaxin_util
from third_data.code_plate_key_manager import CodePlateKeyBuyManager
from trade import trade_manager, trade_queue_manager, l2_trade_factor, l2_trade_util, \
    trade_result_manager, first_code_score_manager
@@ -22,7 +23,7 @@
from l2.cancel_buy_strategy import SecondCancelBigNumComputer, HourCancelBigNumComputer, L2LimitUpMoneyStatisticUtil, \
    L2LimitUpSellStatisticUtil
from l2.l2_data_manager import L2DataException, TradePointManager
from l2.l2_data_util import local_today_datas, L2DataUtil, local_today_num_operate_map, local_latest_datas
from l2.l2_data_util import local_today_datas, L2DataUtil, local_today_num_operate_map,local_today_buyno_map, local_latest_datas
import l2.l2_data_util
from log import logger_l2_trade_buy, logger_l2_process, \
    logger_place_order_score
@@ -195,7 +196,9 @@
                    # 数据不正常需要禁止交易
                    l2_trade_util.forbidden_trade(code)
                # 纠正数据
                datas = l2.l2_data_util.L2DataUtil.correct_data(code, local_latest_datas.get(code), datas)
                if constant.L2_SOURCE_TYPE == constant.L2_SOURCE_TYPE_THS:
                    # 同花顺需要纠正数据,其他渠道不需要
                    datas = l2.l2_data_util.L2DataUtil.correct_data(code, local_latest_datas.get(code), datas)
                _start_index = 0
                if local_today_datas.get(code) is not None and len(
                        local_today_datas[code]) > 0:
@@ -224,6 +227,7 @@
            # 拼接数据
            local_today_datas[code].extend(add_datas)
            l2.l2_data_util.load_num_operate_map(local_today_num_operate_map, code, add_datas)
            l2.l2_data_util.load_buy_no_map(local_today_buyno_map, code, add_datas)
            # 第1条数据是否为09:30:00
            if add_datas[0]["val"]["time"] == "09:30:00":
l2/l2_data_source_util.py
@@ -19,13 +19,13 @@
        cls.__buy_and_cancel_map[code][buy_index] = cancel_index
    @classmethod
    def __get_cancel_index(cls, code, buy_index):
    def __get_cancel_index_cache(cls, code, buy_index):
        if code not in cls.__buy_and_cancel_map:
            return None
        return cls.__buy_and_cancel_map[code].get(buy_index)
    @classmethod
    def __get_buy_index(cls, code, cancel_index):
    def __get_buy_index_cache(cls, code, cancel_index):
        if code not in cls.__cancel_and_buy_map:
            return None
        return cls.__cancel_and_buy_map[code].get(cancel_index)
@@ -52,35 +52,33 @@
            # 小时
            return __time * 3600, (__time + 1) * 3600
    # 根据买撤数据(与今日总的数据)计算买入数据
    # 华鑫渠道的L2,根据买撤数据查找买入数据
    @classmethod
    def get_buy_index_with_cancel_data(cls, code, cancel_data, local_today_num_operate_map):
        key = "{}-{}-{}".format(cancel_data["val"]["num"], "1", cancel_data["val"]["price"])
        cancel_datas = local_today_num_operate_map.get(key)
        try:
            cancel_datas.sort(key=lambda t: t["index"])
        except Exception as e:
            print("测试")
        for item in cancel_datas:
            cls.__get_buy_index_with_cancel_data(code, item, local_today_num_operate_map)
        return cls.__get_buy_index_with_cancel_data(code, cancel_data, local_today_num_operate_map)
    @classmethod
    def __get_buy_index_with_cancel_data(cls, code, cancel_data, local_today_num_operate_map):
        buy_index = cls.__get_buy_index(code, cancel_data["index"])
        if buy_index is not None:
            return buy_index
        min_space, max_space = cls.__compute_time_space_as_second(cancel_data["val"]["cancelTime"],
                                                                  cancel_data["val"]["cancelTimeUnit"])
        max_time = tool.trade_time_add_second(cancel_data["val"]["time"], 0 - min_space)
        min_time = tool.trade_time_add_second(cancel_data["val"]["time"], 0 - max_space)
    def __get_buy_index_with_cancel_data_by_huaxin_l2(cls, code, cancel_data, local_today_num_operate_map):
        buy_datas = local_today_num_operate_map.get(
            "{}-{}-{}".format(cancel_data["val"]["num"], "0", cancel_data["val"]["price"]))
        if buy_datas is None:
            # 无数据
            return None
        # orderNo
        for bd in buy_datas:
            # 根据订单号做匹配
            if bd["val"]["orderNo"] == cancel_data["val"]["orderNo"]:
                return bd
        return None
    # 同花顺渠道的L2,根据买撤数据查找买入数据
    @classmethod
    def __get_buy_index_with_cancel_data_by_ths_l2(cls, code, cancel_data, local_today_num_operate_map):
        buy_datas = local_today_num_operate_map.get(
            "{}-{}-{}".format(cancel_data["val"]["num"], "0", cancel_data["val"]["price"]))
        if buy_datas is None:
            # 无数据
            return None
        min_space, max_space = cls.__compute_time_space_as_second(cancel_data["val"]["cancelTime"],
                                                                  cancel_data["val"]["cancelTimeUnit"])
        max_time = tool.trade_time_add_second(cancel_data["val"]["time"], 0 - min_space)
        min_time = tool.trade_time_add_second(cancel_data["val"]["time"], 0 - max_space)
        # 匹配到的index
        suit_indexes = []
        for i in range(0, len(buy_datas)):
@@ -91,7 +89,7 @@
            if int(data["val"]["num"]) != int(cancel_data["val"]["num"]):
                continue
                # 如果能找到对应的买撤就需要返回
            cancel_index = cls.__get_cancel_index(code, data["index"])
            cancel_index = cls.__get_cancel_index_cache(code, data["index"])
            if cancel_index is not None and cancel_index != cancel_data["index"]:
                continue
@@ -110,6 +108,55 @@
            return suit_indexes[0]
        return None
    @classmethod
    def __get_buy_index_with_cancel_data(cls, code, cancel_data, local_today_num_operate_map):
        buy_index = cls.__get_buy_index_cache(code, cancel_data["index"])
        if buy_index is not None:
            return buy_index
        return cls.__get_buy_index_with_cancel_data_by_ths_l2(code, cancel_data, local_today_num_operate_map)
    # 根据买撤数据(与今日总的数据)计算买入数据
    @classmethod
    def get_buy_index_with_cancel_data(cls, code, cancel_data, local_today_num_operate_map):
        key = "{}-{}-{}".format(cancel_data["val"]["num"], "1", cancel_data["val"]["price"])
        cancel_datas = local_today_num_operate_map.get(key)
        try:
            cancel_datas.sort(key=lambda t: t["index"])
        except Exception as e:
            print("测试")
        for item in cancel_datas:
            # 提前做计算
            cls.__get_buy_index_with_cancel_data(code, item, local_today_num_operate_map)
        return cls.__get_buy_index_with_cancel_data(code, cancel_data, local_today_num_operate_map)
    # 获取没撤的笔数
    @classmethod
    def get_limit_up_buy_no_canceled_count(cls, code, index, total_data, local_today_num_operate_map):
        data = None
        try:
            data = total_data[index]
        except:
            print("")
        val = data["val"]
        # 判断当前买是否已经买撤
        cancel_datas = local_today_num_operate_map.get(
            "{}-{}-{}".format(val["num"], "1", val["price"]))
        canceled = False
        if cancel_datas:
            for cancel_data in cancel_datas:
                buy_index = cls.get_buy_index_with_cancel_data(code, cancel_data, local_today_num_operate_map)
                if buy_index == index:
                    canceled = True
                    count = data["re"] - cancel_data["re"]
                    if count > 0:
                        return count
                    break
        if not canceled:
            count = data["re"]
            return count
        return 0
# if __name__ == "__main__":
#     code = "000925"
l2/l2_data_util.py
@@ -29,6 +29,9 @@
# 用于加快数据处理,用空换时间
local_today_num_operate_map = {}
# 买入订单号映射,只有原生的L2数据才有
local_today_buyno_map = {}
def load_l2_data(code, force=False):
    redis = _redisManager.getRedis()
@@ -66,6 +69,7 @@
        # local_today_datas[code] = new_datas
        # 根据今日数据加载
        load_num_operate_map(local_today_num_operate_map, code, local_today_datas.get(code), force)
        load_buy_no_map(local_today_buyno_map, code, local_today_datas.get(code), force)
        return data_normal
    return True
@@ -82,6 +86,26 @@
        if local_today_num_operate_map[code].get(key) is None:
            local_today_num_operate_map[code].setdefault(key, [])
        local_today_num_operate_map[code].get(key).append(data)
# 将数据根据orderNo分类,原生数据才有
def load_buy_no_map(local_today_buyno_map, code, source_datas, clear=False):
    # 只有原生L2数据才会有此操作
    if constant.L2_SOURCE_TYPE != constant.L2_SOURCE_TYPE_HUAXIN:
        return
    if local_today_buyno_map.get(code) is None:
        local_today_buyno_map[code] = {}
    if clear:
        local_today_buyno_map[code] = {}
    for data in source_datas:
        if data["val"]["operateType"] != 0:
            continue
        # 只填充买入数据
        key = "{}".format(data["val"]["orderNo"])
        if local_today_buyno_map[code].get(key) is None:
            local_today_buyno_map[code].setdefault(key, [])
        local_today_buyno_map[code].get(key).append(data)
@tool.async_call
@@ -138,7 +162,8 @@
            log.logger_l2_data.info("{}-{}", code, add_datas)
        except Exception as e:
            logging.exception(e)
        saveL2Data(code, add_datas)
        # 暂时不将数据保存到redis
        # saveL2Data(code, add_datas)
# 设置最新的l2数据采集的数量
@@ -280,7 +305,8 @@
                    # 保存到数据库,更新re的数据
                    save_list.append(_ldata)
        if len(save_list) > 0:
            saveL2Data(code, save_list, "保存纠正数据")
            # 暂时不将数据保存到redis
            # saveL2Data(code, save_list, "保存纠正数据")
            local_latest_datas[code] = latest_data
        return _datas
l2/l2_huaxin_util.py
File was deleted
l2_data_util.py
@@ -123,32 +123,6 @@
    return min_time, max_time
# 根据买撤数据(与今日总的数据)计算买入数据
def get_buy_data_with_cancel_data(cancel_data, local_today_num_operate_map):
    min_space, max_space = compute_time_space_as_second(cancel_data["val"]["cancelTime"],
                                                        cancel_data["val"]["cancelTimeUnit"])
    max_time = __sub_time(cancel_data["val"]["time"], min_space)
    min_time = __sub_time(cancel_data["val"]["time"], max_space)
    buy_datas = local_today_num_operate_map.get(
        "{}-{}-{}".format(cancel_data["val"]["num"], "0", cancel_data["val"]["price"]))
    if buy_datas is None:
        # 无数据
        return None, None
    for i in range(0, len(buy_datas)):
        data = buy_datas[i]
        if int(data["val"]["operateType"]) != 0:
            continue
        if int(data["val"]["num"]) != int(cancel_data["val"]["num"]):
            continue
        if min_space == 0 and max_space == 0:
            if compare_time(data["val"]["time"], min_time) == 0:
                return data["index"], data
        elif compare_time(data["val"]["time"], min_time) > 0 and compare_time(data["val"]["time"], max_time) <= 0:
            return data["index"], data
    return None, None
# 判断卖撤的卖信号是否在目标信号之前
def is_sell_index_before_target(sell_cancel_data, target_data, local_today_num_operate_map):
    min_space, max_space = compute_time_space_as_second(sell_cancel_data["val"]["cancelTime"],
server.py
@@ -24,7 +24,7 @@
import init
from l2 import l2_data_manager_new, l2_data_manager, l2_data_log, l2_log, code_price_manager
import l2_data_util
from l2.cancel_buy_strategy import HourCancelBigNumComputer, L2LimitUpMoneyStatisticUtil
from l2.cancel_buy_strategy import HourCancelBigNumComputer, L2LimitUpMoneyStatisticUtil, LCancelBigNumComputer
import l2.l2_data_util
import ths_industry_util
@@ -290,7 +290,8 @@
                                        codes.append(code)
                                        dataList.append(item)
                                        # 保存自由流通股本
                                        zyltgb_list.append({"code": code, "zyltgb": item["zyltgb"],"zyltgb_unit": item["zyltgbUnit"]})
                                        zyltgb_list.append(
                                            {"code": code, "zyltgb": item["zyltgb"], "zyltgb_unit": item["zyltgbUnit"]})
                                    else:
                                        # 获取涨停价
                                        _limit_up_price = gpcode_manager.get_limit_up_price(code)
@@ -379,7 +380,8 @@
                                                                     volumes_data)
                        gpcode_manager.FirstCodeManager.add_record(codes)
                        if new_add_codes:
                            gpcode_manager.set_first_gp_codes_with_data(HistoryKDatasUtils.get_gp_latest_info(codes,fields = "symbol,sec_name,sec_type,sec_level"))
                            gpcode_manager.set_first_gp_codes_with_data(HistoryKDatasUtils.get_gp_latest_info(codes,
                                                                                                              fields="symbol,sec_name,sec_type,sec_level"))
                            # 加入首板历史记录
                            logger_first_code_record.info("新增首板:{}", new_add_codes)
@@ -593,6 +595,10 @@
                                                                                            code),
                                                                                        l2.l2_data_util.local_today_num_operate_map.get(
                                                                                            code))
                                            LCancelBigNumComputer.set_trade_progress(code, buy_progress_index,
                                                                                     l2.l2_data_util.local_today_datas.get(
                                                                                         code))
                                            logger_l2_trade_buy_queue.info("获取成交位置成功: code-{} index-{}  数据-{}", code,
                                                                           buy_progress_index,
                                                                           json.dumps(buy_queue_result_list))
@@ -1124,7 +1130,7 @@
            volumes_data = volumes_data[1:]
            volumes = init.parse_max_volume(volumes_data[:60],
                                            code_nature_analyse.is_new_top(limit_up_price,
                                                                             volumes_data[:60]))
                                                                           volumes_data[:60]))
            logger_first_code_record.info("{} 获取到首板60天最大量:{}", code, volumes)
            code_volumn_manager.set_histry_volumn(code, volumes[0], volumes[1], volumes[2])
            # 判断K线形态
trade/huaxin/huaxin_transaction_manager.py
New file
@@ -0,0 +1,30 @@
"""
华鑫成交记录管理
"""
#
# buy_orderno_map 买入数据map
# 返回代码:成交进度数据的字典
def process(datas, total_buyno_map):
    buyno_dict = {}
    last_no_dict = {}
    for d in datas:
        code = d[0]
        if code not in buyno_dict:
            buyno_dict[code] = []
        if last_no_dict.get(code) == d[6]:
            continue
        last_no_dict[code] = d[6]
        buyno_dict[code].append(d[6])
    fresults_dict = {}
    for code in buyno_dict:
        if code not in total_buyno_map:
            continue
        buyno_list = buyno_dict[code]
        buyno_list.reverse()
        for b in buyno_list:
            if b in total_buyno_map[code]:
                fresults_dict[code] = total_buyno_map[code][b]
                break
    return fresults_dict
trade/trade_result_manager.py
@@ -4,7 +4,8 @@
import dask
from l2 import l2_data_manager
from l2.cancel_buy_strategy import HourCancelBigNumComputer, SecondCancelBigNumComputer, L2LimitUpSellStatisticUtil
from l2.cancel_buy_strategy import HourCancelBigNumComputer, SecondCancelBigNumComputer, L2LimitUpSellStatisticUtil, \
    LCancelBigNumComputer
from l2.l2_data_util import local_today_datas, local_today_num_operate_map
from l2.safe_count_manager import BuyL2SafeCountManager
from log import logger_l2_error
@@ -60,13 +61,22 @@
            logging.exception(e)
            logger_l2_error.exception(e)
    buy_single_index, buy_exec_index, buy_compute_index, num, count, max_num_set,volume_rate = l2_data_manager.TradePointManager.get_buy_compute_start_data(
    @dask.delayed
    def l_cancel(code):
        try:
            LCancelBigNumComputer.del_watch_index(code)
        except Exception as e:
            logging.exception(e)
            logger_l2_error.exception(e)
    buy_single_index, buy_exec_index, buy_compute_index, num, count, max_num_set, volume_rate = l2_data_manager.TradePointManager.get_buy_compute_start_data(
        code)
    f1 = clear_max_buy1_volume(code)
    f2 = safe_count(code, buy_single_index, buy_exec_index)
    f3 = h_cancel(code, buy_single_index, buy_exec_index)
    dask.compute(f1, f2, f3)
    f4 = l_cancel(code)
    dask.compute(f1, f2, f3, f4)
    l2_data_manager.TradePointManager.delete_buy_cancel_point(code)