Administrator
2023-12-21 81f328532e366eef171b71810b221a9294dda78f
买入条件调整/L撤调整
11个文件已修改
253 ■■■■■ 已修改文件
code_attribute/code_nature_analyse.py 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
code_attribute/first_target_code_data_processor.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
code_attribute/gpcode_manager.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/cancel_buy_strategy.py 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_manager_new.py 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/test_code_attribute.py 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
third_data/block_info.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
third_data/history_k_data_util.py 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/huaxin/huaxin_trade_server.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/trade_result_manager.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
code_attribute/code_nature_analyse.py
@@ -218,7 +218,8 @@
    # 是否具有辨识度
    p9 = is_special(record_datas)
    p10 = is_latest_10d_max_volume_at_latest_2d(record_datas)
    p11 = __is_yesterday_open_limit_up(record_datas)
    # 最近5天是否跌停/炸板
    p11 = __is_latest_open_limit_up_or_limit_down(record_datas, 5)
    # 30天内是否有涨停
    p12 = __has_limit_up(record_datas, 30)
@@ -476,15 +477,21 @@
    return False, ''
# 昨天是否炸板
def __is_yesterday_open_limit_up(datas):
# 最近几天是否有炸板或跌停
def __is_latest_open_limit_up_or_limit_down(datas, day_count):
    datas = copy.deepcopy(datas)
    datas.sort(key=lambda x: x["bob"])
    item = datas[-1]
    limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"]))
    if abs(limit_up_price - item["high"]) < 0.001 and abs(limit_up_price - item["close"]) > 0.001:
        # 炸板
        return True
    items = datas[0-day_count]
    for item in items:
        limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"]))
        if abs(limit_up_price - item["high"]) < 0.001 and abs(limit_up_price - item["close"]) > 0.001:
            # 炸板
            return True
        # 是否有跌停
        limit_down_price = float(gpcode_manager.get_limit_down_price_by_preprice(item["pre_close"]))
        if abs(limit_down_price - item["close"]) < 0.001:
            # 跌停
            return True
    return False
code_attribute/first_target_code_data_processor.py
@@ -22,6 +22,8 @@
def process_first_codes_datas(dataList, request_id=None):
    logger_l2_codes_subscript.info(f"{request_id}加载l2代码相关数据")
    print("首板代码数量:", len(dataList))
    # 获取最近5天的交易日期,为后面的数据计算做准备
    HistoryKDatasUtils.get_latest_trading_date_cache(5)
    limit_up_price_dict = {}
    temp_codes = []
    codes = []
code_attribute/gpcode_manager.py
@@ -763,6 +763,12 @@
    return tool.to_price(decimal.Decimal(str(price)) * decimal.Decimal("1.1"))
def get_limit_down_price_by_preprice(price):
    if price is None:
        return None
    return tool.to_price(decimal.Decimal(str(price)) * decimal.Decimal("0.9"))
# 获取跌停价
def get_limit_down_price(code):
    price = CodePrePriceManager.get_price_pre_cache(code)
l2/cancel_buy_strategy.py
@@ -35,6 +35,7 @@
    SecondCancelBigNumComputer().set_real_place_order_index(code, index)
    LCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index=buy_single_index)
    HourCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index)
    GCancelBigNumComputer().set_real_place_order_index(code, index)
class SecondCancelBigNumComputer:
@@ -686,7 +687,7 @@
                                                                                                             code))
                cancel_num += val['num'] * (data['re'] - left_count)
            rate = round(cancel_num / total_num, 4)
            must_buy_cancel_rate =  constant.H_CANCEL_RATE
            must_buy_cancel_rate = constant.H_CANCEL_RATE
            try:
                temp_rate = gpcode_manager.MustBuyCodesManager().get_cancel_rate_cache(code)
                if temp_rate:
@@ -834,7 +835,7 @@
            if must_buy_cancel_rate is not None:
                return must_buy_cancel_rate
        except Exception as e:
            async_log_util.error(logger_l2_l_cancel,str(e))
            async_log_util.error(logger_l2_l_cancel, str(e))
        base_rate = constant.L_CANCEL_RATE
        if is_up:
