| | |
| | | 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 utils import global_util, ths_industry_util, tool |
| | | 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, buy_condition_util |
| | | import l2_data_util |
| | | from db import redis_manager_delegate as redis_manager |
| | | from third_data.code_plate_key_manager import CodePlateKeyBuyManager, KPLCodeJXBlockManager, LimitUpCodesPlateKeyManager |
| | |
| | | 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, 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 |
| | | import l2.l2_data_util |
| | | from log_module.log import logger_l2_trade_buy, logger_l2_process, logger_l2_error, logger_debug |
| | | from log_module.log import logger_l2_trade_buy, logger_l2_process, logger_l2_error, logger_debug, \ |
| | | logger_l2_not_buy_reasons |
| | | |
| | | from trade.trade_data_manager import CodeActualPriceProcessor, PlaceOrderCountManager |
| | | |
| | | from trade.trade_manager import TradeTargetCodeModeManager, AccountAvailableMoneyManager |
| | | from trade.trade_manager import TradeTargetCodeModeManager, AccountAvailableMoneyManager, MarketSituationManager |
| | | |
| | | |
| | | class L2DataManager: |
| | |
| | | __SecondCancelBigNumComputer = SecondCancelBigNumComputer() |
| | | __HourCancelBigNumComputer = HourCancelBigNumComputer() |
| | | __LCancelBigNumComputer = LCancelBigNumComputer() |
| | | __GCancelBigNumComputer = GCancelBigNumComputer() |
| | | __TradeStateManager = trade_manager.TradeStateManager() |
| | | __CodesTradeStateManager = trade_manager.CodesTradeStateManager() |
| | | __PauseBuyCodesManager = gpcode_manager.PauseBuyCodesManager() |
| | |
| | | __AccountAvailableMoneyManager = AccountAvailableMoneyManager() |
| | | __TradeBuyDataManager = trade_data_manager.TradeBuyDataManager() |
| | | __LimitUpTimeManager = limit_up_time_manager.LimitUpTimeManager() |
| | | __BlackListCodeManager = l2_trade_util.BlackListCodeManager() |
| | | __WhiteListCodeManager = l2_trade_util.WhiteListCodeManager() |
| | | __BlackListCodeManager = gpcode_manager.BlackListCodeManager() |
| | | __WhiteListCodeManager = gpcode_manager.WhiteListCodeManager() |
| | | __WantBuyCodesManager = gpcode_manager.WantBuyCodesManager() |
| | | __TradeTargetCodeModeManager = TradeTargetCodeModeManager() |
| | | __TradeOrderIdManager = trade_huaxin.TradeOrderIdManager() |
| | |
| | | __L2MarketSellManager = L2MarketSellManager() |
| | | __L2LimitUpSellManager = L2LimitUpSellManager() |
| | | __PlaceOrderCountManager = PlaceOrderCountManager() |
| | | __CodeNatureRecordManager = code_nature_analyse.CodeNatureRecordManager() |
| | | __MarketSituationManager = MarketSituationManager() |
| | | |
| | | # 获取代码评分 |
| | | @classmethod |
| | |
| | | @classmethod |
| | | def set_real_place_order_index(cls, code, index, order_begin_pos: OrderBeginPosInfo): |
| | | trade_record_log_util.add_real_place_order_position_log(code, index, order_begin_pos.buy_single_index) |
| | | if order_begin_pos.mode == OrderBeginPosInfo.MODE_FAST: |
| | | need_cancel = FastCancelBigNumComputer().set_real_order_index(code, index) |
| | | if need_cancel: |
| | | l2_log.debug(code, "触发撤单,撤单位置:{} ,撤单原因:{}", index, "F撤不够2笔触发撤单") |
| | | cls.cancel_buy(code, msg="F撤不够2笔触发撤单") |
| | | return |
| | | l2_log.debug(code, "设置真实下单位:{}", index) |
| | | cancel_buy_strategy.set_real_place_position(code, index, order_begin_pos.buy_single_index) |
| | | |
| | |
| | | # __start_time = l2_data_log.l2_time(code, round(t.time() * 1000) - __start_time, |
| | | # "l2数据预处理时间") |
| | | |
| | | if len(add_datas) > 0: |
| | | # 9:29:55开始处理数据 |
| | | if len(add_datas) > 0 and int(tool.get_now_time_str().replace(":", "")) > int("092955"): |
| | | # 是否为首板代码 |
| | | is_first_code = True # gpcode_manager.FirstCodeManager().is_in_first_record(code) |
| | | # 计算量 |
| | |
| | | pass |
| | | return None, "" |
| | | |
| | | # F撤 |
| | | def f_cancel(_buy_single_index, _buy_exec_index): |
| | | try: |
| | | b_need_cancel, b_cancel_data = FastCancelBigNumComputer().need_cancel(code, start_index, end_index, |
| | | order_begin_pos) |
| | | if b_need_cancel and b_cancel_data: |
| | | return b_cancel_data, f"F撤" |
| | | except Exception as e: |
| | | if constant.TEST: |
| | | logging.exception(e) |
| | | async_log_util.error(logger_l2_error, |
| | | f"F撤出错 参数:buy_single_index-{_buy_single_index} buy_exec_index-{_buy_exec_index} 错误原因:{str(e)}") |
| | | async_log_util.exception(logger_l2_error, e) |
| | | return None, "" |
| | | |
| | | # L撤 |
| | | def l_cancel(_buy_single_index, _buy_exec_index): |
| | | _start_time = round(t.time() * 1000) |
| | |
| | | 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 |
| | | |
| | |
| | | if order_begin_pos.buy_volume_rate is None: |
| | | buy_volume_rate = 0.2 |
| | | 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: |
| | |
| | | info.set_kpl_blocks(list(jx_blocks_by)) |
| | | else: |
| | | info.set_kpl_blocks([]) |
| | | |
| | | can_buy_result = CodePlateKeyBuyManager.can_buy(code) |
| | | if can_buy_result: |
| | | if not can_buy_result[0] and can_buy_result[1]: |
| | | info.set_kpl_match_blocks(["独苗"]) |
| | | elif not can_buy_result[0] and not can_buy_result[1]: |
| | | info.set_kpl_match_blocks(["非独苗不满足身位"]) |
| | | else: |
| | | info.set_kpl_match_blocks(can_buy_result[0]) |
| | | trade_record_log_util.add_place_order_log(code, info) |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_error, f"加入买入记录日志出错:{str(e)}") |
| | |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | |
| | | if float(limit_up_price) >= constant.MAX_CODE_PRICE: |
| | | HighIncreaseCodeManager().add_code(code) |
| | | # HighIncreaseCodeManager().add_code(code) |
| | | return False, True, f"股价大于{constant.MAX_CODE_PRICE}块" |
| | | |
| | | place_order_count = cls.__PlaceOrderCountManager.get_place_order_count(code) |
| | | if place_order_count and place_order_count >= 10: |
| | | l2_trade_util.forbidden_trade(code, msg="当日下单次数已达10次") |
| | | return False, True, f"当日下单次数已达10次" |
| | | # place_order_count = cls.__PlaceOrderCountManager.get_place_order_count(code) |
| | | # if place_order_count and place_order_count >= 10: |
| | | # l2_trade_util.forbidden_trade(code, msg="当日下单次数已达10次") |
| | | # return False, True, f"当日下单次数已达10次" |
| | | |
| | | # ---------均价约束------------- |
| | | average_rate = cls.__Buy1PriceManager.get_average_rate(code) |
| | | if average_rate and average_rate <= 0.01: |
| | | return False, True, f"均价涨幅({average_rate})小于1%" |
| | | |
| | | # -------量的约束-------- |
| | | if cls.volume_rate_info[code][0] < 0.2: |
| | | return False, True, f"当日量比({cls.volume_rate_info[code][0]})小于0.2" |
| | | k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) |
| | | if k_format and (k_format[1][0] or k_format[3][0]): |
| | | # 股价创新高或者逼近前高 |
| | | if cls.volume_rate_info[code][0] < 0.3: |
| | | return False, True, f"股价创新高或者逼近前高,当日量比({cls.volume_rate_info[code][0]})小于0.3" |
| | | if code_nature_analyse.LatestMaxVolumeManager().is_latest_max_volume(code): |
| | | # 最近几天有最大量,判断量比是否大于60% |
| | | if cls.volume_rate_info[code][0] < 0.6: |
| | | HighIncreaseCodeManager().add_code(code) |
| | | return False, True, f"近日出现最大量,当日量比({cls.volume_rate_info[code][0]})小于0.6" |
| | | |
| | | # ------自由流通市值约束------ |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb: |
| | | if zyltgb < 10 * 100000000: |
| | | return False, True, f"自由流通小于10亿({zyltgb})" |
| | | |
| | | total_data = local_today_datas.get(code) |
| | | if constant.L2_SOURCE_TYPE == constant.L2_SOURCE_TYPE_HUAXIN: |
| | |
| | | return False, True, f"自由流通200亿以上,买1剩余档数大于10档,买一({buy1_price})涨停({limit_up_price})" |
| | | |
| | | open_limit_up_lowest_price = cls.__Buy1PriceManager.get_open_limit_up_lowest_price(code) |
| | | price_pre_close = gpcode_manager.CodePrePriceManager.get_price_pre_cache(code) |
| | | if open_limit_up_lowest_price and ( |
| | | float(open_limit_up_lowest_price) - price_pre_close) / price_pre_close < 0.05: |
| | | return False, True, f"炸板后最低价跌至5%以下" |
| | | # price_pre_close = gpcode_manager.CodePrePriceManager.get_price_pre_cache(code) |
| | | # if open_limit_up_lowest_price and ( |
| | | # float(open_limit_up_lowest_price) - price_pre_close) / price_pre_close < 0.05: |
| | | # return False, True, f"炸板后最低价跌至5%以下" |
| | | |
| | | # 回封的票,下13:15买入需要判断板块是否为独苗 |
| | | if open_limit_up_lowest_price and int(total_data[-1]["val"]["time"].replace(":", "")) > 131500: |
| | | # 获取当前票的涨停原因 |
| | | if code in LimitUpCodesPlateKeyManager.today_total_limit_up_reason_dict: |
| | | limit_up_reason = kpl_data_manager.KPLLimitUpDataRecordManager.get_current_block(code) |
| | | if limit_up_reason and limit_up_reason not in constant.KPL_INVALID_BLOCKS: |
| | | # 判断是否是独苗 |
| | | codes = kpl_data_manager.KPLLimitUpDataRecordManager.get_current_codes_by_block(limit_up_reason) |
| | | if codes: |
| | | codes = copy.deepcopy(codes) |
| | | codes.discard(code) |
| | | if not codes: |
| | | return False, True, f"13:15以后炸板之后下单,({limit_up_reason}) 为独苗" |
| | | |
| | | # limit_up_info = cls.__Buy1PriceManager.get_limit_up_info(code) |
| | | # if limit_up_info[0] is None and False: |
| | | # total_data = local_today_datas.get(code) |
| | | # buy_single_index, buy_exec_index, buy_compute_index, num, count, max_num_set, buy_volume_rate = cls.__get_order_begin_pos( |
| | | # code) |
| | | # # 之前没有涨停过 |
| | | # # 统计买入信号位到当前位置没有撤的大单金额 |
| | | # min_money_w = l2_data_util.get_big_money_val(float(total_data[buy_single_index]["val"]["price"])) // 10000 |
| | | # left_big_num = cls.__SecondCancelBigNumComputer.compute_left_big_num(code, |
| | | # buy_single_index, |
| | | # buy_exec_index, |
| | | # total_data[-1][ |
| | | # "index"], |
| | | # total_data, |
| | | # 0, min_money_w) |
| | | # if left_big_num > 0: |
| | | # # 重新获取分数与分数索引 |
| | | # limit_up_time = cls.__LimitUpTimeManager.get_limit_up_time_cache(code) |
| | | # if limit_up_time is None: |
| | | # limit_up_time = tool.get_now_time_str() |
| | | |
| | | # logger_place_order_score.info("code={},data='score_index':{},'score_info':{}", code, |
| | | # cls.__l2PlaceOrderParamsManagerDict[code].score_index, |
| | | # cls.__l2PlaceOrderParamsManagerDict[code].score_info) |
| | | |
| | | # if open_limit_up_lowest_price and int(total_data[-1]["val"]["time"].replace(":", "")) > 131500: |
| | | # # 获取当前票的涨停原因 |
| | | # if code in LimitUpCodesPlateKeyManager.today_total_limit_up_reason_dict: |
| | | # limit_up_reason = kpl_data_manager.KPLLimitUpDataRecordManager.get_current_block(code) |
| | | # if limit_up_reason and limit_up_reason not in constant.KPL_INVALID_BLOCKS: |
| | | # # 判断是否是独苗 |
| | | # codes = kpl_data_manager.KPLLimitUpDataRecordManager.get_current_codes_by_block(limit_up_reason) |
| | | # if codes: |
| | | # codes = copy.deepcopy(codes) |
| | | # codes.discard(code) |
| | | # if not codes: |
| | | # return False, True, f"13:15以后炸板之后下单,({limit_up_reason}) 为独苗" |
| | | # 暂时注释想买单功能 |
| | | if not cls.__WantBuyCodesManager.is_in_cache(code): |
| | | if cls.__TradeTargetCodeModeManager.get_mode_cache() == TradeTargetCodeModeManager.MODE_ONLY_BUY_WANT_CODES: |
| | | return False, True, f"只买想买单中的代码" |
| | | score_index = None # cls.__l2PlaceOrderParamsManagerDict[code].score_index |
| | | score = None # cls.__l2PlaceOrderParamsManagerDict[code].score |
| | | score_info = None # cls.__l2PlaceOrderParamsManagerDict[code].score_info |
| | | |
| | | # lp = LineProfiler() |
| | | # lp.enable() |
| | | # lp_wrap = lp(cls.can_buy_first) |
| | | # results = lp_wrap(code, limit_up_price, score_index, score, score_info, cls.volume_rate_info[code]) |
| | | # output = io.StringIO() |
| | | # lp.print_stats(stream=output) |
| | | # lp.disable() |
| | | # with open(f"{constant.get_path_prefix()}/logs/profile/{code}_can_buy_first.txt", 'w') as f: |
| | | # f.write(output.getvalue()) |
| | | # return results |
| | | # if cls.__TradeTargetCodeModeManager.get_mode_cache() == TradeTargetCodeModeManager.MODE_ONLY_BUY_WANT_CODES: |
| | | # return False, True, f"只买想买单中的代码" |
| | | return cls.can_buy_first(code, limit_up_price) |
| | | else: |
| | | return True, False, "在想买名单中" |
| | | return True, False, "在想买单中" |
| | | |
| | | # 获取可以买的板块 |
| | | @classmethod |
| | | def can_buy_first(cls, code, limit_up_price): |
| | | # 判断板块 |
| | | def __get_can_buy_block(cls, code): |
| | | can_buy_result = CodePlateKeyBuyManager.can_buy(code) |
| | | if can_buy_result is None: |
| | | async_log_util.warning(logger_debug, "没有获取到板块缓存,将获取板块") |
| | | yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes() |
| | | latest_current_limit_up_records = kpl_data_manager.get_latest_current_limit_up_records() |
| | | CodePlateKeyBuyManager.update_can_buy_blocks(code, |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.latest_origin_datas, |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.total_datas, |
| | | yesterday_codes, |
| | | latest_current_limit_up_records, |
| | | block_info.get_before_blocks_dict(), |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.get_current_reason_codes_dict()) |
| | | can_buy_result = CodePlateKeyBuyManager.can_buy(code) |
| | | return can_buy_result |
| | | |
| | | @classmethod |
| | | def can_buy_first(cls, code, limit_up_price): |
| | | now_timestamp = int(tool.get_now_time_str().replace(":", "")) |
| | | # 判断板块 |
| | | # (可以买的板块列表, 是否是独苗, 消息简介,可买的强势主线, 板块关键词) |
| | | can_buy_result = cls.__get_can_buy_block(code) |
| | | l2_log.debug(code, "获取到的板块信息:{}", can_buy_result) |
| | | if can_buy_result is None: |
| | | return False, True, "尚未获取到板块信息" |
| | | # -------量的约束-------- |
| | | volume_rate_thresholds = buy_condition_util.get_volume_rate_by_level( |
| | | 1), buy_condition_util.get_volume_rate_by_level(2) |
| | | |
| | | if can_buy_result[1]: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.6: |
| | | return False, True, f"独苗:量比({cls.volume_rate_info[code][0]})未达到60%" |
| | | |
| | | # 获取K线形态,判断是否近2天是否为10天内最大量 |
| | | k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) |
| | | if k_format and len(k_format) >= 10 and k_format[9]: |
| | | # 是独苗 |
| | | if cls.volume_rate_info[code][0] < 0.3: |
| | | return False, True, f"近2天有10日内最高量,量比({cls.volume_rate_info[code][0]})未达到30%" |
| | | # 是独苗 |
| | | if can_buy_result[1]: |
| | | now_time_int = int(tool.get_now_time_str().replace(":", "")) |
| | | if now_time_int < int("100000") or int("130000") <= now_time_int < int("133000"): |
| | | # 独苗必须9:30-10:00和13:00-13:30时间段内买 |
| | | return True, False, f"独苗:{can_buy_result[2]}" |
| | | # 是否有辨识度 |
| | | is_special = True if k_format and k_format[8][0] else False |
| | | # 上5个交易日有炸板之后 |
| | | has_open_limit_up_in_5 = True if k_format and len(k_format) >= 11 and k_format[10] else False |
| | | # 上5个交易日有跌停 |
| | | has_limit_down_in_5 = True if k_format and len(k_format) >= 13 and k_format[12] else False |
| | | # 是否是强势10分钟 |
| | | is_in_strong_time = now_timestamp <= int("094000") |
| | | # 是否是强势30分钟 |
| | | is_in_strong_time_30 = now_timestamp <= int("100000") |
| | | |
| | | # 量参考是否在最近30天 |
| | | # is_refer_volume_date_in_30_days = False |
| | | # try: |
| | | # volume_refer_date, volume_refer_date_distance = code_volumn_manager.get_volume_refer_date(code) |
| | | # if volume_refer_date_distance < 30: |
| | | # is_refer_volume_date_in_30_days = True |
| | | # except: |
| | | # pass |
| | | |
| | | # 获取市场行情 |
| | | situation = cls.__MarketSituationManager.get_situation_cache() |
| | | zylt_threshold_as_yi = buy_condition_util.get_zyltgb_threshold(situation) |
| | | zyltgb_as_yi = round(global_util.zyltgb_map.get(code) / 100000000, 2) |
| | | |
| | | if zyltgb_as_yi >= zylt_threshold_as_yi[1]: |
| | | return False, True, f"{zylt_threshold_as_yi[1]}亿以上的都不买({zyltgb_as_yi})" |
| | | |
| | | if zyltgb_as_yi < zylt_threshold_as_yi[0]: |
| | | return False, True, f"{zylt_threshold_as_yi[0]}亿以下的都不买({zyltgb_as_yi})" |
| | | |
| | | # 最优市值 |
| | | is_best_zylt = True if zylt_threshold_as_yi[4] <= zyltgb_as_yi <= zylt_threshold_as_yi[5] else False |
| | | |
| | | if is_special: |
| | | # 具有辨识度,算作最优市值 |
| | | zyltgb_as_yi = zylt_threshold_as_yi[2] + 1 |
| | | |
| | | # 是否是最优自由流通市值 |
| | | is_better_zylt = True if zylt_threshold_as_yi[2] <= zyltgb_as_yi <= zylt_threshold_as_yi[3] else False |
| | | |
| | | if is_in_strong_time_30 and is_best_zylt and can_buy_result[0]: |
| | | # 强势30分钟,最优市值, 有可以下单的板块,不看量 |
| | | return True, False, can_buy_result[2] |
| | | |
| | | if k_format and (k_format[1][0] or k_format[3][0]) and len(k_format) >= 12 and k_format[11]: |
| | | # 破前高/接近前高且30天内有涨停 |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[1]: |
| | | return False, True, f"股价创新高或者逼近前高且30天内有涨停,当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[1]}" |
| | | |
| | | 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 is_in_strong_time: |
| | | msg_list.append("强势10分钟") |
| | | # 上5个交易日有炸板之后 |
| | | if has_open_limit_up_in_5: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.15: |
| | | return False, True, f"强势10分钟,上5个交易日炸板,量未达到{0.15}({cls.volume_rate_info[code][0]})" |
| | | |
| | | # 上5个交易日有跌停 |
| | | if has_limit_down_in_5: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.15: |
| | | return False, True, f"强势10分钟,上5个交易日跌停,量未达到{0.15}({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.15 and not is_special: |
| | | return False, True, f"强势10分钟,参考量在最近5天,无辨识度,量未达到0.15({cls.volume_rate_info[code][0]})" |
| | | |
| | | # 独苗 |
| | | if not can_buy_result[0] and can_buy_result[1]: |
| | | msg_list.append("独苗") |
| | | if not is_best_zylt: |
| | | # 如果没有辨识度才不买 |
| | | if not is_special: |
| | | return False, True, f"强势10分钟,无辨识度, 独苗({can_buy_result[4]})不下单({can_buy_result[4]})自由流通市值({zyltgb_as_yi})不是特优市值" |
| | | if k_format and (k_format[1][0] or k_format[3][0]): |
| | | msg_list.append("股价创新高或者逼近前高") |
| | | # 股价创新高或者逼近前高 |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[1]: |
| | | return False, True, f"强势10分钟,独苗({can_buy_result[4]}),股价创新高或者逼近前高,当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[1]}" |
| | | else: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[ |
| | | 0] and not is_special: |
| | | return False, True, f"强势10分钟,无辨识度,独苗({can_buy_result[4]}),当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[0]}" |
| | | else: |
| | | return False, True, f"独苗:当前时间不能买" |
| | | msg_list.append("非独苗") |
| | | if not is_better_zylt: |
| | | msg_list.append("不满足自由流通") |
| | | if k_format and (k_format[1][0] or k_format[3][0]): |
| | | # 股价创新高或者逼近前高 |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[1]: |
| | | return False, True, f"强势10分钟,后排,不满足自由市值,股价创新高或者逼近前高,当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[1]}" |
| | | else: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[ |
| | | 0] and not is_special: |
| | | return False, True, f"强势10分钟,后排,无辨识度,不满足自由市值,当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[0]}" |
| | | else: |
| | | msg_list.append("满足自由流通") |
| | | # 后排,满足自由流通市值需要下单 |
| | | return True, False, can_buy_result[2] |
| | | return True, False, can_buy_result[2] |
| | | else: |
| | | if can_buy_result[0]: |
| | | return True, False, can_buy_result[2] |
| | | return False, True, can_buy_result[2] |
| | | |
| | | # 上5个交易日有炸板之后 |
| | | if has_open_limit_up_in_5: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.29: |
| | | return False, True, f"强势10分钟,上5个交易日炸板,量未达到{0.29}({cls.volume_rate_info[code][0]})" |
| | | |
| | | # 上5个交易日有跌停 |
| | | if has_limit_down_in_5: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.29: |
| | | return False, True, f"强势10分钟,上5个交易日跌停,量未达到{0.29}({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.29 and not is_special: |
| | | return False, True, f"参考量在最近5天,无辨识度,量未达到0.29({cls.volume_rate_info[code][0]})" |
| | | |
| | | # 非强势10分钟只买主线 |
| | | if not can_buy_result[0] and can_buy_result[1]: |
| | | if not is_special and not is_best_zylt: |
| | | return False, True, f"非强势10分钟,无辨识度,非特优市值,独苗({can_buy_result[4]})不下单" |
| | | if can_buy_result[3]: |
| | | # 强势主线 |
| | | if not is_better_zylt: |
| | | if k_format and (k_format[1][0] or k_format[3][0]): |
| | | # 股价创新高或者逼近前高 |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[1]: |
| | | return False, True, f"非强势10分钟,强势主线后排,不满足自由市值,股价创新高或者逼近前高,当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[1]}" |
| | | else: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[ |
| | | 0] and not is_special: |
| | | return False, True, f"非强势10分钟,强势主线后排,不满足自由市值,无辨识度,当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[0]}" |
| | | else: |
| | | if k_format and (k_format[1][0] or k_format[3][0]): |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[0]: |
| | | return False, True, f"非强势10分钟,强势主线后排,满足自由市值,股价创新高或者逼近前高, 当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[0]}" |
| | | else: |
| | | # 非强势主线 |
| | | if not is_better_zylt: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[ |
| | | 1] and not is_special: |
| | | return False, True, f"非强势10分钟,非强势主线后排【主线后排】,不满足自由市值,无辨识度, 当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[1]}" |
| | | else: |
| | | if k_format and (k_format[1][0] or k_format[3][0]): |
| | | # 股价创新高或者逼近前高 |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[1]: |
| | | return False, True, f"非强势10分钟,非强势主线后排【主线后排】,满足自由市值,股价创新高或者逼近前高, 当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[1]}" |
| | | else: |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < volume_rate_thresholds[ |
| | | 0] and not is_special: |
| | | return False, True, f"非强势10分钟,非强势主线后排【主线后排】, 满足自由市值,无辨识度,当日量比({cls.volume_rate_info[code][0]})小于{volume_rate_thresholds[0]}" |
| | | return True, False, can_buy_result[2] |
| | | |
| | | @classmethod |
| | | def __cancel_buy(cls, code): |
| | |
| | | # 是否是交易队列触发 |
| | | order_begin_pos = cls.__get_order_begin_pos( |
| | | code) |
| | | total_datas = local_today_datas[code] |
| | | total_datas = local_today_datas.get(code) |
| | | if not total_datas: |
| | | return False |
| | | if source == "trade_queue": |
| | | # 交易队列触发的需要下单后5s |
| | | if order_begin_pos.buy_exec_index is not None and order_begin_pos.buy_exec_index > 0: |
| | |
| | | trade_index, is_default = TradeBuyQueue().get_traded_index(code) |
| | | if trade_index and not is_default: |
| | | m_base_val = l2_trade_factor.L2PlaceOrderParamsManager.get_base_m_val(code) |
| | | thresh_hold_num = m_base_val * 3 // (float(gpcode_manager.get_limit_up_price(code)) * 100) |
| | | thresh_hold_num = m_base_val * 4 // (float(gpcode_manager.get_limit_up_price(code)) * 100) |
| | | # 真实下单位到成交位置的纯买额 * 3 |
| | | total_num = 0 |
| | | for i in range(trade_index + 1, buy_single_index): |
| | |
| | | order_begin_pos.count = 0 |
| | | order_begin_pos.buy_single_index = buy_single_index |
| | | if order_begin_pos.sell_info: |
| | | k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) |
| | | if k_format and (k_format[1][0] or k_format[3][0]): |
| | | # 股价新高或者逼近前高 |
| | | order_begin_pos.threshold_money = int(sell_info[1]) |
| | | else: |
| | | if float(total_datas[buy_single_index]["val"]["price"]) >= 3 and cls.volume_rate_info[code][ |
| | | 0] > 0.3 and sell_info[1] > 2000 * 10000: |
| | | # 暂时打8折 |
| | | # order_begin_pos.threshold_money = int(sell_info[1] * 0.8) |
| | | # 深证总卖大于1000万的票,m值打5折 |
| | | if code.find('00') == 0: |
| | | # k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) |
| | | # if k_format and (k_format[1][0] or k_format[3][0]): |
| | | # # 股价新高或者逼近前高 |
| | | # order_begin_pos.threshold_money = int(sell_info[1]) |
| | | # else: |
| | | if float(total_datas[buy_single_index]["val"]["price"]) >= 3 and cls.volume_rate_info[code][ |
| | | 0] > 0.3 and sell_info[1] > 2000 * 10000 and int( |
| | | tool.get_now_time_str().replace(":", "")) < int("100000"): |
| | | # 暂时打8折 |
| | | # order_begin_pos.threshold_money = int(sell_info[1] * 0.8) |
| | | # 深证总卖大于1000万的票,m值打5折 |
| | | if code.find('00') == 0: |
| | | # 深圳首次下单打折 |
| | | place_order_count = trade_data_manager.PlaceOrderCountManager().get_place_order_count(code) |
| | | if place_order_count is not None and place_order_count == 0: |
| | | order_begin_pos.threshold_money = int(sell_info[1] * 0.6) |
| | | else: |
| | | order_begin_pos.threshold_money = int(sell_info[1] * 0.8) |
| | | order_begin_pos.threshold_money = int(sell_info[1]) |
| | | else: |
| | | order_begin_pos.threshold_money = int(sell_info[1]) |
| | | order_begin_pos.threshold_money = int(sell_info[1] * 0.8) |
| | | else: |
| | | order_begin_pos.threshold_money = int(sell_info[1]) |
| | | l2_log.debug(code, "获取到买入信号起始点:{} ,计算范围:{}-{} ,量比:{},是否板上买:{},数据:{} 模式:{}({})", buy_single_index, |
| | | compute_start_index, |
| | | compute_end_index, cls.volume_rate_info[code], order_begin_pos.at_limit_up, |
| | |
| | | # _start_time = l2_data_log.l2_time(code, tool.get_now_timestamp() - _start_time, "m值阈值计算") |
| | | |
| | | # 买入纯买额统计 |
| | | new_buy_exec_index, buy_nums, buy_count, rebegin_buy_pos, max_num_set_new = None, None, None, None, [] |
| | | new_buy_exec_index, buy_nums, buy_count, rebegin_buy_pos, max_num_set_new, not_buy_msg = None, None, None, None, [], "" |
| | | if order_begin_pos.mode == OrderBeginPosInfo.MODE_FAST: |
| | | |
| | | threshold_money = order_begin_pos.threshold_money |
| | | new_buy_exec_index, buy_nums, buy_count, rebegin_buy_pos, threshold_money_new = cls.__sum_buy_num_for_order_fast( |
| | | new_buy_exec_index, buy_nums, buy_count, rebegin_buy_pos, threshold_money_new, not_buy_msg = cls.__sum_buy_num_for_order_fast( |
| | | code, |
| | | start_process_index, |
| | | compute_end_index, |
| | |
| | | threshold_money = threshold_money_new |
| | | order_begin_pos.threshold_money = threshold_money |
| | | else: |
| | | new_buy_exec_index, buy_nums, buy_count, rebegin_buy_pos, max_num_set_new = cls.__sum_buy_num_for_order_3( |
| | | new_buy_exec_index, buy_nums, buy_count, rebegin_buy_pos, max_num_set_new, not_buy_msg = cls.__sum_buy_num_for_order_3( |
| | | code, |
| | | start_process_index, |
| | | compute_end_index, |
| | |
| | | max_num_set=max_num_set_new, mode=order_begin_pos.mode, |
| | | sell_info=order_begin_pos.sell_info, |
| | | threshold_money=threshold_money)) |
| | | # 记录没下单原因 |
| | | async_log_util.info(logger_l2_not_buy_reasons, f"{code}#{not_buy_msg}") |
| | | _start_time = t.time() |
| | | l2_data_log.l2_time_log(code, "__start_compute_buy 结束") |
| | | |
| | |
| | | # 目标订单数量 |
| | | threshold_count = cls.__l2PlaceOrderParamsManagerDict[code].get_safe_count() |
| | | |
| | | buy_single_time_seconds = L2DataUtil.get_time_as_second(total_datas[buy_single_index]["val"]["time"]) |
| | | # buy_single_time_seconds = L2DataUtil.get_time_as_second(total_datas[buy_single_index]["val"]["time"]) |
| | | |
| | | # 可以触发买,当有涨停买信号时才会触发买 |
| | | trigger_buy = True |
| | | |
| | | # 间隔最大时间依次为:3,9,27,81 |
| | | max_space_time = cls.__l2PlaceOrderParamsManagerDict[code].get_time_range() |
| | | # 最大间隔时间ms |
| | | max_space_time_ms = cls.__l2PlaceOrderParamsManagerDict[code].get_time_range() * 1000 |
| | | # 最大买量 |
| | | max_buy_num = 0 |
| | | max_buy_num_set = set(max_num_set) |
| | |
| | | # 较大单的手数 |
| | | bigger_num = round(5000 / limit_up_price) |
| | | |
| | | not_buy_msg = "" |
| | | for i in range(compute_start_index, compute_end_index + 1): |
| | | data = total_datas[i] |
| | | _val = total_datas[i]["val"] |
| | | trigger_buy = False |
| | | # 必须为连续2秒内的数据 |
| | | if L2DataUtil.get_time_as_second(_val["time"]) - buy_single_time_seconds + 1 > max_space_time: |
| | | if L2DataUtil.time_sub_as_ms(_val, total_datas[buy_single_index]["val"]) > max_space_time_ms: |
| | | cls.__TradePointManager.delete_buy_point(code) |
| | | if i == compute_end_index: |
| | | # 数据处理完毕 |
| | | return None, buy_nums, buy_count, None, max_buy_num_set |
| | | return None, buy_nums, buy_count, None, max_buy_num_set, f"【{i}】信号不连续,囊括时间-{max_space_time_ms}ms" |
| | | else: |
| | | # 计算买入信号,不能同一时间开始计算 |
| | | for ii in range(buy_single_index + 1, compute_end_index + 1): |
| | | if total_datas[buy_single_index]["val"]["time"] != total_datas[ii]["val"]["time"]: |
| | | return None, buy_nums, buy_count, ii, max_buy_num_set |
| | | return None, buy_nums, buy_count, ii, max_buy_num_set, f"【{i}】信号不连续,囊括时间-{max_space_time_ms}ms" |
| | | # 涨停买 |
| | | if L2DataUtil.is_limit_up_price_buy(_val): |
| | | if l2_data_util.is_big_money(_val): |
| | |
| | | max_buy_num_set_count = 0 |
| | | for i1 in max_buy_num_set: |
| | | max_buy_num_set_count += total_datas[i1]["re"] |
| | | # 有撤单信号,且小于阈值 |
| | | if buy_nums >= threshold_num and buy_count >= threshold_count and trigger_buy and max_buy_num_set_count >= big_num_count: |
| | | try: |
| | | info = cls.__trade_log_placr_order_info_dict[code] |
| | | info.set_trade_factor(threshold_money, threshold_count, list(max_buy_num_set)) |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_error, f"记录交易因子出错:{str(e)}") |
| | | |
| | | return i, buy_nums, buy_count, None, max_buy_num_set |
| | | if buy_nums < threshold_num: |
| | | not_buy_msg = f"【{i}】纯买额不足,{buy_nums}/{threshold_num}" |
| | | continue |
| | | |
| | | if buy_count < threshold_count: |
| | | not_buy_msg = f"【{i}】安全笔数不够,{buy_count}/{threshold_count}" |
| | | continue |
| | | |
| | | if not trigger_buy: |
| | | not_buy_msg = f"【{i}】没有买单触发" |
| | | continue |
| | | |
| | | if max_buy_num_set_count < big_num_count: |
| | | not_buy_msg = f"【{i}】大单数量不足,{max_buy_num_set_count}/{big_num_count}" |
| | | continue |
| | | |
| | | try: |
| | | info = cls.__trade_log_placr_order_info_dict[code] |
| | | info.set_trade_factor(threshold_money, threshold_count, list(max_buy_num_set)) |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_error, f"记录交易因子出错:{str(e)}") |
| | | |
| | | return i, buy_nums, buy_count, None, max_buy_num_set, "可以下单" |
| | | |
| | | l2_log.buy_debug(code, "尚未获取到买入执行点,起始计算位置:{} 统计纯买手数:{} 目标纯买手数:{} 统计纯买单数:{} 目标纯买单数:{} 大单数量:{} 目标大单数量:{}", |
| | | compute_start_index, |
| | | buy_nums, |
| | | threshold_num, buy_count, threshold_count, max_buy_num_set_count, big_num_count) |
| | | |
| | | return None, buy_nums, buy_count, None, max_buy_num_set |
| | | return None, buy_nums, buy_count, None, max_buy_num_set, not_buy_msg |
| | | |
| | | # 返回(买入执行点, 总手, 总笔数, 从新计算起点, 纯买额阈值) |
| | | # 计算快速买入 |
| | |
| | | # 目标手数 |
| | | threshold_num = round(threshold_money / (limit_up_price * 100)) |
| | | |
| | | buy_single_time_seconds = L2DataUtil.get_time_as_second(total_datas[buy_single_index]["val"]["time"]) |
| | | # buy_single_time_seconds = L2DataUtil.get_time_as_second(total_datas[buy_single_index]["val"]["time"]) |
| | | |
| | | # 可以触发买,当有涨停买信号时才会触发买 |
| | | trigger_buy = True |
| | | # 间隔最大时间为3s |
| | | max_space_time = 3 |
| | | max_space_time_ms = 3 * 1000 |
| | | # 不下单的信息 |
| | | not_buy_msg = "" |
| | | for i in range(compute_start_index, compute_end_index + 1): |
| | | data = total_datas[i] |
| | | _val = total_datas[i]["val"] |
| | | trigger_buy = False |
| | | # 必须为连续2秒内的数据 |
| | | if L2DataUtil.get_time_as_second(_val["time"]) - buy_single_time_seconds + 1 > max_space_time: |
| | | if L2DataUtil.time_sub_as_ms(_val, total_datas[buy_single_index]["val"]) > max_space_time_ms: |
| | | cls.__TradePointManager.delete_buy_point(code) |
| | | if i == compute_end_index: |
| | | # 数据处理完毕 |
| | | return None, buy_nums, buy_count, None, threshold_money |
| | | return None, buy_nums, buy_count, None, threshold_money, f"【{i}】信号不连续,囊括时间-{max_space_time_ms}ms" |
| | | else: |
| | | # 计算买入信号,不能同一时间开始计算 |
| | | for ii in range(buy_single_index + 1, compute_end_index + 1): |
| | | if total_datas[buy_single_index]["val"]["time"] != total_datas[ii]["val"]["time"]: |
| | | return None, buy_nums, buy_count, ii, threshold_money |
| | | return None, buy_nums, buy_count, ii, threshold_money, f"【{i}】信号不连续,囊括时间-{max_space_time_ms}ms" |
| | | if L2DataUtil.is_sell(_val): |
| | | threshold_money += _val["num"] * int(float(_val["price"]) * 100) |
| | | threshold_num = round(threshold_money / (limit_up_price * 100)) |
| | |
| | | buy_count -= int(total_datas[i]["re"]) |
| | | l2_log.buy_debug(code, "位置-{},总手数:{},目标手数:{}", i, |
| | | buy_nums, threshold_num) |
| | | # 有撤单信号,且小于阈值 |
| | | if buy_nums >= threshold_num and trigger_buy: |
| | | try: |
| | | info = cls.__trade_log_placr_order_info_dict[code] |
| | | info.set_trade_factor(threshold_money, 0, []) |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_error, f"记录交易因子出错:{str(e)}") |
| | | # 纯买额足够,且笔数大于5笔 |
| | | if buy_nums < threshold_num: |
| | | not_buy_msg = f"【{i}】纯买额不够,{buy_nums}/{threshold_num}" |
| | | continue |
| | | if not trigger_buy: |
| | | not_buy_msg = f"【{i}】没有买单触发" |
| | | continue |
| | | if buy_count < 5: |
| | | not_buy_msg = f"【{i}】安全笔数不足,{buy_count}/{5}" |
| | | continue |
| | | try: |
| | | info = cls.__trade_log_placr_order_info_dict[code] |
| | | info.set_trade_factor(threshold_money, 0, []) |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_error, f"记录交易因子出错:{str(e)}") |
| | | |
| | | return i, buy_nums, buy_count, None, threshold_money |
| | | return i, buy_nums, buy_count, None, threshold_money, "可以下单" |
| | | |
| | | l2_log.buy_debug(code, "尚未获取到买入执行点(快速买入),起始计算位置:{} 统计纯买手数:{} 目标纯买手数:{} 统计纯买单数:{}", |
| | | compute_start_index, |
| | | buy_nums, |
| | | threshold_num, buy_count) |
| | | |
| | | return None, buy_nums, buy_count, None, threshold_money |
| | | return None, buy_nums, buy_count, None, threshold_money, not_buy_msg |
| | | |
| | | |
| | | def test_trade_record(): |