api/outside_api_command_callback.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
l2/l2_data_manager_new.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
l2/l2_transaction_data_processor.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
servers/data_server.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
servers/huaxin_trade_server.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
third_data/code_plate_key_manager.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
third_data/kpl_data_manager.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
trade/buy_radical/radical_buy_data_manager.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
trade/buy_radical/radical_buy_strategy.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
trade/radical_buy_data_manager.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
trade/trade_result_manager.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
api/outside_api_command_callback.py
@@ -36,8 +36,7 @@ logger_real_place_order_position, logger_device from output import l2_output_util from third_data import kpl_util, history_k_data_manager, huaxin_l1_data_manager, third_blocks_manager, kpl_data_manager from third_data.code_plate_key_manager import KPLCodeJXBlockManager, \ RadicalBuyBlockManager from third_data.code_plate_key_manager import KPLCodeJXBlockManager from third_data.history_k_data_manager import HistoryKDataManager from third_data.history_k_data_util import JueJinApi, HistoryKDatasUtils from third_data.kpl_data_manager import KPLDataManager @@ -51,6 +50,7 @@ from trade.huaxin import huaxin_trade_api, huaxin_trade_data_update, \ huaxin_trade_record_manager, huaxin_trade_order_processor, huaxin_sell_util from trade.huaxin.huaxin_trade_record_manager import PositionManager, DealRecordManager, DelegateRecordManager from trade.buy_radical.radical_buy_data_manager import RadicalBuyBlockManager from trade.sell import sell_manager from trade.sell.sell_rule_manager import TradeRuleManager, SellRule from trade.trade_manager import TradeTargetCodeModeManager, AutoCancelSellModeManager l2/l2_data_manager_new.py
@@ -6,8 +6,8 @@ from cancel_strategy.s_l_h_cancel_strategy import HourCancelBigNumComputer, LCancelRateManager from cancel_strategy.s_l_h_cancel_strategy import LCancelBigNumComputer from cancel_strategy.s_l_h_cancel_strategy import SCancelBigNumComputer from code_attribute import big_money_num_manager, code_volumn_manager, code_data_util, industry_codes_sort, \ limit_up_time_manager, global_data_loader, gpcode_manager, code_nature_analyse from code_attribute import big_money_num_manager, code_volumn_manager, code_data_util, limit_up_time_manager, \ gpcode_manager, code_nature_analyse import constant from db.redis_manager_delegate import RedisUtils from l2.huaxin import l2_huaxin_util, huaxin_delegate_postion_manager @@ -17,15 +17,14 @@ from l2.place_order_single_data_manager import L2TradeSingleDataProcessor from log_module import async_log_util, log_export from third_data import kpl_data_manager, block_info from third_data.kpl_data_constant import LimitUpDataConstant from trade.buy_money_count_setting import RadicalBuyBlockCodeCountManager from utils import global_util, ths_industry_util, tool, buy_condition_util, buy_strategy_util, trade_util from utils import global_util, tool, buy_condition_util, buy_strategy_util, trade_util import l2_data_util from db import redis_manager_delegate as redis_manager from third_data.code_plate_key_manager import CodePlateKeyBuyManager, KPLCodeJXBlockManager from trade import trade_manager, trade_queue_manager, l2_trade_factor, l2_trade_util, \ trade_result_manager, current_price_process_manager, trade_data_manager, trade_huaxin, trade_record_log_util, \ trade_constant, buy_open_limit_up_strategy, radical_buy_data_manager trade_constant, buy_open_limit_up_strategy from trade.buy_radical import radical_buy_data_manager 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 DCancelBigNumComputer, \ l2/l2_transaction_data_processor.py
@@ -21,7 +21,7 @@ from trade import current_price_process_manager, trade_constant import concurrent.futures from trade.radical_buy_data_manager import RadicalBuyDataManager, EveryLimitupBigDealOrderManager from trade.buy_radical.radical_buy_data_manager import RadicalBuyDataManager, EveryLimitupBigDealOrderManager from utils import tool servers/data_server.py
@@ -9,19 +9,19 @@ from code_attribute.gpcode_manager import BlackListCodeManager from l2.l2_transaction_data_manager import HuaXinBuyOrderManager from log_module.log import logger_system, logger_debug, logger_kpl_limit_up, logger_request_api from third_data.kpl_data_constant import LimitUpDataConstant, LimitUpCodesBlockRecordManager from third_data.kpl_data_constant import LimitUpCodesBlockRecordManager from third_data.kpl_limit_up_data_manager import LatestLimitUpBlockManager, CodeLimitUpSequenceManager from third_data.third_blocks_manager import BlockMapManager from trade.buy_strategy import OpenLimitUpGoodBlocksBuyStrategy from trade.buy_radical.radical_buy_data_manager import RadicalBuyBlockManager from utils import global_util, tool, data_export_util from code_attribute import gpcode_manager from log_module import log, log_analyse, log_export, async_log_util from log_module import log_analyse, log_export, async_log_util from l2 import code_price_manager, l2_data_util, transaction_progress from cancel_strategy.s_l_h_cancel_strategy import HourCancelBigNumComputer, LCancelRateManager from output.limit_up_data_filter import IgnoreCodeManager from third_data import kpl_util, kpl_data_manager, kpl_api, block_info from third_data.code_plate_key_manager import RealTimeKplMarketData, KPLPlateForbiddenManager, CodePlateKeyBuyManager, \ RadicalBuyBlockManager from third_data.code_plate_key_manager import RealTimeKplMarketData, KPLPlateForbiddenManager from third_data.history_k_data_util import HistoryKDatasUtils from third_data.kpl_data_manager import KPLDataManager, KPLLimitUpDataRecordManager, \ KPLCodeLimitUpReasonManager servers/huaxin_trade_server.py
@@ -16,7 +16,7 @@ import constant import outside_api_command_manager from cancel_strategy.s_l_h_cancel_strategy import SCancelBigNumComputer from code_attribute import gpcode_manager, code_volumn_manager, global_data_loader, zyltgb_util, code_nature_analyse from code_attribute import gpcode_manager, code_volumn_manager, global_data_loader, zyltgb_util from code_attribute.code_l1_data_manager import L1DataManager from code_attribute.gpcode_manager import CodePrePriceManager, CodesNameManager from huaxin_client import l2_data_transform_protocol @@ -32,7 +32,6 @@ from l2.l2_data_manager_new import L2TradeDataProcessor from l2.l2_data_util import L2DataUtil from l2.l2_sell_manager import L2MarketSellManager from l2.l2_transaction_data_manager import HuaXinSellOrderStatisticManager from l2.l2_transaction_data_processor import HuaXinTransactionDatasProcessor from l2.place_order_single_data_manager import L2TradeSingleCallback, L2TradeSingleDataManager from log_module import async_log_util, log_export @@ -40,11 +39,11 @@ hx_logger_l2_orderdetail, hx_logger_l2_market_data, logger_l2_g_cancel, logger_debug, \ logger_system, logger_trade, logger_local_huaxin_l1_trade_info, logger_l2_codes_subscript, logger_l2_radical_buy from third_data import block_info, kpl_data_manager, history_k_data_manager, huaxin_l1_data_manager from third_data.code_plate_key_manager import KPLCodeJXBlockManager, CodePlateKeyBuyManager, RadicalBuyBlockManager, \ TargetCodePlateKeyManager from third_data.code_plate_key_manager import KPLCodeJXBlockManager, CodePlateKeyBuyManager from third_data.history_k_data_util import JueJinApi from trade import trade_manager, l2_trade_util, \ trade_data_manager, trade_constant, radical_buy_strategy, radical_buy_data_manager, buy_open_limit_up_strategy from trade import l2_trade_util, \ trade_data_manager, trade_constant, buy_open_limit_up_strategy from trade.buy_radical import radical_buy_data_manager, radical_buy_strategy from trade.buy_money_count_setting import BuyMoneyAndCountSetting, BuyMoneyUtil from trade.huaxin import huaxin_trade_api as trade_api, huaxin_trade_api, huaxin_trade_data_update, \ @@ -52,7 +51,7 @@ from api.outside_api_command_callback import OutsideApiCommandCallback from trade.huaxin.huaxin_trade_record_manager import DelegateRecordManager from trade.order_statistic import DealAndDelegateWithBuyModeDataManager from trade.radical_buy_data_manager import RadicalBuyDataManager from trade.buy_radical.radical_buy_data_manager import RadicalBuyDataManager, RadicalBuyBlockManager from trade.sell.sell_rule_manager import TradeRuleManager from trade.trade_data_manager import RadicalBuyDealCodesManager from trade.trade_manager import CodesTradeStateManager third_data/code_plate_key_manager.py
@@ -10,21 +10,17 @@ import constant from db.redis_manager_delegate import RedisUtils from third_data import kpl_block_util, kpl_api, kpl_util, kpl_data_constant, huaxin_l1_data_manager from third_data import kpl_block_util, kpl_api, kpl_util from settings.trade_setting import MarketSituationManager from third_data.kpl_data_constant import LimitUpDataConstant, LimitUpCodesBlockRecordManager from third_data.third_blocks_manager import BlockMapManager, CodeThirdBlocksManager from trade.buy_money_count_setting import RadicalBuyBlockCodeCountManager from trade.order_statistic import DealAndDelegateWithBuyModeDataManager from trade.radical_buy_data_manager import RadicalBuyDataManager, BlockPlaceOrderRecordManager from trade.trade_data_manager import RadicalBuyDealCodesManager from third_data.kpl_data_constant import LimitUpCodesBlockRecordManager from third_data.third_blocks_manager import BlockMapManager from utils import global_util, tool, buy_condition_util from log_module import log, async_log_util from log_module import async_log_util from db import redis_manager_delegate as redis_manager from log_module.log import logger_kpl_block_can_buy, logger_debug, logger_kpl_jx_out from log_module.log import logger_kpl_block_can_buy, logger_kpl_jx_out from third_data.kpl_util import KPLPlatManager from trade import trade_manager, l2_trade_util, trade_constant, radical_buy_data_manager from trade import trade_manager, l2_trade_util, trade_constant # 代码精选板块管理 from utils.kpl_data_db_util import KPLLimitUpDataUtil @@ -923,7 +919,12 @@ # 获取目标代码板块 # keys, k1, k11, k2, k3, k4 = cls.__TargetCodePlateKeyManager.get_plate_keys(code) keys, k1 = RadicalBuyBlockManager.get_code_blocks(code) keys = LimitUpCodesBlockRecordManager().get_radical_buy_blocks(code) if not keys: keys = set() keys = BlockMapManager().filter_blocks(keys) if keys: keys -= constant.KPL_INVALID_BLOCKS # log.logger_kpl_debug.info("{}最终关键词:{}", code, keys) @@ -1101,617 +1102,6 @@ # 保存板块计算结果 cls.__can_buy_compute_result_dict[code] = ( can_buy_blocks, unique, msg, can_buy_strong_blocks, keys, active_buy_blocks) class RadicalBuyBlockManager: """ 扫入买板块管理 """ __TargetCodePlateKeyManager = TargetCodePlateKeyManager() # 上次的涨停代码 __last_limit_up_codes = set() # 记录代码的涨停时间 __limit_up_time_dict = {} # 炸板代码的总涨停时间 __total_limit_up_space_dict = {} # 当前涨停的代码 __current_limit_up_codes = set() @classmethod def set_current_limit_up_datas(cls, current_limit_up_datas): # 查询当前的涨停代码集合 codes = set([d[0] for d in current_limit_up_datas]) cls.__current_limit_up_codes = codes try: # 炸板代码 break_limit_up_codes = cls.__last_limit_up_codes - codes # 新涨停的代码 new_limit_up_codes = codes - cls.__last_limit_up_codes if new_limit_up_codes: for code in new_limit_up_codes: if code not in cls.__limit_up_time_dict: cls.__limit_up_time_dict[code] = time.time() if break_limit_up_codes: # 记录总涨停时间 for bc in break_limit_up_codes: if bc in cls.__limit_up_time_dict: space = tool.trade_time_sub(tool.get_now_time_str(), tool.to_time_str(cls.__limit_up_time_dict[bc])) if bc not in cls.__total_limit_up_space_dict: cls.__total_limit_up_space_dict[bc] = 0 cls.__total_limit_up_space_dict[bc] = cls.__total_limit_up_space_dict[bc] + space logger_debug.info(f"炸板代码涨停时间:{bc}-{cls.__total_limit_up_space_dict[bc]}") cls.__limit_up_time_dict.pop(bc) except Exception as e: logger_debug.exception(e) finally: cls.__last_limit_up_codes = codes cls.compute_open_limit_up_code_dict_for_radical_buy(current_limit_up_datas) @classmethod def compute_open_limit_up_code_dict_for_radical_buy(cls, current_limit_up_datas): """ 计算开1的代码信息,不包含5板以上的 @param current_limit_up_datas: @return: """ timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range temp_dict = {} for d in current_limit_up_datas: code = d[0] # d: (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额,涨停原因代码,涨停原因代码数量) # 计算是否开1 if int(d[2]) >= timestamp_end or int(d[2]) < timestamp_start: continue buy1_money = huaxin_l1_data_manager.get_buy1_money(code) # 买1是否大于5000w if not constant.TEST: if not buy1_money or buy1_money < 5e7: continue if not tool.is_can_buy_code(code): continue blocks = {d[5]} if d[6]: blocks |= set(d[6].split("、")) blocks -= constant.KPL_INVALID_BLOCKS # 过滤 blocks = BlockMapManager().filter_blocks(blocks) # 开1剔除4板以上的 high_level = kpl_util.get_high_level_count(d[4]) if high_level >= 4: continue temp_dict[code] = (high_level, blocks) kpl_data_constant.open_limit_up_code_dict_for_radical_buy = temp_dict @classmethod def __get_current_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None, limit_up_time=None, ignore_open_limit_up=True): """ 获取当前涨停身位 @param code: @param block: @param yesterday_limit_up_codes: @param exclude_codes: @param limit_up_time: @param ignore_open_limit_up: 是否忽略开1的代码 @return: 索引,前排代码信息([(代码, 涨停时间)]) """ if exclude_codes is None: exclude_codes = set() current_index = 0 block_codes_infos = [] timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range if limit_up_time is None: limit_up_time = time.time() for k in LimitUpDataConstant.current_limit_up_datas: _code = k[0] if _code in exclude_codes: continue blocks = LimitUpDataConstant.get_blocks_with_history(_code) if not blocks: blocks = set() if _code == code: # 获取当前代码涨停时间 limit_up_time = int(k[2]) continue # 不是这个板块 if block not in blocks: continue # 剔除4板以上的板 if kpl_util.get_high_level_count(k[4]) >= 4 and len(blocks) > 1: continue if not tool.is_can_buy_code(_code): continue # 剔除开1的数据 if ignore_open_limit_up and timestamp_start <= int(k[2]) < timestamp_end: continue # 剔除高位板 if _code in yesterday_limit_up_codes: continue # 代码.涨停时间 block_codes_infos.append((_code, int(k[2]))) block_codes_infos.append((code, limit_up_time)) block_codes_infos.sort(key=lambda x: x[1]) before_codes_info = [] for i in range(0, len(block_codes_infos)): if block_codes_infos[i][0] == code: current_index = i break else: before_codes_info.append(block_codes_infos[i]) return current_index, before_codes_info @classmethod def __get_history_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None, ignore_open_limit_up=True): """ 获取历史涨停身位 @param code: @param block: @param yesterday_limit_up_codes: @param exclude_codes: @param ignore_open_limit_up: 是否忽略开1代码 @return: """ if exclude_codes is None: exclude_codes = set() history_index = 0 block_codes_infos = [] # 开1时间范围 timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range limit_up_time = time.time() limit_up_space_ge_60s_codes = set() for k in LimitUpDataConstant.history_limit_up_datas: _code = k[3] if _code in exclude_codes: continue if _code == code: # 获取当前代码涨停时间 limit_up_time = int(k[5]) continue blocks = LimitUpDataConstant.get_blocks_with_history(_code) # 不是这个板块 if block not in blocks: continue # 剔除4板以上且板块数量大于1个 if kpl_util.get_high_level_count(k[12]) >= 4 and len(blocks) > 1: continue if not tool.is_can_buy_code(_code): continue # 剔除开1的数据 if ignore_open_limit_up and timestamp_start <= int(k[5]) < timestamp_end: continue # 剔除高位板 if _code in yesterday_limit_up_codes: continue # 剔除炸板代码持续涨停时间小于1分钟的代码 且 只能用于不排除前2条数据 if _code not in cls.__current_limit_up_codes and _code in cls.__total_limit_up_space_dict and \ cls.__total_limit_up_space_dict[_code] < 60 and not exclude_codes and len( limit_up_space_ge_60s_codes) < 3: limit_up_space_ge_60s_codes.add(_code) continue # 代码,涨停时间 block_codes_infos.append((_code, int(k[5]))) block_codes_infos.append((code, limit_up_time)) block_codes_infos.sort(key=lambda x: x[1]) before_codes_info = [] for i in range(0, len(block_codes_infos)): if block_codes_infos[i][0] == code: history_index = i break else: before_codes_info.append(block_codes_infos[i]) return history_index, before_codes_info @classmethod def __is_radical_buy_with_open_limitup(cls, code, block, yesterday_limit_up_codes): """ 是否需要激进买(某个板块开1) 1.有>=2个开1买老2 2.有1个开1的买老3 @param code: @param block: @param yesterday_limit_up_codes 昨日涨停代码 @return: """ # 9:45点之前涨停的才能买入 # 获取当前代码的涨停时间 limit_up_timestamp = cls.__get_limit_up_timestamp(code) if tool.get_now_time_as_int() > 100000: return False, "超过生效时间" # 根据板块聚合数据 open_limit_up_block_codes_dict = {} for c in kpl_data_constant.open_limit_up_code_dict_for_radical_buy: blocks = kpl_data_constant.open_limit_up_code_dict_for_radical_buy[c][1] for b in blocks: if b not in open_limit_up_block_codes_dict: open_limit_up_block_codes_dict[b] = set() open_limit_up_block_codes_dict[b].add(c) if block not in open_limit_up_block_codes_dict: return False, "板块未开1" open_limit_up_block_codes = list(open_limit_up_block_codes_dict.get(block)) count = len(open_limit_up_block_codes) # ----获取历史身位---- history_index, history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes) # ----获取实时身位---- current_index, current_before_codes_info = cls.__get_current_index(code, block, yesterday_limit_up_codes, limit_up_time=limit_up_timestamp) exclude_codes = set() # 是否为强势二板开1:该代码所有的慨念必须都为二板开1且开1的只能有他自己 is_strong_2_level = count == 1 and \ kpl_data_constant.open_limit_up_code_dict_for_radical_buy[open_limit_up_block_codes[0]][ 0] == 2 if is_strong_2_level: _code = open_limit_up_block_codes[0] blocks = LimitUpDataConstant.get_blocks_with_history(_code) if blocks: # 所有的慨念的开1代码必须只有他自己 for b in blocks: temp_codes = open_limit_up_block_codes_dict.get(b) if temp_codes and len(temp_codes) > 1: is_strong_2_level = False break if count >= 2 or is_strong_2_level: # 开始数量大于2个或者只有一个2板开1 exclude_codes.clear() else: # 只有一个开1 # 获取包含高位板的身位 # ----获取历史身位---- history_index, history_before_codes_info = cls.__get_history_index(code, block, set()) # ----获取实时身位---- current_index, current_before_codes_info = cls.__get_current_index(code, block, set(), limit_up_time=limit_up_timestamp) if history_before_codes_info and current_before_codes_info and history_before_codes_info[0][0] == \ current_before_codes_info[0][0]: # 排除第一个非开1数据 exclude_codes = {history_before_codes_info[0][0]} else: return False, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}" # 获取主板的身位(已经排除了开1的代码) history_index, history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes, exclude_codes=exclude_codes) # 过滤不正的原因 history_index, history_before_codes_info = cls.__filter_before_codes(block, history_index, history_before_codes_info, yesterday_limit_up_codes) # 买首板老大/老二 # 首板老大不能买时可买老二 if history_index > 1: return False, f"开1数量:{count},非开1首板身位不匹配:历史-{history_index + 1} 实时-{current_index + 1}" if history_index == 1: # 当前代码为老2,要判断老大是否可买 if RadicalBuyDataManager.is_code_can_buy(history_before_codes_info[0][0], DealAndDelegateWithBuyModeDataManager().get_deal_codes(), is_refered=True)[0]: return False, f"开1数量:{count},前排代码可买:{history_before_codes_info[0]}" return True, f"开1数量:{count},前排代码不可买:{history_before_codes_info[0]},历史前排-{history_before_codes_info},开1代码-{open_limit_up_block_codes}" return True, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}, 前排代码-{current_before_codes_info}, 开1代码-{open_limit_up_block_codes}" @classmethod def __filter_before_codes(cls, block, index, before_codes_info, yesterday_codes): """ 过滤前排涨停原因不正/不算身位的代码 @param code: @param block:板块 @param index: 目标代码位置 @param before_codes_info: [(代码, 涨停时间戳)] @return: 过滤之后的 (index, before_codes_info) """ try: if index == 0 or not before_codes_info: return index, before_codes_info temp_index = index temp_before_codes_info = [] deal_codes = RadicalBuyDealCodesManager().get_deal_codes() for b in before_codes_info: # 当作目标票获取扫入板块 code_ = b[0] blocks = LimitUpCodesBlockRecordManager().get_radical_buy_blocks(code_) blocks = BlockMapManager().filter_blocks(blocks) need_delete = False # 判断原因不正 if block not in blocks and b[0] not in yesterday_codes: # 首板涨停原因不正 need_delete = True # 判断是否是不计算身位 if not need_delete: if radical_buy_data_manager.ExcludeIndexComputeCodesManager.is_in_cache(code_): need_delete = True # 判断是不是扫了没有扫进入 if not need_delete: if code_ in BlockPlaceOrderRecordManager().get_codes() and code_ not in deal_codes: need_delete = True if need_delete: temp_index -= 1 else: temp_before_codes_info.append(b) return temp_index, temp_before_codes_info except Exception as e: async_log_util.error(logger_debug, f"扫入板块过滤出错:{str(e)}") return index, before_codes_info @classmethod def __is_radical_buy_with_block_up(cls, code, block, yesterday_limit_up_codes): """ 是否激进买(板块突然涨起来) 1.老二和老三的涨停时间相差5分钟内 2.老三不能买顺位到老四(老四与老三相差10分钟内) 3.前2个票不能炸板(历史身位与现在身位一致) 4.除开前两个代码可买老1与老2 5.买老2的情况:老1不满足买入条件 @param code: @param block: @param yesterday_limit_up_codes: @return: """ # 获取当前代码的涨停时间 limit_up_timestamp = cls.__get_limit_up_timestamp(code) # 获取当前的板块 current_index, current_before_codes_info = cls.__get_current_index(code, block, set(), limit_up_time=limit_up_timestamp) current_before_codes = [x[0] for x in current_before_codes_info] if len(current_before_codes_info) < 2: return False, f"前排代码小于2个:{current_before_codes_info}" # 当前代码开1不能买 if limit_up_timestamp < kpl_block_util.open_limit_up_time_range[1]: return False, f"当前代码开1" if tool.trade_time_sub(tool.timestamp_format(limit_up_timestamp, '%H:%M:%S'), tool.timestamp_format(current_before_codes_info[-1][1], '%H:%M:%S')) >= 10 * 60: return False, f"距离上个代码涨停已过去10分钟({current_before_codes_info[-1]})" # 包含高位板的整体排序 all_history_index, all_history_before_codes_info = cls.__get_history_index(code, block, set()) all_history_before_codes = [x[0] for x in all_history_before_codes_info] # 前两个代码是否有炸板 dif_codes = set(all_history_before_codes[:2]) - set(current_before_codes[:2]) if dif_codes: return False, f"前2代码有炸板:{dif_codes}, 前排代码:{all_history_before_codes}" # 前排代码炸板不能>=2个 dif_codes = set(all_history_before_codes) - set(current_before_codes) if len(dif_codes) >= 2: return False, f"板块前排有{len(dif_codes)}个炸板" exclude_codes = set() for x in current_before_codes_info: if x[1] < kpl_block_util.open_limit_up_time_range[1]: exclude_codes.add(x[0]) # 除去前二代码与开1代码之后是否为首板老大:所有开1的视为1个 open_count = len(exclude_codes) if open_count > 0 and open_count + 1 <= len(current_before_codes): # 前排有开1 exclude_codes |= set(current_before_codes[open_count:open_count + 1]) else: exclude_codes |= set(current_before_codes[:2]) open_limit_up_code_dict = kpl_data_constant.open_limit_up_code_dict_for_radical_buy if open_limit_up_code_dict: exclude_codes |= set(open_limit_up_code_dict.keys()) origin_history_index, origin_history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes, exclude_codes) # 过滤不正的原因 history_index, history_before_codes_info = cls.__filter_before_codes(block, origin_history_index, origin_history_before_codes_info, yesterday_limit_up_codes) # 获取本板块买入代码的最大数量 max_count = RadicalBuyBlockCodeCountManager().get_block_code_count(block) if history_index > max_count: return False, f"排除前2,目标代码位于历史身位-{history_index + 1},前排代码:{history_before_codes_info}, 板块最多可买{max_count}" if max_count == 1: if history_index == 1: # 首板老2,判断前面的老大是否是属于不能买的范畴 pre_code = history_before_codes_info[0][0] # pre_code不能买,才能买 if RadicalBuyDataManager.is_code_can_buy(pre_code, DealAndDelegateWithBuyModeDataManager().get_deal_codes(), is_refered=True)[0]: return False, f"前排代码可买:{pre_code}" # 前面一个代码不能买,前一个代码必须与前前个代码涨停时间相差15分钟内 for i in range(len(all_history_before_codes_info) - 1, -1, -1): if all_history_before_codes_info[i][0] == pre_code: if tool.trade_time_sub(tool.timestamp_format(all_history_before_codes_info[i][1], '%H:%M:%S'), tool.timestamp_format(all_history_before_codes_info[i - 1][1], '%H:%M:%S')) >= 15 * 60: return False, f"被顺位代码({pre_code}) 与上个代码涨停时间>=15分钟 ({all_history_before_codes_info[i]}##{all_history_before_codes_info[i - 1]})原始队列:{origin_history_before_codes_info}" else: return True, f"被顺位代码({pre_code}) 与上个代码涨停时间<15分钟 ({all_history_before_codes_info[i]}##{all_history_before_codes_info[i - 1]})原始队列:{origin_history_before_codes_info}" return False, f"没找到顺位代码({pre_code})的前排代码" else: # 代码为目标代码 pass else: # 代码为目标代码 pass return True, f"满足买入需求: 前排代码-{current_before_codes_info} 原始队列:{origin_history_before_codes_info}" @classmethod def __is_re_limit_up(cls, code, block): """ 是否是炸板回封可买 @param code: @param block: @return: """ # 获取身位 current_index, current_before_codes_info = cls.__get_current_index(code, block, set(), limit_up_time=cls.__get_limit_up_timestamp( code)) history_index, history_before_codes_info = cls.__get_history_index(code, block, set()) if current_index != history_index: return False, f"有其他炸板" if current_index > 1: return False, f"不是前2的板块" history_codes = set() # 获取板块炸板情况 for k in LimitUpDataConstant.history_limit_up_datas: _code = k[3] blocks = LimitUpDataConstant.get_blocks_with_history(_code) blocks = BlockMapManager().filter_blocks(blocks) # 不是这个板块 if block in blocks: history_codes.add(_code) if len(history_codes) <= 4: return False, f"板块历史涨停小于4个:{history_codes}" # 获取当前涨停数量 current_codes = set() for k in LimitUpDataConstant.current_limit_up_datas: _code = k[0] blocks = LimitUpDataConstant.get_blocks_with_history(_code) if not blocks: blocks = set() blocks = BlockMapManager().filter_blocks(blocks) # 不是这个板块 if block in blocks: current_codes.add(_code) current_codes.add(code) diff = history_codes - current_codes if diff: return False, f"板块炸板不止当前票:{diff}" return True, "" @classmethod def __get_limit_up_timestamp(cls, code): """ 获取代码的涨停时间,默认当前时间 @param code: @return: """ limit_up_timestamp = LimitUpDataConstant.get_first_limit_up_time(code) if not limit_up_timestamp: limit_up_timestamp = time.time() return limit_up_timestamp @classmethod def get_code_kpl_blocks(cls, code): blocks = KPLCodeJXBlockManager().get_jx_blocks_radical(code) if blocks is None: blocks = set() # 将获取涨停原因与涨停推荐 keys = TargetCodePlateKeyManager().get_plate_keys(code, contains_today=True) if keys and keys[0]: blocks |= set(keys[0]) return blocks @classmethod def get_code_blocks(cls, code): """ 获取目标代码的板块 @param code: @return: 过滤后的板块,过滤前的板块 """ # blocks = cls.get_code_kpl_blocks(code) # match_blocks, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks) # match_blocks -= constant.KPL_INVALID_BLOCKS # fblocks = match_blocks & RealTimeKplMarketData.get_top_market_jingxuan_blocks() # if not fblocks: # fblocks = set() # match_blocks_3, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks, same_count=3) # if match_blocks_3: # match_blocks_3 -= constant.KPL_INVALID_BLOCKS # fblocks |= match_blocks_3 # # 获取开盘啦历史涨停原因 # kpl_history_blocks = CodesHisReasonAndBlocksManager().get_history_blocks_cache(code) # if kpl_history_blocks: # fblocks |= BlockMapManager().filter_blocks(kpl_history_blocks) # jx_out_blocks = RealTimeKplMarketData.get_top_market_jingxuan_out_blocks() # if jx_out_blocks: # fblocks -= jx_out_blocks # # return fblocks, match_blocks # 新版本 before_fblocks = LimitUpCodesBlockRecordManager().get_radical_buy_blocks(code) if not before_fblocks: before_fblocks = set() fblocks = BlockMapManager().filter_blocks(before_fblocks) if fblocks: fblocks -= constant.KPL_INVALID_BLOCKS return fblocks, before_fblocks @classmethod def is_radical_buy(cls, code, yesterday_limit_up_codes): """ 是否是激进买 @param code: @return: {激进买的板块}, 原因 """ # 计算 # 获取开1的板块 open_limit_up_code_dict = kpl_data_constant.open_limit_up_code_dict_for_radical_buy open_limit_up_blocks = set() if open_limit_up_code_dict: for c in open_limit_up_code_dict: open_limit_up_blocks |= open_limit_up_code_dict[c][1] # 获取代码的板块 keys_, info = cls.get_code_blocks(code) if not keys_: return set(), "没获取到板块交集" match_blocks = open_limit_up_blocks & keys_ can_buy_blocks = set() fmsges = [] msges = [] for b in match_blocks: # 判断板块是否该激进买 result = cls.__is_radical_buy_with_open_limitup(code, b, yesterday_limit_up_codes) if result[0]: can_buy_blocks.add(b) msges.append(f"【{b}】:{result[1]}") fmsges.append("开1判断##" + ",".join(msges)) if not can_buy_blocks: msges.clear() for b in keys_: # 板块快速启动 result = cls.__is_radical_buy_with_block_up(code, b, yesterday_limit_up_codes) if result[0]: can_buy_blocks.add(b) msges.append(f"【{b}】:{result[1]}") fmsges.append("板块快速启动判断##" + ",".join(msges)) if not can_buy_blocks: msges.clear() for b in keys_: result = cls.__is_re_limit_up(code, b) if result[0]: can_buy_blocks.add(b) msges.append(f"【{b}】:{result[1]}") fmsges.append("板块回封判断##" + ",".join(msges)) # 如果能扫入就需要获取代码在板块中的身位 # if can_buy_blocks: # excude_codes = set() # if kpl_data_constant.open_limit_up_code_dict_for_radical_buy: # excude_codes |= kpl_data_constant.open_limit_up_code_dict_for_radical_buy.keys() # # 剔除开1的代码 # for b in keys_: # history_index, history_before_codes_info = cls.__get_history_index(code, b, yesterday_limit_up_codes, # excude_codes) # if history_index >= 4: # return set(), f"在【{b}】中身位({history_index + 1})靠后" return can_buy_blocks, " **** ".join(fmsges) if __name__ == "__main__": pass third_data/kpl_data_manager.py
@@ -17,7 +17,7 @@ from db import mysql_data_delegate as mysql_data, redis_manager_delegate as redis_manager from log_module.log import logger_kpl_limit_up_reason_change, logger_debug, logger_kpl_limit_up, \ logger_kpl_open_limit_up from third_data import kpl_util, kpl_api, kpl_data_constant from third_data import kpl_util, kpl_api from third_data.code_plate_key_manager import LimitUpCodesPlateKeyManager, CodesHisReasonAndBlocksManager # 代码对应的涨停原因保存 trade/buy_radical/radical_buy_data_manager.py
New file @@ -0,0 +1,985 @@ """ 激进买数据管理 """ import json import time import constant import l2_data_util from code_attribute import code_nature_analyse, code_volumn_manager, gpcode_manager from code_attribute.code_l1_data_manager import L1DataManager from db import redis_manager_delegate as redis_manager from db.redis_manager_delegate import RedisUtils from l2.l2_transaction_data_manager import BigOrderDealManager, HuaXinBuyOrderManager from log_module import async_log_util from log_module.log import logger_l2_radical_buy, logger_debug from third_data import kpl_data_manager, kpl_block_util, huaxin_l1_data_manager, kpl_util, kpl_data_constant from third_data.code_plate_key_manager import TargetCodePlateKeyManager, KPLCodeJXBlockManager from third_data.kpl_data_constant import LimitUpDataConstant, LimitUpCodesBlockRecordManager from third_data.third_blocks_manager import BlockMapManager from trade.buy_money_count_setting import RadicalBuyBlockCodeCountManager from trade.order_statistic import DealAndDelegateWithBuyModeDataManager from trade.trade_data_manager import RadicalBuyDealCodesManager from utils import tool, global_util class RadicalBuyDataManager: @classmethod def is_code_can_buy(cls, code, deal_codes=None, is_refered=False): """ 代码是否可以买(根据代码本身属性) @param deal_codes: 已经成交的代码 @param is_refered: 是否是参考票 @param code: 代码 @param total_sell_volume: 总卖量 @return: 是否可以买, 原因 """ k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) if k_format: if not k_format[13]: return False, "近60个交易日无涨停" if k_format[14]: # 昨天炸板,一律不买 return False, f"昨日炸板" # 获取涨停价 price = gpcode_manager.get_limit_up_price_as_num(code) if not price: # 获取现价 price = L1DataManager.get_l1_current_price(code) if price: if price < constant.MIN_CODE_RADICAL_BUY_PRICE or price > constant.MAX_CODE_RADICAL_BUY_PRICE: return False, "价格不满足需求" # 判断自由流通股本 zyltgb = global_util.zyltgb_map.get(code) if zyltgb: zyltgb_as_yi = round(zyltgb / 100000000, 2) zylt_can_buy = False for zy in constant.RADICAL_BUY_ZYLTGB_AS_YI_RANGES: if zy[0] <= zyltgb_as_yi <= zy[1]: zylt_can_buy = True break if not zylt_can_buy: return False, "自由流通市值不满足扫的范围" # 判断昨日是否跌幅过大 k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) if k_format and len(k_format) > 12 and k_format[12]: return False, "上个交易日跌幅过大" if gpcode_manager.BlackListCodeManager().is_in_cache(code): if deal_codes is not None and code in deal_codes: pass else: # 拉黑且不是已经买入性质的拉黑 return False, "已拉黑" if is_refered: # 参考票没有大单 volume_rate = code_volumn_manager.CodeVolumeManager().get_volume_rate(code, with_info=False) if volume_rate is None: volume_rate = 0.5 big_order_deal_enough = is_big_order_deal_enough(code, volume_rate) if not big_order_deal_enough[0] and big_order_deal_enough[2]: return False, "交易前两分钟大单不足" return True, "" @classmethod def big_order_deal(cls, code): """ 有大单成交 @param code: @param count: @return: """ if gpcode_manager.MustBuyCodesManager().is_in_cache(code): return cls.place_order_success(code) @classmethod def place_order_success(cls, code): # 如果有大单成交就加红 volume_rate = code_volumn_manager.CodeVolumeManager().get_volume_rate(code, with_info=False) if volume_rate is None: volume_rate = 0.5 big_order_deal_enough = is_big_order_deal_enough(code, volume_rate) # BigOrderDealManager().get_total_buy_count(code) if big_order_deal_enough[0]: gpcode_manager.MustBuyCodesManager().add_code(code) class RadicalBuyBlockManager: """ 扫入买板块管理 """ # 上次的涨停代码 __last_limit_up_codes = set() # 记录代码的涨停时间 __limit_up_time_dict = {} # 炸板代码的总涨停时间 __total_limit_up_space_dict = {} # 当前涨停的代码 __current_limit_up_codes = set() @classmethod def set_current_limit_up_datas(cls, current_limit_up_datas): # 查询当前的涨停代码集合 codes = set([d[0] for d in current_limit_up_datas]) cls.__current_limit_up_codes = codes try: # 炸板代码 break_limit_up_codes = cls.__last_limit_up_codes - codes # 新涨停的代码 new_limit_up_codes = codes - cls.__last_limit_up_codes if new_limit_up_codes: for code in new_limit_up_codes: if code not in cls.__limit_up_time_dict: cls.__limit_up_time_dict[code] = time.time() if break_limit_up_codes: # 记录总涨停时间 for bc in break_limit_up_codes: if bc in cls.__limit_up_time_dict: space = tool.trade_time_sub(tool.get_now_time_str(), tool.to_time_str(cls.__limit_up_time_dict[bc])) if bc not in cls.__total_limit_up_space_dict: cls.__total_limit_up_space_dict[bc] = 0 cls.__total_limit_up_space_dict[bc] = cls.__total_limit_up_space_dict[bc] + space logger_debug.info(f"炸板代码涨停时间:{bc}-{cls.__total_limit_up_space_dict[bc]}") cls.__limit_up_time_dict.pop(bc) except Exception as e: logger_debug.exception(e) finally: cls.__last_limit_up_codes = codes cls.compute_open_limit_up_code_dict_for_radical_buy(current_limit_up_datas) @classmethod def compute_open_limit_up_code_dict_for_radical_buy(cls, current_limit_up_datas): """ 计算开1的代码信息,不包含5板以上的 @param current_limit_up_datas: @return: """ timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range temp_dict = {} for d in current_limit_up_datas: code = d[0] # d: (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额,涨停原因代码,涨停原因代码数量) # 计算是否开1 if int(d[2]) >= timestamp_end or int(d[2]) < timestamp_start: continue buy1_money = huaxin_l1_data_manager.get_buy1_money(code) # 买1是否大于5000w if not constant.TEST: if not buy1_money or buy1_money < 5e7: continue if not tool.is_can_buy_code(code): continue blocks = {d[5]} if d[6]: blocks |= set(d[6].split("、")) blocks -= constant.KPL_INVALID_BLOCKS # 过滤 blocks = BlockMapManager().filter_blocks(blocks) # 开1剔除4板以上的 high_level = kpl_util.get_high_level_count(d[4]) if high_level >= 4: continue temp_dict[code] = (high_level, blocks) kpl_data_constant.open_limit_up_code_dict_for_radical_buy = temp_dict @classmethod def __get_current_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None, limit_up_time=None, ignore_open_limit_up=True): """ 获取当前涨停身位 @param code: @param block: @param yesterday_limit_up_codes: @param exclude_codes: @param limit_up_time: @param ignore_open_limit_up: 是否忽略开1的代码 @return: 索引,前排代码信息([(代码, 涨停时间)]) """ if exclude_codes is None: exclude_codes = set() current_index = 0 block_codes_infos = [] timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range if limit_up_time is None: limit_up_time = time.time() for k in LimitUpDataConstant.current_limit_up_datas: _code = k[0] if _code in exclude_codes: continue blocks = LimitUpDataConstant.get_blocks_with_history(_code) if not blocks: blocks = set() if _code == code: # 获取当前代码涨停时间 limit_up_time = int(k[2]) continue # 不是这个板块 if block not in blocks: continue # 剔除4板以上的板 if kpl_util.get_high_level_count(k[4]) >= 4 and len(blocks) > 1: continue if not tool.is_can_buy_code(_code): continue # 剔除开1的数据 if ignore_open_limit_up and timestamp_start <= int(k[2]) < timestamp_end: continue # 剔除高位板 if _code in yesterday_limit_up_codes: continue # 代码.涨停时间 block_codes_infos.append((_code, int(k[2]))) block_codes_infos.append((code, limit_up_time)) block_codes_infos.sort(key=lambda x: x[1]) before_codes_info = [] for i in range(0, len(block_codes_infos)): if block_codes_infos[i][0] == code: current_index = i break else: before_codes_info.append(block_codes_infos[i]) return current_index, before_codes_info @classmethod def __get_history_index(cls, code, block, yesterday_limit_up_codes, exclude_codes=None, ignore_open_limit_up=True): """ 获取历史涨停身位 @param code: @param block: @param yesterday_limit_up_codes: @param exclude_codes: @param ignore_open_limit_up: 是否忽略开1代码 @return: """ if exclude_codes is None: exclude_codes = set() history_index = 0 block_codes_infos = [] # 开1时间范围 timestamp_start, timestamp_end = kpl_block_util.open_limit_up_time_range limit_up_time = time.time() limit_up_space_ge_60s_codes = set() for k in LimitUpDataConstant.history_limit_up_datas: _code = k[3] if _code in exclude_codes: continue if _code == code: # 获取当前代码涨停时间 limit_up_time = int(k[5]) continue blocks = LimitUpDataConstant.get_blocks_with_history(_code) # 不是这个板块 if block not in blocks: continue # 剔除4板以上且板块数量大于1个 if kpl_util.get_high_level_count(k[12]) >= 4 and len(blocks) > 1: continue if not tool.is_can_buy_code(_code): continue # 剔除开1的数据 if ignore_open_limit_up and timestamp_start <= int(k[5]) < timestamp_end: continue # 剔除高位板 if _code in yesterday_limit_up_codes: continue # 剔除炸板代码持续涨停时间小于1分钟的代码 且 只能用于不排除前2条数据 if _code not in cls.__current_limit_up_codes and _code in cls.__total_limit_up_space_dict and \ cls.__total_limit_up_space_dict[_code] < 60 and not exclude_codes and len( limit_up_space_ge_60s_codes) < 3: limit_up_space_ge_60s_codes.add(_code) continue # 代码,涨停时间 block_codes_infos.append((_code, int(k[5]))) block_codes_infos.append((code, limit_up_time)) block_codes_infos.sort(key=lambda x: x[1]) before_codes_info = [] for i in range(0, len(block_codes_infos)): if block_codes_infos[i][0] == code: history_index = i break else: before_codes_info.append(block_codes_infos[i]) return history_index, before_codes_info @classmethod def __is_radical_buy_with_open_limitup(cls, code, block, yesterday_limit_up_codes): """ 是否需要激进买(某个板块开1) 1.有>=2个开1买老2 2.有1个开1的买老3 @param code: @param block: @param yesterday_limit_up_codes 昨日涨停代码 @return: """ # 9:45点之前涨停的才能买入 # 获取当前代码的涨停时间 limit_up_timestamp = cls.__get_limit_up_timestamp(code) if tool.get_now_time_as_int() > 100000: return False, "超过生效时间" # 根据板块聚合数据 open_limit_up_block_codes_dict = {} for c in kpl_data_constant.open_limit_up_code_dict_for_radical_buy: blocks = kpl_data_constant.open_limit_up_code_dict_for_radical_buy[c][1] for b in blocks: if b not in open_limit_up_block_codes_dict: open_limit_up_block_codes_dict[b] = set() open_limit_up_block_codes_dict[b].add(c) if block not in open_limit_up_block_codes_dict: return False, "板块未开1" open_limit_up_block_codes = list(open_limit_up_block_codes_dict.get(block)) count = len(open_limit_up_block_codes) # ----获取历史身位---- history_index, history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes) # ----获取实时身位---- current_index, current_before_codes_info = cls.__get_current_index(code, block, yesterday_limit_up_codes, limit_up_time=limit_up_timestamp) exclude_codes = set() # 是否为强势二板开1:该代码所有的慨念必须都为二板开1且开1的只能有他自己 is_strong_2_level = count == 1 and \ kpl_data_constant.open_limit_up_code_dict_for_radical_buy[open_limit_up_block_codes[0]][ 0] == 2 if is_strong_2_level: _code = open_limit_up_block_codes[0] blocks = LimitUpDataConstant.get_blocks_with_history(_code) if blocks: # 所有的慨念的开1代码必须只有他自己 for b in blocks: temp_codes = open_limit_up_block_codes_dict.get(b) if temp_codes and len(temp_codes) > 1: is_strong_2_level = False break if count >= 2 or is_strong_2_level: # 开始数量大于2个或者只有一个2板开1 exclude_codes.clear() else: # 只有一个开1 # 获取包含高位板的身位 # ----获取历史身位---- history_index, history_before_codes_info = cls.__get_history_index(code, block, set()) # ----获取实时身位---- current_index, current_before_codes_info = cls.__get_current_index(code, block, set(), limit_up_time=limit_up_timestamp) if history_before_codes_info and current_before_codes_info and history_before_codes_info[0][0] == \ current_before_codes_info[0][0]: # 排除第一个非开1数据 exclude_codes = {history_before_codes_info[0][0]} else: return False, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}" # 获取主板的身位(已经排除了开1的代码) history_index, history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes, exclude_codes=exclude_codes) # 过滤不正的原因 history_index, history_before_codes_info = cls.__filter_before_codes(block, history_index, history_before_codes_info, yesterday_limit_up_codes) # 买首板老大/老二 # 首板老大不能买时可买老二 if history_index > 1: return False, f"开1数量:{count},非开1首板身位不匹配:历史-{history_index + 1} 实时-{current_index + 1}" if history_index == 1: # 当前代码为老2,要判断老大是否可买 if RadicalBuyDataManager.is_code_can_buy(history_before_codes_info[0][0], DealAndDelegateWithBuyModeDataManager().get_deal_codes(), is_refered=True)[0]: return False, f"开1数量:{count},前排代码可买:{history_before_codes_info[0]}" return True, f"开1数量:{count},前排代码不可买:{history_before_codes_info[0]},历史前排-{history_before_codes_info},开1代码-{open_limit_up_block_codes}" return True, f"开1数量:{count},历史-{history_index + 1} 实时-{current_index + 1}, 前排代码-{current_before_codes_info}, 开1代码-{open_limit_up_block_codes}" @classmethod def __filter_before_codes(cls, block, index, before_codes_info, yesterday_codes): """ 过滤前排涨停原因不正/不算身位的代码 @param code: @param block:板块 @param index: 目标代码位置 @param before_codes_info: [(代码, 涨停时间戳)] @return: 过滤之后的 (index, before_codes_info) """ try: if index == 0 or not before_codes_info: return index, before_codes_info temp_index = index temp_before_codes_info = [] deal_codes = RadicalBuyDealCodesManager().get_deal_codes() # 已经下单过的代码 placed_order_codes = set() max_count = RadicalBuyBlockCodeCountManager().get_block_code_count(block) for b in before_codes_info: # 当作目标票获取扫入板块 code_ = b[0] blocks = LimitUpCodesBlockRecordManager().get_radical_buy_blocks(code_) blocks = BlockMapManager().filter_blocks(blocks) need_delete = False # 判断原因不正 if block not in blocks and b[0] not in yesterday_codes: # 首板涨停原因不正 need_delete = True # 判断是否是不计算身位 if not need_delete: if ExcludeIndexComputeCodesManager.is_in_cache(code_): need_delete = True # 判断是不是扫了没有扫进入 if not need_delete: # 最多排除max_count个 if code_ in BlockPlaceOrderRecordManager().get_codes() and code_ not in deal_codes and len( placed_order_codes) < max_count: need_delete = True placed_order_codes.add(code_) if need_delete: temp_index -= 1 else: temp_before_codes_info.append(b) return temp_index, temp_before_codes_info except Exception as e: async_log_util.error(logger_debug, f"扫入板块过滤出错:{str(e)}") return index, before_codes_info @classmethod def __is_radical_buy_with_block_up(cls, code, block, yesterday_limit_up_codes): """ 是否激进买(板块突然涨起来) 1.老二和老三的涨停时间相差5分钟内 2.老三不能买顺位到老四(老四与老三相差10分钟内) 3.前2个票不能炸板(历史身位与现在身位一致) 4.除开前两个代码可买老1与老2 5.买老2的情况:老1不满足买入条件 @param code: @param block: @param yesterday_limit_up_codes: @return: """ # 获取当前代码的涨停时间 limit_up_timestamp = cls.__get_limit_up_timestamp(code) # 获取当前的板块 current_index, current_before_codes_info = cls.__get_current_index(code, block, set(), limit_up_time=limit_up_timestamp) current_before_codes = [x[0] for x in current_before_codes_info] if len(current_before_codes_info) < 2: return False, f"前排代码小于2个:{current_before_codes_info}" # 当前代码开1不能买 if limit_up_timestamp < kpl_block_util.open_limit_up_time_range[1]: return False, f"当前代码开1" if tool.trade_time_sub(tool.timestamp_format(limit_up_timestamp, '%H:%M:%S'), tool.timestamp_format(current_before_codes_info[-1][1], '%H:%M:%S')) >= 10 * 60: return False, f"距离上个代码涨停已过去10分钟({current_before_codes_info[-1]})" # 包含高位板的整体排序 all_history_index, all_history_before_codes_info = cls.__get_history_index(code, block, set()) all_history_before_codes = [x[0] for x in all_history_before_codes_info] # 前两个代码是否有炸板 dif_codes = set(all_history_before_codes[:2]) - set(current_before_codes[:2]) if dif_codes: return False, f"前2代码有炸板:{dif_codes}, 前排代码:{all_history_before_codes}" # 前排代码炸板不能>=2个 dif_codes = set(all_history_before_codes) - set(current_before_codes) if len(dif_codes) >= 2: return False, f"板块前排有{len(dif_codes)}个炸板" exclude_codes = set() for x in current_before_codes_info: if x[1] < kpl_block_util.open_limit_up_time_range[1]: exclude_codes.add(x[0]) # 除去前二代码与开1代码之后是否为首板老大:所有开1的视为1个 open_count = len(exclude_codes) if open_count > 0 and open_count + 1 <= len(current_before_codes): # 前排有开1 exclude_codes |= set(current_before_codes[open_count:open_count + 1]) else: exclude_codes |= set(current_before_codes[:2]) open_limit_up_code_dict = kpl_data_constant.open_limit_up_code_dict_for_radical_buy if open_limit_up_code_dict: exclude_codes |= set(open_limit_up_code_dict.keys()) origin_history_index, origin_history_before_codes_info = cls.__get_history_index(code, block, yesterday_limit_up_codes, exclude_codes) # 过滤不正的原因 history_index, history_before_codes_info = cls.__filter_before_codes(block, origin_history_index, origin_history_before_codes_info, yesterday_limit_up_codes) # 获取本板块买入代码的最大数量 max_count = RadicalBuyBlockCodeCountManager().get_block_code_count(block) if history_index > max_count: return False, f"排除前2,目标代码位于历史身位-{history_index + 1},前排代码:{history_before_codes_info}, 板块最多可买{max_count}" if max_count == 1: if history_index == 1: # 首板老2,判断前面的老大是否是属于不能买的范畴 pre_code = history_before_codes_info[0][0] # pre_code不能买,才能买 if RadicalBuyDataManager.is_code_can_buy(pre_code, DealAndDelegateWithBuyModeDataManager().get_deal_codes(), is_refered=True)[0]: # TODO 前排代码可买而没有买成功的可继续下单 deal_codes = RadicalBuyDealCodesManager().get_deal_codes() if pre_code in deal_codes: return False, f"前排代码已成交:{pre_code}" # 前面一个代码不能买,前一个代码必须与前前个代码涨停时间相差15分钟内 for i in range(len(all_history_before_codes_info) - 1, -1, -1): if all_history_before_codes_info[i][0] == pre_code: if tool.trade_time_sub(tool.timestamp_format(all_history_before_codes_info[i][1], '%H:%M:%S'), tool.timestamp_format(all_history_before_codes_info[i - 1][1], '%H:%M:%S')) >= 15 * 60: return False, f"被顺位代码({pre_code}) 与上个代码涨停时间>=15分钟 ({all_history_before_codes_info[i]}##{all_history_before_codes_info[i - 1]})" else: return True, f"被顺位代码({pre_code}) 与上个代码涨停时间<15分钟 ({all_history_before_codes_info[i]}##{all_history_before_codes_info[i - 1]})" return False, f"没找到顺位代码({pre_code})的前排代码" else: # 代码为目标代码 pass else: # 代码为目标代码 pass return True, f"满足买入需求: 实时前排代码-{current_before_codes_info} 历史前排代码-{history_before_codes_info}" @classmethod def __is_re_limit_up(cls, code, block): """ 是否是炸板回封可买 @param code: @param block: @return: """ # 获取身位 current_index, current_before_codes_info = cls.__get_current_index(code, block, set(), limit_up_time=cls.__get_limit_up_timestamp( code)) history_index, history_before_codes_info = cls.__get_history_index(code, block, set()) if current_index != history_index: return False, f"有其他炸板" if current_index > 1: return False, f"不是前2的板块" history_codes = set() # 获取板块炸板情况 for k in LimitUpDataConstant.history_limit_up_datas: _code = k[3] blocks = LimitUpDataConstant.get_blocks_with_history(_code) blocks = BlockMapManager().filter_blocks(blocks) # 不是这个板块 if block in blocks: history_codes.add(_code) if len(history_codes) <= 4: return False, f"板块历史涨停小于4个:{history_codes}" # 获取当前涨停数量 current_codes = set() for k in LimitUpDataConstant.current_limit_up_datas: _code = k[0] blocks = LimitUpDataConstant.get_blocks_with_history(_code) if not blocks: blocks = set() blocks = BlockMapManager().filter_blocks(blocks) # 不是这个板块 if block in blocks: current_codes.add(_code) current_codes.add(code) diff = history_codes - current_codes if diff: return False, f"板块炸板不止当前票:{diff}" return True, "" @classmethod def __get_limit_up_timestamp(cls, code): """ 获取代码的涨停时间,默认当前时间 @param code: @return: """ limit_up_timestamp = LimitUpDataConstant.get_first_limit_up_time(code) if not limit_up_timestamp: limit_up_timestamp = time.time() return limit_up_timestamp @classmethod def get_code_kpl_blocks(cls, code): blocks = KPLCodeJXBlockManager().get_jx_blocks_radical(code) if blocks is None: blocks = set() # 将获取涨停原因与涨停推荐 keys = TargetCodePlateKeyManager().get_plate_keys(code, contains_today=True) if keys and keys[0]: blocks |= set(keys[0]) return blocks @classmethod def get_code_blocks(cls, code): """ 获取目标代码的板块 @param code: @return: 过滤后的板块,过滤前的板块 """ # blocks = cls.get_code_kpl_blocks(code) # match_blocks, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks) # match_blocks -= constant.KPL_INVALID_BLOCKS # fblocks = match_blocks & RealTimeKplMarketData.get_top_market_jingxuan_blocks() # if not fblocks: # fblocks = set() # match_blocks_3, info = CodeThirdBlocksManager().get_intersection_blocks_info(code, blocks, same_count=3) # if match_blocks_3: # match_blocks_3 -= constant.KPL_INVALID_BLOCKS # fblocks |= match_blocks_3 # # 获取开盘啦历史涨停原因 # kpl_history_blocks = CodesHisReasonAndBlocksManager().get_history_blocks_cache(code) # if kpl_history_blocks: # fblocks |= BlockMapManager().filter_blocks(kpl_history_blocks) # jx_out_blocks = RealTimeKplMarketData.get_top_market_jingxuan_out_blocks() # if jx_out_blocks: # fblocks -= jx_out_blocks # # return fblocks, match_blocks # 新版本 before_fblocks = LimitUpCodesBlockRecordManager().get_radical_buy_blocks(code) if not before_fblocks: before_fblocks = set() fblocks = BlockMapManager().filter_blocks(before_fblocks) if fblocks: fblocks -= constant.KPL_INVALID_BLOCKS return fblocks, before_fblocks @classmethod def is_radical_buy(cls, code, yesterday_limit_up_codes): """ 是否是激进买 @param code: @return: {激进买的板块}, 原因 """ # 计算 # 获取开1的板块 open_limit_up_code_dict = kpl_data_constant.open_limit_up_code_dict_for_radical_buy open_limit_up_blocks = set() if open_limit_up_code_dict: for c in open_limit_up_code_dict: open_limit_up_blocks |= open_limit_up_code_dict[c][1] # 获取代码的板块 keys_, info = cls.get_code_blocks(code) if not keys_: return set(), "没获取到板块交集" match_blocks = open_limit_up_blocks & keys_ can_buy_blocks = set() fmsges = [] msges = [] for b in match_blocks: # 判断板块是否该激进买 result = cls.__is_radical_buy_with_open_limitup(code, b, yesterday_limit_up_codes) if result[0]: can_buy_blocks.add(b) msges.append(f"【{b}】:{result[1]}") fmsges.append("开1判断##" + ",".join(msges)) if not can_buy_blocks: msges.clear() for b in keys_: # 板块快速启动 result = cls.__is_radical_buy_with_block_up(code, b, yesterday_limit_up_codes) if result[0]: can_buy_blocks.add(b) msges.append(f"【{b}】:{result[1]}") fmsges.append("板块快速启动判断##" + ",".join(msges)) if not can_buy_blocks: msges.clear() for b in keys_: result = cls.__is_re_limit_up(code, b) if result[0]: can_buy_blocks.add(b) msges.append(f"【{b}】:{result[1]}") fmsges.append("板块回封判断##" + ",".join(msges)) # 如果能扫入就需要获取代码在板块中的身位 # if can_buy_blocks: # excude_codes = set() # if kpl_data_constant.open_limit_up_code_dict_for_radical_buy: # excude_codes |= kpl_data_constant.open_limit_up_code_dict_for_radical_buy.keys() # # 剔除开1的代码 # for b in keys_: # history_index, history_before_codes_info = cls.__get_history_index(code, b, yesterday_limit_up_codes, # excude_codes) # if history_index >= 4: # return set(), f"在【{b}】中身位({history_index + 1})靠后" return can_buy_blocks, " **** ".join(fmsges) class ExcludeIndexComputeCodesManager: """ 排除身位计算管理器(始终都要排除) """ __codes_cache = set() @classmethod def add_code(cls, code): cls.__codes_cache.add(code) @classmethod def remove_code(cls, code): cls.__codes_cache.discard(code) @classmethod def get_all_codes(cls): return cls.__codes_cache @classmethod def is_in_cache(cls, code): return code in cls.__codes_cache class BlockPlaceOrderRecordManager: """ 板块下单记录 """ __db = 2 __redis_manager = redis_manager.RedisManager(2) __instance = None # 下单板块的代码记录 __block_record_codes_dict = {} __codes = set() def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance = super(BlockPlaceOrderRecordManager, cls).__new__(cls, *args, **kwargs) cls.__load_data() return cls.__instance @classmethod def __get_redis(cls): return cls.__redis_manager.getRedis() @classmethod def __load_data(cls): val = RedisUtils.get(cls.__get_redis(), "radical_place_order_block_records") if val: val = json.loads(val) for v in val: cls.__block_record_codes_dict[v[0]] = set(v[1]) cls.__codes |= set(v[1]) def add_record(self, code, blocks): """ 添加下单记录 @param code: @param blocks: @return: """ if blocks: for b in blocks: if b not in self.__block_record_codes_dict: self.__block_record_codes_dict[b] = set() self.__block_record_codes_dict[b].add(code) datas = [(b, list(self.__block_record_codes_dict[b])) for b in self.__block_record_codes_dict] RedisUtils.set_async(self.__db, "radical_place_order_block_records", tool.get_expire(), json.dumps(datas)) self.__codes.add(code) def get_block_codes(self, block): """ 获取板块下过单的代码 @param block: @return: """ if block in self.__block_record_codes_dict: return self.__block_record_codes_dict[block] return set() def get_codes(self): return self.__codes def is_big_order_deal_enough(code, volume_rate): """ 大单成交是否足够 @param code: @param volume_rate: @return: 大单是否足够, 原因, 是否是短时生效 """ limit_up_price = gpcode_manager.get_limit_up_price_as_num(code) refer_volume = code_volumn_manager.CodeVolumeManager().get_max_volume_in_5days(code) if refer_volume is None: refer_volume = 0 money_y = int(refer_volume * limit_up_price / 1e8) money_y = min(money_y, 50) money_y = max(money_y, 5) before_time = tool.get_now_time_as_int() < 93200 # 计算大单参考数量 threshold_count = 1 # int(round(0.4 * money_y)) if before_time: threshold_count = int(round(0.4 * money_y * 1.5)) threshold_money = threshold_count * 299 * 10000 if volume_rate >= 0.5 or True: # 按量大于50%算 # 当换手量>50%时,则,不需要每次扫入时需要≥2笔大单,而是累计需要≥2笔大单即可 deal_big_order_money = BigOrderDealManager().get_total_buy_money(code) try: # 获取正在成交的订单 dealing_order_info = HuaXinBuyOrderManager().get_dealing_order_info(code) threshold_big_money = l2_data_util.get_big_money_val(limit_up_price, tool.is_ge_code(code)) if dealing_order_info and dealing_order_info[2] >= threshold_big_money: # 正在成交的订单是大单 deal_big_order_money += dealing_order_info[2] except Exception as e: async_log_util.info(logger_l2_radical_buy, f"计算正在成交大单出错:{str(e)}") if deal_big_order_money >= threshold_money: return True, f"量比-{volume_rate}, 总大单成交金额({deal_big_order_money})>={threshold_money}", before_time else: return False, f"量比-{volume_rate}, 总大单成交金额({deal_big_order_money})<{threshold_money}", before_time else: current_big_order_deal_count = EveryLimitupBigDealOrderManager.get_big_buy_deal_order_count(code) if current_big_order_deal_count >= threshold_count: return True, f"量比-{volume_rate}, 本次大单成交数量({current_big_order_deal_count})>={threshold_count}", before_time else: return False, f"量比-{volume_rate}, 本次大单成交数量({current_big_order_deal_count})<{threshold_count}", before_time class EveryLimitupBigDealOrderManager: """ 每次上板的大单管理 """ # 成交大单的订单号:{"code":{"order_no",...}} __deal_big_order_nos_dict = {} @classmethod def open_limit_up(cls, code): if code in cls.__deal_big_order_nos_dict: cls.__deal_big_order_nos_dict[code].clear() @classmethod def add_big_buy_order_deal(cls, code, order_nos: list): if code not in cls.__deal_big_order_nos_dict: cls.__deal_big_order_nos_dict[code] = set() for order_no in order_nos: cls.__deal_big_order_nos_dict[code].add(order_no) @classmethod def get_big_buy_deal_order_count(cls, code): if code in cls.__deal_big_order_nos_dict: return len(cls.__deal_big_order_nos_dict[code]) return 0 def __get_deal_reasons(code): """ 获取成交的原因 @param code: @return: """ reasons = set() # 当前的涨停原因 limit_up_reason = kpl_data_manager.LimitUpDataConstant.get_limit_up_reason_with_history(code) if limit_up_reason and limit_up_reason in constant.KPL_INVALID_BLOCKS: limit_up_reason = None # 如果涨停原因为空就需要获取上次激进买的原因 if limit_up_reason: reasons.add(limit_up_reason) if not limit_up_reason: radical_buy_deal_blocks = RadicalBuyDealCodesManager.radical_buy_blocks_dict.get(code) if radical_buy_deal_blocks: reasons |= radical_buy_deal_blocks return reasons def is_block_can_radical_buy(code, radical_buy_blocks, deal_codes): """ 板块是否还能买入:如果有身位更加靠前的买入一个了可以下单 @param code: @param radical_buy_blocks: 板块 @param deal_codes: 成交的代码 @return: """ # 原因下面的代码个数 deal_reason_codes = {} for dc in deal_codes: # 获取涨停原因 reasons = __get_deal_reasons(dc) for r in reasons: if r not in deal_reason_codes: deal_reason_codes[r] = set() deal_reason_codes[r].add(dc) async_log_util.info(logger_l2_radical_buy, f"已经成交的板块:{code}-{deal_reason_codes.keys()}") f_buy_blocks = set() for b in radical_buy_blocks: # 获取板块的最大买入个数 max_count = RadicalBuyBlockCodeCountManager().get_block_code_count(b) if b in deal_reason_codes and len(deal_reason_codes[b]) >= max_count: if len(deal_reason_codes[b]) >= max_count + 1: continue else: # 当前代码身位比成交代码身位靠前的可以多成交一个代码 is_front = False limit_up_timestamp = LimitUpDataConstant.get_first_limit_up_time(code) if not limit_up_timestamp: limit_up_timestamp = time.time() for c in deal_reason_codes[b]: # 获取涨停时间 timestamp = LimitUpDataConstant.get_first_limit_up_time(c) if timestamp and timestamp > limit_up_timestamp: # 比目标代码后涨停 is_front = True async_log_util.info(logger_l2_radical_buy, f"前排代码还可买入:{b}-{code},后排成交代码-{c}") break if not is_front: continue f_buy_blocks.add(b) async_log_util.info(logger_l2_radical_buy, f"还可以买入的板块:{code}-{f_buy_blocks}") return f_buy_blocks def get_deal_codes_by_block(block, deal_codes): """ 获取板块成交的代码 @param block: @param deal_codes: @return: """ codes = set() for dc in deal_codes: # 获取涨停原因 reasons = __get_deal_reasons(dc) if block in reasons: codes.add(block) return codes def get_volume_rate_threshold(code, volume_rate): """ 获取吃卖1的比例 @param code: 代码 @param volume_rate:量比 @return: """ fvolume_rate = volume_rate if volume_rate <= 0.05: fvolume_rate = 0.05 elif volume_rate > 1: fvolume_rate = 1 if tool.is_sh_code(code): return round(0 - 0.44 * fvolume_rate + 0.822, 3) else: return round(0 - 0.44 * fvolume_rate + 0.722, 3) trade/buy_radical/radical_buy_strategy.py
File was renamed from trade/radical_buy_strategy.py @@ -2,17 +2,14 @@ 激进买策略管理 """ # 上一个50W的起始时间:{code:"09:30:00.120"} import l2_data_util from code_attribute import code_volumn_manager, gpcode_manager from l2 import l2_data_manager from l2.huaxin import l2_huaxin_util from l2.l2_limitup_sell_data_manager import L2LimitUpSellDataManager from l2.l2_sell_manager import L2MarketSellManager from l2.l2_transaction_data_manager import HuaXinSellOrderStatisticManager, BigOrderDealManager, HuaXinBuyOrderManager from l2.l2_transaction_data_manager import HuaXinSellOrderStatisticManager from log_module import async_log_util from log_module.log import logger_l2_radical_buy, hx_logger_l2_transaction from trade import radical_buy_data_manager from trade.radical_buy_data_manager import EveryLimitupBigDealOrderManager from trade.buy_radical import radical_buy_data_manager from utils import tool # 不买入 trade/radical_buy_data_manager.py
File was deleted trade/trade_result_manager.py
@@ -12,10 +12,10 @@ from l2.l2_data_util import local_today_datas, L2DataUtil from l2.l2_sell_manager import L2MarketSellManager from log_module.log import logger_l2_error from trade.radical_buy_data_manager import RadicalBuyDataManager from trade.buy_radical.radical_buy_data_manager import RadicalBuyDataManager from trade.trade_data_manager import PlaceOrderCountManager from trade.trade_queue_manager import THSBuy1VolumnManager from utils import tool, buy_condition_util from utils import buy_condition_util __thsBuy1VolumnManager = THSBuy1VolumnManager()