@@ -913,8 +914,6 @@
    __near_by_trade_progress_index_cache = {}
    __SecondCancelBigNumComputer = SecondCancelBigNumComputer()
    __last_l_up_compute_info = {}
@@ -1286,8 +1285,11 @@
        watch_indexes = set([int(i) for i in watch_indexes_info[2]])
        # 计算监听的总条数
        total_num = 0
        max_num = 0
        for wi in watch_indexes:
            total_num += total_data[wi]["val"]["num"] * total_data[wi]["re"]
            if total_data[wi]["val"]["num"] > max_num:
                max_num = total_data[wi]["val"]["num"]
        # 判断撤单中是否有监听中的索引
        need_compute = False
        for i in range(start_index, end_index + 1):
@@ -1324,6 +1326,9 @@
            rate = round(canceled_num / total_num, 3)
            thresh_hold_rate = LCancelRateManager.get_cancel_rate(code)
            # 除开最大单的影响权重
            temp_thresh_hold_rate = round((total_num - max_num)*0.9/total_num, 2)
            thresh_hold_rate = min(thresh_hold_rate, temp_thresh_hold_rate)
            l2_log.l_cancel_debug(code, f"计算范围:{start_index}-{end_index},已撤单比例:{rate}/{thresh_hold_rate}")
            if rate >= thresh_hold_rate:
                canceled_indexes.sort()
@@ -1452,7 +1457,7 @@
    def need_cancel(self, code, buy_exec_index, start_index, end_index, total_data, is_first_code):
        if buy_exec_index is None:
            return False, "尚未找到下单位置", ""
            return False, None, "尚未找到下单位置"
        # 守护S撤以外的数据
        if int(tool.get_now_time_str().replace(":", "")) > int("145700") and not constant.TEST:
            return False, None, ""
@@ -1666,38 +1671,52 @@
# ---------------------------------G撤-------------------------------
class GCancelBigNumComputer:
    __SecondCancelBigNumComputer = SecondCancelBigNumComputer()
    __real_place_order_index_dict = {}
    __instance = None
    # 开始撤单
    def start_cancel(self, code, buy_no, total_datas, m_val_num):
        # TODO 暂时注释掉G撤
        return False, "暂时不执行G撤"
        thresh_num = int(m_val_num * 1)
        place_order_index = self.__SecondCancelBigNumComputer.get_real_place_order_index_cache(code)
        if place_order_index is None:
            raise Exception("未获取到下单真实位置")
        buy_data = buy_order_no_map.get(buy_no)
        if not buy_data:
            raise Exception(f"尚未获取到撤买单详情数据: order_no:{buy_no} map数量:{len(buy_order_no_map)}")
        # 从成交位置到下单位置计算m值
        transaction_index = buy_data["index"]
        need_cancel = True
        buy_nums = 0
        for index in range(transaction_index + 1, place_order_index):
            data = total_datas[index]
            if L2DataUtil.is_limit_up_price_buy(data["val"]):
                # 获取是否在买入执行信号周围2s
                left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code, index,
                                                                                                         total_datas,
                                                                                                         local_today_canceled_buyno_map.get(
                                                                                                             code))
                if left_count > 0:
                    buy_nums += left_count * data["val"]["num"]
                    if buy_nums > thresh_num:
                        break
        if buy_nums > thresh_num:
            need_cancel = False
        return need_cancel, f"成交进度位({transaction_index})-真实下单位({place_order_index})  纯买手数:{buy_nums}/1.8倍m值手数:{thresh_num}"
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = super(GCancelBigNumComputer, cls).__new__(cls, *args, **kwargs)
        return cls.__instance
    def set_real_place_order_index(self, code, index):
        self.__real_place_order_index_dict[code] = index
    def clear(self, code=None):
        if code:
            if code in self.__real_place_order_index_dict:
                self.__real_place_order_index_dict.pop(code)
        else:
            self.__real_place_order_index_dict.clear()
    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 = self.__real_place_order_index_dict.get(code)
        total_datas = local_today_datas.get(code)
        # 30s内有效
        if tool.trade_time_sub(total_datas[end_index]["val"]["time"], total_datas[buy_exec_index]["val"]["time"]) > 30:
            return False, None, "下单30s内才生效"
        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"]) < 30000:
                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:
                return True, data, ""
        return False, None, ""
    def place_order_success(self, code):
        self.clear(code)
    def cancel_success(self, code):
        self.clear(code)
