"""
|
激进买数据管理
|
"""
|
import json
|
|
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
|
from third_data import kpl_data_manager
|
from trade.buy_money_count_setting import RadicalBuyBlockCodeCountManager
|
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 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:
|
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)
|