"""
|
激进买策略管理
|
"""
|
# 上一个50W的起始时间:{code:"09:30:00.120"}
|
import time
|
|
from code_attribute import code_volumn_manager, gpcode_manager
|
from l2.code_price_manager import Buy1PriceManager
|
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
|
from log_module import async_log_util
|
from log_module.log import logger_l2_radical_buy, hx_logger_l2_transaction, logger_l2_not_buy_reasons
|
from third_data import kpl_data_manager
|
from third_data.kpl_data_constant import LimitUpDataConstant, LimitUpCodesBlockRecordManager
|
from trade.buy_radical import radical_buy_data_manager, block_special_codes_manager
|
from trade.buy_radical.block_special_codes_manager import BlockSpecialCodesManager
|
from trade.buy_radical.radical_buy_data_manager import RadicalBuyBlockManager, TotalDealBigOrderThresholdMoneyManager
|
from trade.trade_data_manager import RadicalBuyDealCodesManager
|
from utils import tool, global_util
|
|
# 不买入
|
BUY_MODE_NONE = 0
|
# 直接买入
|
BUY_MODE_DIRECT = 1
|
# 根据L2买入
|
BUY_MODE_BY_L2 = 2
|
|
# 开始计时时间
|
__start_time_dict = {}
|
# 转换时间缓存
|
__huaxin_timestamp_convert_temp = {}
|
# 主动成交的累计金额
|
__deal_active_buy_total_money = {}
|
# 最近成交的买单信息{code:[订单号,量,金额]}
|
__latest_deal_active_buy_order = {}
|
|
|
def clear_data(code, force=False, market_time_str=None, msg=""):
|
"""
|
清除数据:下单过后/开板后清除数据
|
@param market_time_str: L2 market时间
|
@param force: 是否强制清除
|
@param code:
|
@return:
|
"""
|
if code in __latest_deal_active_buy_order:
|
__latest_deal_active_buy_order.pop(code)
|
|
if not force:
|
# 非强制清除数据要看大单成交是否足够
|
big_deal_info = radical_buy_data_manager.get_total_deal_big_order_info(code,
|
gpcode_manager.get_limit_up_price_as_num(
|
code))
|
if big_deal_info[0] > 0:
|
# 大单不够
|
force = True
|
|
if force:
|
# 如果比最近成交时间<=L2 market时间就视为数据延迟
|
if market_time_str and code in RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict:
|
if tool.trade_time_sub(market_time_str,
|
RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict[code][3]) <= 0:
|
async_log_util.info(logger_l2_radical_buy, f"L2market时间小于成交时间:{code}-{market_time_str}")
|
return
|
|
if __deal_active_buy_total_money.get(code):
|
async_log_util.info(logger_l2_radical_buy, f"清除涨停卖成交数据:{code}-{market_time_str}")
|
# 强制清除数据
|
if code in __deal_active_buy_total_money:
|
__deal_active_buy_total_money.pop(code)
|
# 清除L2下单信号
|
if code in RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict:
|
async_log_util.info(logger_l2_radical_buy, f"清除下单信号:{code}-{force}-{market_time_str} msg-{msg}")
|
RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict.pop(code)
|
|
|
def process_limit_up_active_buy_deal(code, transaction_datas, is_almost_open_limit_up=False,
|
no_left_limit_up_sell=False):
|
"""
|
计算抛压消耗之后是否能下单
|
@param code:
|
@param transaction_datas: # ((data['SecurityID'], data['TradePrice'], data['TradeVolume'],
|
# data['OrderTime'], data['MainSeq'], data['SubSeq'], data['BuyNo'],
|
# data['SellNo'], data['ExecType']))
|
@param is_almost_open_limit_up: 是否即将炸板,如果即将炸板就按照上板无大单处理
|
@return: 买入方式, 消息
|
"""
|
if is_almost_open_limit_up:
|
return BUY_MODE_BY_L2, f"即将炸板"
|
|
# ---------初始化-------------
|
if code not in __huaxin_timestamp_convert_temp:
|
__huaxin_timestamp_convert_temp[code] = {}
|
if code not in __deal_active_buy_total_money:
|
__deal_active_buy_total_money[code] = 0
|
if code not in __latest_deal_active_buy_order:
|
__latest_deal_active_buy_order[code] = ['', 0, 0]
|
for transaction_data in transaction_datas:
|
# 当遇到大单之后才需要计算累计成交
|
# 统计金额
|
money = transaction_data[1] * transaction_data[2]
|
price = transaction_data[1]
|
|
# 统计成交的买单
|
if __latest_deal_active_buy_order[code][0] == transaction_data[6]:
|
__latest_deal_active_buy_order[code][1] += transaction_data[2]
|
__latest_deal_active_buy_order[code][2] += money
|
else:
|
__latest_deal_active_buy_order[code] = [transaction_data[6], transaction_data[2], money]
|
|
if code not in __start_time_dict and False:
|
# 判断买单成交的金额,如果金额大于50w就作为计时起始点
|
if __latest_deal_active_buy_order[code][2] >= 500000:
|
# 设置计时起点,将当前的数据清零
|
__start_time_dict[code] = l2_huaxin_util.convert_time(transaction_data[3], with_ms=True)
|
__deal_active_buy_total_money[code] = __latest_deal_active_buy_order[code][2]
|
else:
|
__deal_active_buy_total_money[code] += money
|
# 已经开始计数
|
# THRESHOLD_TIME = 1000 if tool.is_sh_code(code) else 500
|
# huaxin_timestamp = transaction_data[3]
|
# time_str_with_ms = __huaxin_timestamp_convert_temp[code].get(huaxin_timestamp)
|
# if not time_str_with_ms:
|
# __huaxin_timestamp_convert_temp[code].clear()
|
# time_str_with_ms = l2_huaxin_util.convert_time(huaxin_timestamp, with_ms=True)
|
# __huaxin_timestamp_convert_temp[code][huaxin_timestamp] = time_str_with_ms
|
|
# if tool.trade_time_sub_with_ms(time_str_with_ms, __start_time_dict[code]) > THRESHOLD_TIME:
|
# __start_time_dict.pop(code)
|
# __deal_active_buy_total_money[code] = 0
|
# return BUY_MODE_NONE, f"距离上个大单成交超过{THRESHOLD_TIME}ms"
|
|
# 初次上板需要计算临时大单
|
is_first = radical_buy_data_manager.is_first_limit_up_buy(code)
|
if is_first:
|
# 首封下单
|
money_info_list = BigOrderDealManager().get_total_buy_data_list(code)
|
radical_buy_data_manager.BeforeSubDealBigOrderManager().set_temp_deal_big_orders(code, money_info_list)
|
|
price = transaction_datas[-1][1]
|
huaxin_timestamp = transaction_datas[-1][3]
|
|
# 判断是否可以扫入
|
can_direct_buy = False
|
human_setting_money = TotalDealBigOrderThresholdMoneyManager().get_money_cache(code)
|
if human_setting_money:
|
can_direct_buy = True
|
|
# 获取参考总卖额
|
refer_sell_data = L2MarketSellManager().get_refer_sell_data(code, l2_huaxin_util.convert_time(
|
huaxin_timestamp))
|
async_log_util.info(logger_l2_radical_buy, f"参考总卖额(备用):{code}-{refer_sell_data}")
|
|
# 参考总卖额
|
refer_sell_money = 0
|
|
if refer_sell_data:
|
refer_sell_money = refer_sell_data[1]
|
|
if refer_sell_money < 500e4:
|
# 参考抛压小于500万,直接根据L2下单
|
return BUY_MODE_BY_L2, f"总抛压小于500w({refer_sell_money})"
|
|
# 处于涨停卖的委托订单总手数
|
selling_num = L2LimitUpSellDataManager.get_delegating_sell_num(code)
|
if selling_num is None:
|
selling_num = 0
|
# 剩余涨停卖金额
|
left_limit_up_sell_money = selling_num * price
|
|
# 每次上板的大单与金额
|
big_order_count = radical_buy_data_manager.EveryLimitupBigDealOrderManager.get_big_buy_deal_order_count(code)
|
big_order_money = radical_buy_data_manager.EveryLimitupBigDealOrderManager.get_big_buy_deal_order_money(code)
|
|
total_lack_money_info = radical_buy_data_manager.get_total_deal_big_order_info(code,
|
gpcode_manager.get_limit_up_price_as_num(
|
code),
|
is_for_buy=True)
|
if total_lack_money_info[2] < 1e8:
|
# 要求的大单阈值必须>1亿才能直接扫入
|
can_direct_buy = False
|
|
if total_lack_money_info[0] > 0:
|
# 大单够了才能扫入
|
can_direct_buy = False
|
|
|
|
if total_lack_money_info and total_lack_money_info[2] > 1e8 and total_lack_money_info[0] <= 0:
|
# 要求的大单够了 以后,回封买,只要有两个大单成交了,立即下单
|
THRESHOLD_MONEY, is_temp_threshold_money = radical_buy_data_manager.BeforeSubDealBigOrderManager().get_big_order_threshold_info(
|
code)
|
if big_order_money > THRESHOLD_MONEY * 2 and can_direct_buy:
|
return BUY_MODE_DIRECT, f"有两个以上大单瞬时成交({big_order_money}/{THRESHOLD_MONEY * 2}), 大单足够"
|
|
if big_order_count >= 2:
|
# 判断大单是否满足
|
average_big_order_money = int(big_order_money / big_order_count)
|
# 如果均价涨幅小于7%,均大单等于299w
|
average_rate = Buy1PriceManager().get_average_rate(code)
|
if average_rate is not None and average_rate < 0.07:
|
average_big_order_money = 299 * 10000
|
threshold_left_sell_money = average_big_order_money
|
|
# 辨识度的票如果是非新题材的首封: 2个大单的折扣
|
# if block_special_codes_manager.BlockSpecialCodesManager().get_code_blocks(code) and radical_buy_data_manager.is_first_limit_up_buy(code) and not LimitUpCodesBlockRecordManager().has_new_block(
|
# code):
|
# threshold_left_sell_money = average_big_order_money * 2
|
# 判断是否可直接下单,不需要等到封单消耗
|
# if refer_sell_money >= 5e7 and is_first:
|
# # 大抛压,是首封
|
# zyltgb = global_util.zyltgb_map.get(code)
|
# if zyltgb and zyltgb > 50e8 and BlockSpecialCodesManager().get_code_blocks(code):
|
# # 自由市值>50亿,具有辨识度
|
# total_lack_money_info = radical_buy_data_manager.get_total_deal_big_order_info(code,
|
# gpcode_manager.get_limit_up_price_as_num(
|
# code),
|
# is_for_buy=True)
|
# if total_lack_money_info[0] <= 0 and total_lack_money_info[1] > 5e7 and total_lack_money_info[1] > \
|
# total_lack_money_info[2] * 1.5:
|
# # 大单足够,总成交金额是大单的1.2倍以上
|
# return BUY_MODE_DIRECT, f"首封下单抛压大、市值大、成交多、直接扫 卖1-{refer_sell_money} 大单-{total_lack_money_info}"
|
|
if threshold_left_sell_money > left_limit_up_sell_money:
|
# 剩余总卖小于均大单才能下单
|
# 如果是深证且卖一大于5000w可不判断大单是否满足
|
if tool.is_sz_code(code) and refer_sell_money >= 5e7 and can_direct_buy:
|
return BUY_MODE_DIRECT, f"剩余涨停总卖额-{left_limit_up_sell_money},均大单-{average_big_order_money}, 剩余阈值-{threshold_left_sell_money}, 总抛压大({refer_sell_money})"
|
else:
|
if total_lack_money_info[0] <= 0 and tool.is_sz_code(code) and can_direct_buy:
|
return BUY_MODE_DIRECT, f"剩余涨停总卖额-{left_limit_up_sell_money},均大单-{average_big_order_money}, 大单足够"
|
else:
|
average_big_order_money = 0
|
# 如果剩余总卖小于100w直接根据L2买入
|
if left_limit_up_sell_money < 100e4 or no_left_limit_up_sell:
|
return BUY_MODE_BY_L2, f"剩余总卖小于100w({left_limit_up_sell_money}) 是否还有剩余涨停卖-{no_left_limit_up_sell}"
|
|
return BUY_MODE_NONE, f"均大单-{average_big_order_money}({big_order_money}/{big_order_count}),剩余涨停卖:{left_limit_up_sell_money}"
|
# #总卖 = 涨停主动买成交的累计金额 + 处于委托状态的涨停卖金额
|
# total_sell = __deal_active_buy_total_money[code] + left_limit_up_sell_money
|
# if total_sell == 0:
|
# total_sell = 1
|
# rate = round(__deal_active_buy_total_money[code] / total_sell, 2)
|
# # 获取当前的成交量比
|
# limit_up_price = gpcode_manager.get_limit_up_price_as_num(code)
|
# volume_rate = code_volumn_manager.CodeVolumeManager().get_volume_rate_refer_in_5days(code,
|
# total_sell_volume=int(
|
# total_sell / limit_up_price))
|
# if volume_rate is None:
|
# volume_rate = 0.5
|
#
|
# THRESHOLD_RATE = radical_buy_data_manager.get_volume_rate_threshold(code, volume_rate)
|
# if rate >= THRESHOLD_RATE:
|
# # 根据大单判断是否可以扫
|
# big_order_deal_result = radical_buy_data_manager.is_big_order_deal_enough(code, volume_rate,
|
# refer_sell_money, for_buy=True)
|
# if big_order_deal_result[0]:
|
# return BUY_MODE_DIRECT, f"剩余涨停总卖额-{selling_num * price},原涨停总卖-{total_sell},已成交额-{__deal_active_buy_total_money[code]},成交比例-{rate}/{THRESHOLD_RATE}, 大单信息-{big_order_deal_result}"
|
# else:
|
# # 无大单成交就只能通过L2下单
|
# return BUY_MODE_BY_L2, f"无大单成交-{big_order_deal_result},原涨停总卖-{total_sell},已成交额-{__deal_active_buy_total_money[code]},成交比例-{rate}/{THRESHOLD_RATE} "
|
# else:
|
# return BUY_MODE_NONE, f"被动卖成交比例未达到:剩余涨停总卖额-{selling_num * price},原涨停总卖-{total_sell},已成交额-{__deal_active_buy_total_money[code]},成交比例-{rate}/{THRESHOLD_RATE}"
|
|
|
def is_can_buy_with_open_price(code, open_price):
|
"""
|
根据开盘价判断是否可买
|
@param code:
|
@param open_price: 开盘价没获取到就不判断
|
@return:
|
"""
|
if tool.get_now_time_as_int() < int("093500") and open_price:
|
async_log_util.info(logger_l2_radical_buy, f"开盘价:{code}-{open_price}")
|
pre_price = gpcode_manager.CodePrePriceManager.get_price_pre_cache(code)
|
if pre_price:
|
rate = round((open_price - pre_price) / pre_price, 4)
|
async_log_util.info(logger_l2_radical_buy, f"开盘价涨幅:{code}-{rate}")
|
if tool.get_limit_up_rate(code) > 1.1:
|
return rate < 0.149
|
else:
|
return rate < 0.049
|
return True
|
|
|
# 板块缓存
|
__radical_buy_by_blocks_result_cache = {}
|
|
|
def compute_can_radical_buy_blocks(code, deal_codes):
|
"""
|
计算可以扫入的板块
|
@param code:
|
@return: 可买板块集合, 过滤后的集合
|
"""
|
result_cache = __radical_buy_by_blocks_result_cache.get(code)
|
if not result_cache or result_cache[0] < time.time():
|
# 不存在/过期
|
yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes()
|
if yesterday_codes is None:
|
yesterday_codes = set()
|
# 计算是否可以扫入
|
radical_result = RadicalBuyBlockManager.is_radical_buy(code, yesterday_codes)
|
async_log_util.info(logger_l2_radical_buy, f"计算板块结果:{code}-{radical_result}")
|
result_cache = (time.time() + 3, radical_result)
|
__radical_buy_by_blocks_result_cache[code] = result_cache
|
RadicalBuyDealCodesManager().set_code_blocks(code, radical_result[0])
|
if not radical_result[0]:
|
async_log_util.info(logger_l2_not_buy_reasons, f"{code}#{radical_result[1]}")
|
# 取缓存
|
result = result_cache[1]
|
if result[0]:
|
# 买入的板块
|
buy_blocks = result[0]
|
# 如果关键词包含已成交的原因就不再下单
|
# 获取已经成交代码的板块
|
# ---------------判断板块是否还可以买入----------------
|
f_buy_blocks = radical_buy_data_manager.is_block_can_radical_buy(code, buy_blocks, deal_codes)
|
return f_buy_blocks, result[0]
|
return set(), result[0]
|