# ---------------------------------独苗撤-------------------------------
l2/l2_data_manager_new.py
@@ -12,7 +12,8 @@
from l2.l2_sell_manager import L2MarketSellManager, L2LimitUpSellManager
from l2.transaction_progress import TradeBuyQueue
from log_module import async_log_util, log_export
from third_data import kpl_data_manager, block_info
from third_data import kpl_data_manager, block_info, history_k_data_util
from third_data.history_k_data_util import HistoryKDatasUtils
from utils import global_util, ths_industry_util, tool
import l2_data_util
from db import redis_manager_delegate as redis_manager
@@ -22,7 +23,7 @@
from l2 import l2_data_manager, l2_log, l2_data_source_util, code_price_manager, \
    transaction_progress, cancel_buy_strategy, l2_data_log
from l2.cancel_buy_strategy import SecondCancelBigNumComputer, HourCancelBigNumComputer, DCancelBigNumComputer, \
    LCancelBigNumComputer, LatestCancelIndexManager, FastCancelBigNumComputer, LCancelRateManager
    LCancelBigNumComputer, LatestCancelIndexManager, FastCancelBigNumComputer, LCancelRateManager, GCancelBigNumComputer
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
@@ -221,6 +222,7 @@
    __SecondCancelBigNumComputer = SecondCancelBigNumComputer()
    __HourCancelBigNumComputer = HourCancelBigNumComputer()
    __LCancelBigNumComputer = LCancelBigNumComputer()
    __GCancelBigNumComputer = GCancelBigNumComputer()
    __TradeStateManager = trade_manager.TradeStateManager()
    __CodesTradeStateManager = trade_manager.CodesTradeStateManager()
    __PauseBuyCodesManager = gpcode_manager.PauseBuyCodesManager()
@@ -557,6 +559,25 @@
                pass
            return None, ""
        # G撤
        def g_cancel(_buy_single_index, _buy_exec_index):
            try:
                b_need_cancel, b_cancel_data, extra_msg = cls.__GCancelBigNumComputer.need_cancel(code,
                                                                                                  _buy_exec_index,
                                                                                                  start_index,
                                                                                                  end_index)
                if b_need_cancel and b_cancel_data:
                    return b_cancel_data, f"G撤({extra_msg})"
            except Exception as e:
                async_log_util.error(logger_l2_error,
                                     f"G撤出错 参数:buy_single_index-{_buy_single_index} buy_exec_index-{_buy_exec_index} 错误原因:{str(e)}")
                # logger_l2_error.exception(e)
                async_log_util.exception(logger_l2_error, e)
            finally:
                # l2_data_log.l2_time(code, round(t.time() * 1000) - _start_time, "已下单-L撤大单计算")
                pass
            return None, ""
        if start_index < 0:
            start_index = 0
@@ -573,6 +594,9 @@
        cancel_data, cancel_msg = None, ""
        if order_begin_pos.mode == OrderBeginPosInfo.MODE_FAST:
            cancel_data, cancel_msg = f_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index)
        if not cancel_data:
            cancel_data, cancel_msg = g_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index)
        # 依次处理
        if not cancel_data:
@@ -942,8 +966,6 @@
        # if cls.__TradeTargetCodeModeManager.get_mode_cache() == TradeTargetCodeModeManager.MODE_ONLY_BUY_WANT_CODES:
        #     return False, True, f"只买想买单中的代码"
        if HighIncreaseCodeManager().is_in(code):
            return False, True, f"涨幅过高,5天内3次涨停"
        return cls.can_buy_first(code, limit_up_price)
        # else:
        #     return True, False, "在想买名单中"
