| | |
| | | |
| | | # l2交易因子 |
| | | |
| | | import big_money_num_manager |
| | | import global_data_loader |
| | | import global_util |
| | | import limit_up_time_manager |
| | | from code_attribute import big_money_num_manager, limit_up_time_manager, global_data_loader, gpcode_manager |
| | | import constant |
| | | from trade import trade_manager, deal_big_money_manager, trade_constant |
| | | from utils import global_util, tool |
| | | |
| | | |
| | | # 下单参数 |
| | | |
| | | |
| | | class L2PlaceOrderParamsManager: |
| | | |
| | | # 获取买入等级描述 |
| | | def get_buy_rank_desc(self): |
| | | continue_count = self.get_begin_continue_buy_count() |
| | | time_range = self.get_time_range() |
| | | m = self.get_m_val()[0] |
| | | m = m // 10000 |
| | | |
| | | desc = "" |
| | | if self.buy_rank == 0: |
| | | desc = f"买入信号({continue_count})" |
| | | elif self.buy_rank == 1: |
| | | desc = f"买入信号({continue_count})+M值≥{m}万" |
| | | elif self.buy_rank == 2: |
| | | desc = f"买入信号({continue_count})+M值≥{m}万+至少含1笔大单" |
| | | elif self.buy_rank == 3: |
| | | desc = f"买入信号({continue_count})+M值≥{m}万+至少含2笔大单" |
| | | else: |
| | | desc = "常规买入" |
| | | desc += f"+囊括时间{time_range}s" |
| | | return desc |
| | | |
| | | # 获取买入等级 |
| | | # 0:买入信号 |
| | | # 1:买入信号+M1000万 |
| | | # 2:买入信号+M1000万+1笔大单 |
| | | # 3:买入信号+M1000+2笔大单 |
| | | # 100:执行之前固有方案 |
| | | def get_buy_rank(self): |
| | | if self.score_index == 0: |
| | | return 0 |
| | | elif self.score_index == 1: |
| | | return 1 |
| | | elif self.score_index == 2: |
| | | return 2 |
| | | else: |
| | | return 100 |
| | | # 暂时不需要次此中策略 |
| | | # # 判断有没有炸开 |
| | | # if code_price_manager.Buy1PriceManager().is_can_buy(self.code): |
| | | # # 回封 |
| | | # if self.score_index == 0: |
| | | # return 0 |
| | | # elif self.score_index == 1: |
| | | # return 1 |
| | | # elif self.score_index == 2: |
| | | # return 2 |
| | | # else: |
| | | # return 100 |
| | | # else: |
| | | # # 首封 |
| | | # if tool.trade_time_sub(self.now_time, "10:30:00") < 0 or tool.trade_time_sub(self.now_time, "14:00:00") > 0: |
| | | # if self.score_index == 0: |
| | | # return 1 |
| | | # elif self.score_index == 1: |
| | | # return 2 |
| | | # elif self.score_index == 2: |
| | | # return 3 |
| | | # else: |
| | | # return 100 |
| | | # else: |
| | | # if self.score_index == 0: |
| | | # return 2 |
| | | # elif self.score_index == 1: |
| | | # return 3 |
| | | # elif self.score_index == 2: |
| | | # return 100 |
| | | # else: |
| | | # return 100 |
| | | |
| | | # 得分 |
| | | def __init__(self, code, is_first_code, volume_rate, volume_rate_index, score, now_time=tool.get_now_time_str()): |
| | | self.code = code |
| | | self.is_first_code = is_first_code |
| | | score_ranks = [constant.BUY_SCORE_RANK_3, constant.BUY_SCORE_RANK_2, constant.BUY_SCORE_RANK_1, |
| | | constant.BUY_SCORE_RANK_0] |
| | | # self.score = score[0][0] |
| | | # self.score_info = score |
| | | # 为分数设置等级 |
| | | # score_index = -1 |
| | | # for i in range(0, len(score_ranks)): |
| | | # if self.score >= score_ranks[i]: |
| | | # score_index = i |
| | | # break |
| | | # 固定设置为2 |
| | | self.score_index = 2 |
| | | # 只要加入想买单的,全部执行主动买入二星方案 |
| | | if gpcode_manager.WantBuyCodesManager().is_in_cache(code): |
| | | self.score_index = 1 |
| | | self.is_want_buy = True |
| | | else: |
| | | self.is_want_buy = False |
| | | # 没有加入想买单的,2星/3星将为1星 |
| | | if self.score_index == 0 or self.score_index == 1: |
| | | self.score_index = 2 |
| | | |
| | | self.volume_rate = volume_rate |
| | | self.volume_rate_index = volume_rate_index |
| | | self.now_time = now_time |
| | | self.buy_rank = self.get_buy_rank() |
| | | |
| | | # 是否是初次下单 |
| | | @classmethod |
| | | def is_first_place_order(cls, code): |
| | | return trade_manager.CodesTradeStateManager().get_trade_state_cache(code) == trade_constant.TRADE_STATE_NOT_TRADE |
| | | |
| | | # 设置分数 |
| | | def set_score(self, score): |
| | | score_ranks = [constant.BUY_SCORE_RANK_3, constant.BUY_SCORE_RANK_2, constant.BUY_SCORE_RANK_1, |
| | | constant.BUY_SCORE_RANK_0] |
| | | self.score = score[0][0] |
| | | self.score_info = score |
| | | # 为分数设置等级 |
| | | score_index = -1 |
| | | for i in range(0, len(score_ranks)): |
| | | if self.score >= score_ranks[i]: |
| | | score_index = i |
| | | break |
| | | self.score_index = score_index |
| | | |
| | | # 获取信号连续买笔数 |
| | | def get_begin_continue_buy_count(self): |
| | | counts = [3, 3, 3, 2, 2, 2, 2] |
| | | volume_rate_index = self.volume_rate_index |
| | | if self.volume_rate_index >= len(counts): |
| | | volume_rate_index = -1 |
| | | return counts[volume_rate_index] |
| | | |
| | | # 获取时间计算范围,返回s |
| | | def get_time_range(self): |
| | | # ts = [pow(3, 1), pow(3, 1), pow(3, 1), pow(3, 2), pow(3, 2), pow(3, 3), pow(3, 3), pow(3, 3)] |
| | | ts = [pow(2, 1), pow(2, 1), pow(2, 1), pow(2, 1), pow(2, 1), pow(2, 1), pow(2, 1), pow(2, 1)] |
| | | # 暂时去除分的影响 |
| | | # if -1 < self.score_index < 3: |
| | | # return ts[0] |
| | | volume_rate_index = self.volume_rate_index |
| | | if self.volume_rate_index >= len(ts): |
| | | volume_rate_index = -1 |
| | | # 首次下单必须同1s |
| | | if self.is_first_place_order(self.code): |
| | | return 1 |
| | | return ts[volume_rate_index] |
| | | |
| | | # 获取需要的大单个数 |
| | | def get_big_num_count(self): |
| | | # counts = [1, 1, 1, 1, 0, 0, 0, 0] |
| | | # volume_rate_index = self.volume_rate_index |
| | | # if self.volume_rate_index >= len(counts): |
| | | # volume_rate_index = -1 |
| | | # return counts[volume_rate_index] |
| | | # 有大单成交就不需要大单了,没有大单成交就需要大单 |
| | | deal_big_money_count = deal_big_money_manager.get_deal_big_money_count(self.code) |
| | | if deal_big_money_count > 0: |
| | | return 0 |
| | | else: |
| | | return 1 |
| | | |
| | | # 获取安全笔数影响比例 |
| | | def get_safe_count_rate(self): |
| | | rates = [0, -0.1, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7] |
| | | volume_rate_index = self.volume_rate_index |
| | | if self.volume_rate_index >= len(rates): |
| | | volume_rate_index = -1 |
| | | return rates[volume_rate_index] |
| | | |
| | | def get_safe_count(self): |
| | | # if self.is_first_code: |
| | | # if self.buy_rank < 4: |
| | | # return 2 |
| | | base_count, min_count, max_count = L2TradeFactorUtil.get_safe_buy_count(self.code, True) |
| | | rate = self.get_safe_count_rate() |
| | | count = int(round(base_count * (1 + rate))) |
| | | # 最少8笔 |
| | | return max(count, 8) |
| | | |
| | | # 获取m值影响比例 |
| | | @classmethod |
| | | def get_m_val_rate(cls, volume_rate_index): |
| | | rates = [0.0, -0.1, -0.15, -0.2, -0.25, -0.3, -0.35, -0.4] |
| | | if volume_rate_index >= len(rates): |
| | | volume_rate_index = -1 |
| | | return rates[volume_rate_index] |
| | | |
| | | @classmethod |
| | | def get_base_m_val(cls, code): |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb is None: |
| | | global_data_loader.load_zyltgb() |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | base_m = L2TradeFactorUtil.get_base_safe_val(zyltgb) |
| | | return base_m |
| | | |
| | | # 获取m值 |
| | | def get_m_val(self): |
| | | base_m = self.get_base_m_val(self.code) |
| | | if self.is_first_place_order(self.code) and tool.is_sz_code(self.code): |
| | | base_m = int(base_m * 2) |
| | | rate = self.get_m_val_rate(self.volume_rate_index) |
| | | m = round(base_m * (1 + rate)) |
| | | return m, "" |
| | | |
| | | |
| | | # S撤参数 |
| | | class SCancelParamsManager: |
| | | # 剔除前几的点火大单 |
| | | @staticmethod |
| | | def get_max_exclude_count(volume_rate_index): |
| | | counts = [5, 4, 3, 2, 1, 1, 1, 1] |
| | | if volume_rate_index >= len(counts): |
| | | volume_rate_index = -1 |
| | | return counts[volume_rate_index] |
| | | |
| | | # 获取买时间范围(距离执行位),返回s |
| | | @staticmethod |
| | | def get_buy_time_range(volume_rate_index): |
| | | # rates = [0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.6] |
| | | seconds = [pow(2, 1), pow(2, 2), pow(2, 3), pow(2, 4), pow(2, 5), pow(2, 5), pow(2, 4), pow(2, 4)] |
| | | if volume_rate_index >= len(seconds): |
| | | volume_rate_index = -1 |
| | | return seconds[volume_rate_index] |
| | | |
| | | # 获取撤销比例 |
| | | @staticmethod |
| | | def get_cancel_rate(volume_rate_index): |
| | | rates = [0.34, 0.44, 0.54, 0.64, 0.74, 0.84, 0.94, 1.04] |
| | | if volume_rate_index >= len(rates): |
| | | volume_rate_index = -1 |
| | | return 0.79 # rates[volume_rate_index] |
| | | |
| | | |
| | | # H撤参数 |
| | | class HCancelParamsManager: |
| | | |
| | | # 获取最大的观察笔数 |
| | | @staticmethod |
| | | def get_max_watch_count(volume_rate_index): |
| | | counts = [40, 36, 32, 28, 24, 20, 16, 12] |
| | | if volume_rate_index >= len(counts): |
| | | volume_rate_index = -1 |
| | | return counts[volume_rate_index] |
| | | |
| | | # 获取撤销比例 |
| | | @staticmethod |
| | | def get_cancel_rate(volume_rate_index): |
| | | # 暂时固定死 |
| | | # rates = [0.35, 0.45, 0.55, 0.65, 0.65, 0.75, 0.75, 0.75] |
| | | # if volume_rate_index >= len(rates): |
| | | # volume_rate_index = -1 |
| | | # return rates[volume_rate_index] |
| | | return 0.89 |
| | | |
| | | |
| | | class L2TradeFactorUtil: |
| | | # 获取基础m值,返回单位为元 |
| | | @classmethod |
| | | def get_base_safe_val(cls, zyltgb): |
| | | if zyltgb is None: |
| | | return 10000000 |
| | | yi = round(zyltgb / 100000000) |
| | | if yi < 1: |
| | | yi = 1 |
| | | m = 5000000 + (yi - 1) * 500000 |
| | | return round(m * 0.7) |
| | | return int(-0.058 * yi * yi + 60.9 * yi) * 10000 |
| | | # m = 5000000 + (yi - 1) * 500000 |
| | | # return round(m * (1 - 0.3)) |
| | | |
| | | # 获取行业影响比例 |
| | | # total_limit_percent为统计的比例之和乘以100 |
| | |
| | | if today is None: |
| | | return 0 |
| | | old_volumn = int(yest) |
| | | if int(day60_max) > int(yest): |
| | | old_volumn = int(day60_max) |
| | | if int(day60_max[0]) > int(yest): |
| | | old_volumn = int(day60_max[0]) |
| | | r = round(int(today) / old_volumn, 2) |
| | | if r < 0.01: |
| | | r = 0.01 |
| | |
| | | # 首次涨停时间 |
| | | limit_up_time = global_util.limit_up_time.get(code) |
| | | if limit_up_time is None: |
| | | limit_up_time = limit_up_time_manager.get_limit_up_time(code) |
| | | limit_up_time = limit_up_time_manager.LimitUpTimeManager().get_limit_up_time_cache(code) |
| | | |
| | | big_money_num = global_util.big_money_num.get(code) |
| | | if big_money_num is None: |
| | | big_money_num = big_money_num_manager.get_num(code) |
| | | big_money_num = big_money_num_manager.get_num_cache(code) |
| | | return ( |
| | | zyltgb, total_industry_limit_percent, volumn_day60_max, volumn_yest, volumn_today, limit_up_time, |
| | | big_money_num) |
| | |
| | | return zyltgb |
| | | |
| | | @classmethod |
| | | def compute_m_value(cls, code): |
| | | def compute_m_value(cls, code, volume_rate): |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb is None: |
| | | global_data_loader.load_zyltgb() |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb is None: |
| | | print("没有获取到自由流通市值") |
| | | return 10000000 |
| | | return 10000000, "" |
| | | zyltgb = cls.get_base_safe_val(zyltgb) |
| | | rate, msg = cls.compute_rate_by_code(code) |
| | | # 暂时注释 |
| | | # rate, msg = cls.compute_rate_by_code(code) |
| | | # print("m值获取:", code, round(zyltgb * rate)) |
| | | return round(zyltgb * rate), msg |
| | | rate = L2PlaceOrderParamsManager.get_m_val_rate(volume_rate) |
| | | |
| | | return round(zyltgb * (1 + rate)), "" |
| | | |
| | | # 获取安全笔数 |
| | | @classmethod |
| | | def get_safe_buy_count(cls, code): |
| | | def get_safe_buy_count(cls, code, is_first=False): |
| | | gb = cls.get_zyltgb(code) |
| | | return cls.get_safe_buy_count_by_gp(gb, is_first) |
| | | |
| | | @classmethod |
| | | def get_safe_buy_count_by_gp(cls, gb, is_first=False): |
| | | MIN_VAL = 8 |
| | | MAX_VAL = 16 |
| | | if is_first: |
| | | MIN_VAL = 5 |
| | | MAX_VAL = 13 |
| | | if not gb: |
| | | # 默认8笔 |
| | | return 8 |
| | | return MIN_VAL, MIN_VAL, MAX_VAL |
| | | count = gb // 100000000 |
| | | if count <= 6: |
| | | count = 8 |
| | | elif count < 32: |
| | | count = round(8 + 0.5 * (count - 6)) |
| | | else: |
| | | count = 21 |
| | | |
| | | # volumn_day60_max, volumn_yest, volumn_today = cls.__get_volumns(code) |
| | | # rate = cls.get_volumn_rate(volumn_day60_max, volumn_yest, volumn_today) |
| | | # 取大单影响值与行业影响值的较大值 |
| | | # count = round(count * (1 - rate)) |
| | | if count < 8: |
| | | count = 8 |
| | | elif count > 21: |
| | | count = 21 |
| | | return count |
| | | if True: |
| | | if count < 8: |
| | | count = MIN_VAL |
| | | elif count < 11: |
| | | count = MIN_VAL + 1 |
| | | elif count < 14: |
| | | count = MIN_VAL + 2 |
| | | elif count < 17: |
| | | count = MIN_VAL + 3 |
| | | elif count < 20: |
| | | count = MIN_VAL + 4 |
| | | elif count < 23: |
| | | count = MIN_VAL + 5 |
| | | elif count < 26: |
| | | count = MIN_VAL + 6 |
| | | elif count < 29: |
| | | count = MIN_VAL + 7 |
| | | else: |
| | | count = MAX_VAL |
| | | if count < MIN_VAL: |
| | | count = MIN_VAL |
| | | elif count > MAX_VAL: |
| | | count = MAX_VAL |
| | | return count, MIN_VAL, MAX_VAL |
| | | |
| | | |
| | | # l2因子归因数据 |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | print(L2TradeFactorUtil.get_safe_buy_count("003005")) |
| | | # print(L2TradeFactorUtil.get_safe_buy_count("003005")) |
| | | # print(L2TradeFactorUtil.get_rate_factors("003004")) |
| | | # print(L2TradeFactorUtil.factors_to_string("003004")) |
| | | print(L2TradeFactorUtil.get_safe_buy_count("002864")) |
| | | |
| | | # for i in range(2, 150): |
| | | print(22, L2TradeFactorUtil.get_base_safe_val(100000000 * 22)) |
| | | # print(L2TradeFactorUtil.get_limit_up_time_rate("11:30:00")) |
| | | # print(L2TradeFactorUtil.get_limit_up_time_rate("13:00:00")) |
| | | # print(L2TradeFactorUtil.get_limit_up_time_rate("13:48:00")) |