@@ -980,15 +1002,29 @@
            if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.6:
                return False, True, f"股价创新高或者逼近前高且30天内有涨停,当日量比({cls.volume_rate_info[code][0]})小于0.6"
        # 前一天炸板之后,今日10:00之前才能下单
        # 上5个交易日有炸板/跌停之后
        if k_format and len(k_format) >= 11 and k_format[10]:
            if now_timestamp > int("100000"):
                return False, True, f"上个交易日炸板,当日10点以后不下单"
            if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.6:
                return False, True, f"上5个交易日炸板/跌停,量未达到60%({cls.volume_rate_info[code][0]})"
        # 获取量的参考日期
        if code in global_util.max60_volumn:
            day = global_util.max60_volumn[code][1]
            if day in HistoryKDatasUtils.get_latest_trading_date_cache(5):
                if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.6:
                    return False, True, f"参考量在最近5天,量未达到60%({cls.volume_rate_info[code][0]})"
        zyltgb = global_util.zyltgb_map.get(code)
        if zyltgb >= 40 * 100000000:
            return False, True, f"40亿以上的都不买({zyltgb})"
        if HighIncreaseCodeManager().is_in(code):
            if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.8:
                return False, True, f"5天内3次涨停,量未达到80%({cls.volume_rate_info[code][0]})"
        msg_list = []
        if can_buy_result[3] and now_timestamp <= int("094000"):
        if now_timestamp <= int("094000"):
            msg_list.append("强势10分钟")
            zyltgb = global_util.zyltgb_map.get(code)
            # 独苗
            if not can_buy_result[0] and can_buy_result[1]:
                msg_list.append("独苗")
@@ -1019,7 +1055,6 @@
                    return True, False, can_buy_result[2]
            return True, False, can_buy_result[2]
        else:
            zyltgb = global_util.zyltgb_map.get(code)
            # 非强势10分钟只买主线
            if not can_buy_result[0] and can_buy_result[1]:
                return False, True, f"非强势10分钟,独苗不下单"
server.py
@@ -593,7 +593,7 @@
                    day = tool.get_now_date_str()
                    data_dict = {}
                    for i in range(0, 2):
                        day = HistoryKDatasUtils.get_previous_trading_date(day)
                        day = HistoryKDatasUtils.get_previous_trading_date_cache(day)
                        data_list = list(block_info.KPLLimitUpDataRecordManager.list_all(day))
                        codes_set = set()
                        if data_list:
test/test_code_attribute.py
@@ -10,15 +10,21 @@
if __name__ == "__main__":
    code_str = "603178"
    code_str = "002861"
    codes = code_str.split(",")
    for code in codes:
        if not tool.is_shsz_code(code):
            continue
        try:
            datas = init_data_util.get_volumns_by_code(code, 120)
            result = is_too_high(datas)
            if result:
                print(code, result)
            limit_up_price = 16.96
            volumes_data = init_data_util.get_volumns_by_code(code, 150)
            volumes_data = volumes_data[1:]
            volumes = init_data_util.parse_max_volume(volumes_data[:90],
                                                      code_nature_analyse.is_new_top(
                                                          limit_up_price,
                                                          volumes_data[:90]) or code_nature_analyse.is_near_top(
                                                          limit_up_price,
                                                          volumes_data[:90]))
            print(volumes)
        except:
            print(code, "出错")
third_data/block_info.py
@@ -69,7 +69,7 @@
    if now_day in __blocks_dict:
        return __blocks_dict[now_day]
    now_date = datetime.datetime.now()
    end_date = HistoryKDatasUtils.get_previous_trading_date(tool.get_now_date_str())
    end_date = HistoryKDatasUtils.get_previous_trading_date_cache(tool.get_now_date_str())
    start_date = now_date - datetime.timedelta(days=(day_count * 2 + 10))
    start_date = start_date.strftime("%Y-%m-%d")
    days = HistoryKDatasUtils.get_trading_dates(start_date, end_date)
third_data/history_k_data_util.py
@@ -11,6 +11,8 @@
from db.redis_manager_delegate import RedisUtils
from utils import tool, middle_api_protocol
from db import redis_manager_delegate as redis_manager
# import gm.api as gmapi
@@ -194,7 +196,8 @@
class HistoryKDatasUtils(object):
    __previous_trading_date_cache={}
    __previous_trading_date_cache = {}
    __latest_trading_date_cache = {}
    @classmethod
    def get_gp_latest_info(cls, codes, fields=None):
@@ -221,6 +224,26 @@
        if fdata:
            cls.__previous_trading_date_cache[date] = fdata
        return fdata
    # 获取最近的交易日
    @classmethod
    def get_latest_trading_date(cls, day_count):
        now_day = tool.get_now_date_str()
        days = []
        for i in range(day_count):
            pday = cls.get_previous_trading_date_cache(now_day)
            days.append(pday)
            now_day = pday
        return days
    @classmethod
    def get_latest_trading_date_cache(cls, day_count):
        key = f"{tool.get_now_date_str()}-{day_count}"
        if key in cls.__latest_trading_date_cache:
            return cls.__latest_trading_date_cache[key]
        days = cls.get_latest_trading_date(day_count)
        cls.__latest_trading_date_cache[key] = days
        return days
    # 返回指定日期的下个交易日
    @classmethod
@@ -285,4 +308,9 @@
if __name__ == "__main__":
    constant.JUEJIN_LOCAL_API = False
    print(HistoryKDatasUtils.get_lowest_price_rate("000725", 30))
    print(tool.get_now_time_str())
    print(HistoryKDatasUtils.get_latest_trading_date(5))
    print(tool.get_now_time_str())
    print(HistoryKDatasUtils.get_latest_trading_date(5))
    print(tool.get_now_time_str())
    print(HistoryKDatasUtils.get_latest_trading_date(5))
trade/huaxin/huaxin_trade_server.py
@@ -464,18 +464,6 @@
        if limit_up_price:
            rate = round(total_deal_nums / (thresh_hold_money // (float(limit_up_price) * 100)), 2)
            LCancelRateManager().set_big_num_deal_rate(code, rate)
        try:
            need_cancel, msg = cls.__GCancelBigNumComputer.start_cancel(code, f"{order_no}",
                                                                        l2_data_util.local_today_datas.get(
                                                                            code), m_val_num)
            if need_cancel:
                # 需要撤单
                l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, "G撤撤单", "G撤")
                async_log_util.info(logger_l2_g_cancel, f"{code}-需要撤单:{msg}")
            else:
                async_log_util.info(logger_l2_g_cancel, f"{code}-不需要撤单:{msg}")
        except Exception as e:
            async_log_util.error(logger_l2_g_cancel, f"{code}-撤单异常:{str(e)}")
    @classmethod
    def test_sell(cls):
trade/trade_result_manager.py
@@ -3,7 +3,7 @@
from l2 import l2_data_manager
from l2.cancel_buy_strategy import HourCancelBigNumComputer, SecondCancelBigNumComputer, \
    LCancelBigNumComputer, DCancelBigNumComputer, FastCancelBigNumComputer
    LCancelBigNumComputer, DCancelBigNumComputer, FastCancelBigNumComputer, GCancelBigNumComputer
from l2.l2_data_manager import OrderBeginPosInfo
from l2.l2_data_util import local_today_datas, local_today_num_operate_map
from l2.l2_sell_manager import L2MarketSellManager
@@ -29,6 +29,7 @@
    SecondCancelBigNumComputer().cancel_success(code)
    DCancelBigNumComputer().cancel_success(code)
    LCancelBigNumComputer().cancel_success(code)
    GCancelBigNumComputer().cancel_success(code)
    # dask.compute(f1, f2, f5, f6, f7, f8)
@@ -67,6 +68,13 @@
            logging.exception(e)
            logger_l2_error.exception(e)
    def g_cancel(code):
        try:
            GCancelBigNumComputer().place_order_success(code)
        except Exception as e:
            logging.exception(e)
            logger_l2_error.exception(e)
    order_begin_pos = tradePointManager.get_buy_compute_start_data_cache(
        code)
@@ -75,6 +83,7 @@
    # H撤暂时不生效
    h_cancel(code, order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index)
    l_cancel(code)
    g_cancel(code)
    if order_begin_pos.mode == OrderBeginPosInfo.MODE_FAST:
        f_cancel(code)
        # 记录卖盘统计时间被用
@@ -92,6 +101,7 @@
    DCancelBigNumComputer().cancel_success(code)
    LCancelBigNumComputer().cancel_success(code)
    FastCancelBigNumComputer().cancel_success(code)
    GCancelBigNumComputer().cancel_success(code)
if __name__ == "__main__":