| | |
| | | # 是否具有辨识度 |
| | | p9 = is_special(record_datas) |
| | | p10 = is_latest_10d_max_volume_at_latest_2d(record_datas) |
| | | p11 = __is_yesterday_open_limit_up(record_datas) |
| | | # 最近5天是否跌停/炸板 |
| | | p11 = __is_latest_open_limit_up_or_limit_down(record_datas, 5) |
| | | # 30天内是否有涨停 |
| | | p12 = __has_limit_up(record_datas, 30) |
| | | |
| | |
| | | return False, '' |
| | | |
| | | |
| | | # 昨天是否炸板 |
| | | def __is_yesterday_open_limit_up(datas): |
| | | # 最近几天是否有炸板或跌停 |
| | | def __is_latest_open_limit_up_or_limit_down(datas, day_count): |
| | | datas = copy.deepcopy(datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | item = datas[-1] |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_up_price - item["high"]) < 0.001 and abs(limit_up_price - item["close"]) > 0.001: |
| | | # 炸板 |
| | | return True |
| | | items = datas[0-day_count] |
| | | for item in items: |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_up_price - item["high"]) < 0.001 and abs(limit_up_price - item["close"]) > 0.001: |
| | | # 炸板 |
| | | return True |
| | | # 是否有跌停 |
| | | limit_down_price = float(gpcode_manager.get_limit_down_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_down_price - item["close"]) < 0.001: |
| | | # 跌停 |
| | | return True |
| | | return False |
| | | |
| | | |
| | |
| | | def process_first_codes_datas(dataList, request_id=None): |
| | | logger_l2_codes_subscript.info(f"{request_id}加载l2代码相关数据") |
| | | print("首板代码数量:", len(dataList)) |
| | | # 获取最近5天的交易日期,为后面的数据计算做准备 |
| | | HistoryKDatasUtils.get_latest_trading_date_cache(5) |
| | | limit_up_price_dict = {} |
| | | temp_codes = [] |
| | | codes = [] |
| | |
| | | return tool.to_price(decimal.Decimal(str(price)) * decimal.Decimal("1.1")) |
| | | |
| | | |
| | | def get_limit_down_price_by_preprice(price): |
| | | if price is None: |
| | | return None |
| | | return tool.to_price(decimal.Decimal(str(price)) * decimal.Decimal("0.9")) |
| | | |
| | | |
| | | # 获取跌停价 |
| | | def get_limit_down_price(code): |
| | | price = CodePrePriceManager.get_price_pre_cache(code) |
| | |
| | | SecondCancelBigNumComputer().set_real_place_order_index(code, index) |
| | | LCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index=buy_single_index) |
| | | HourCancelBigNumComputer().set_real_place_order_index(code, index, buy_single_index) |
| | | GCancelBigNumComputer().set_real_place_order_index(code, index) |
| | | |
| | | |
| | | class SecondCancelBigNumComputer: |
| | |
| | | code)) |
| | | cancel_num += val['num'] * (data['re'] - left_count) |
| | | rate = round(cancel_num / total_num, 4) |
| | | must_buy_cancel_rate = constant.H_CANCEL_RATE |
| | | must_buy_cancel_rate = constant.H_CANCEL_RATE |
| | | try: |
| | | temp_rate = gpcode_manager.MustBuyCodesManager().get_cancel_rate_cache(code) |
| | | if temp_rate: |
| | |
| | | if must_buy_cancel_rate is not None: |
| | | return must_buy_cancel_rate |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_l_cancel,str(e)) |
| | | async_log_util.error(logger_l2_l_cancel, str(e)) |
| | | |
| | | base_rate = constant.L_CANCEL_RATE |
| | | if is_up: |
| | |
| | | __near_by_trade_progress_index_cache = {} |
| | | |
| | | __SecondCancelBigNumComputer = SecondCancelBigNumComputer() |
| | | |
| | | |
| | | |
| | | __last_l_up_compute_info = {} |
| | | |
| | |
| | | watch_indexes = set([int(i) for i in watch_indexes_info[2]]) |
| | | # 计算监听的总条数 |
| | | total_num = 0 |
| | | max_num = 0 |
| | | for wi in watch_indexes: |
| | | total_num += total_data[wi]["val"]["num"] * total_data[wi]["re"] |
| | | if total_data[wi]["val"]["num"] > max_num: |
| | | max_num = total_data[wi]["val"]["num"] |
| | | # 判断撤单中是否有监听中的索引 |
| | | need_compute = False |
| | | for i in range(start_index, end_index + 1): |
| | |
| | | |
| | | rate = round(canceled_num / total_num, 3) |
| | | thresh_hold_rate = LCancelRateManager.get_cancel_rate(code) |
| | | # 除开最大单的影响权重 |
| | | temp_thresh_hold_rate = round((total_num - max_num)*0.9/total_num, 2) |
| | | thresh_hold_rate = min(thresh_hold_rate, temp_thresh_hold_rate) |
| | | l2_log.l_cancel_debug(code, f"计算范围:{start_index}-{end_index},已撤单比例:{rate}/{thresh_hold_rate}") |
| | | if rate >= thresh_hold_rate: |
| | | canceled_indexes.sort() |
| | |
| | | |
| | | def need_cancel(self, code, buy_exec_index, start_index, end_index, total_data, is_first_code): |
| | | if buy_exec_index is None: |
| | | return False, "尚未找到下单位置", "" |
| | | return False, None, "尚未找到下单位置" |
| | | # 守护S撤以外的数据 |
| | | if int(tool.get_now_time_str().replace(":", "")) > int("145700") and not constant.TEST: |
| | | return False, None, "" |
| | |
| | | |
| | | # ---------------------------------G撤------------------------------- |
| | | class GCancelBigNumComputer: |
| | | __SecondCancelBigNumComputer = SecondCancelBigNumComputer() |
| | | __real_place_order_index_dict = {} |
| | | __instance = None |
| | | |
| | | # 开始撤单 |
| | | def start_cancel(self, code, buy_no, total_datas, m_val_num): |
| | | # TODO 暂时注释掉G撤 |
| | | return False, "暂时不执行G撤" |
| | | thresh_num = int(m_val_num * 1) |
| | | place_order_index = self.__SecondCancelBigNumComputer.get_real_place_order_index_cache(code) |
| | | if place_order_index is None: |
| | | raise Exception("未获取到下单真实位置") |
| | | buy_data = buy_order_no_map.get(buy_no) |
| | | if not buy_data: |
| | | raise Exception(f"尚未获取到撤买单详情数据: order_no:{buy_no} map数量:{len(buy_order_no_map)}") |
| | | # 从成交位置到下单位置计算m值 |
| | | transaction_index = buy_data["index"] |
| | | need_cancel = True |
| | | buy_nums = 0 |
| | | for index in range(transaction_index + 1, place_order_index): |
| | | data = total_datas[index] |
| | | if L2DataUtil.is_limit_up_price_buy(data["val"]): |
| | | # 获取是否在买入执行信号周围2s |
| | | left_count = l2_data_source_util.L2DataSourceUtils.get_limit_up_buy_no_canceled_count_v2(code, index, |
| | | total_datas, |
| | | local_today_canceled_buyno_map.get( |
| | | code)) |
| | | if left_count > 0: |
| | | buy_nums += left_count * data["val"]["num"] |
| | | if buy_nums > thresh_num: |
| | | break |
| | | if buy_nums > thresh_num: |
| | | need_cancel = False |
| | | return need_cancel, f"成交进度位({transaction_index})-真实下单位({place_order_index}) 纯买手数:{buy_nums}/1.8倍m值手数:{thresh_num}" |
| | | def __new__(cls, *args, **kwargs): |
| | | if not cls.__instance: |
| | | cls.__instance = super(GCancelBigNumComputer, cls).__new__(cls, *args, **kwargs) |
| | | return cls.__instance |
| | | |
| | | def set_real_place_order_index(self, code, index): |
| | | self.__real_place_order_index_dict[code] = index |
| | | |
| | | def clear(self, code=None): |
| | | if code: |
| | | if code in self.__real_place_order_index_dict: |
| | | self.__real_place_order_index_dict.pop(code) |
| | | else: |
| | | self.__real_place_order_index_dict.clear() |
| | | |
| | | def need_cancel(self, code, buy_exec_index, start_index, end_index): |
| | | if code not in self.__real_place_order_index_dict: |
| | | return False, None, "没有找到真实下单位" |
| | | real_place_order_index = self.__real_place_order_index_dict.get(code) |
| | | total_datas = local_today_datas.get(code) |
| | | # 30s内有效 |
| | | if tool.trade_time_sub(total_datas[end_index]["val"]["time"], total_datas[buy_exec_index]["val"]["time"]) > 30: |
| | | return False, None, "下单30s内才生效" |
| | | |
| | | for i in range(start_index, end_index + 1): |
| | | data = total_datas[i] |
| | | val = data["val"] |
| | | if not L2DataUtil.is_limit_up_price_buy_cancel(val): |
| | | continue |
| | | if val["num"] * float(val["price"]) < 30000: |
| | | continue |
| | | buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data_v2(data, |
| | | local_today_buyno_map.get( |
| | | code)) |
| | | if buy_index is not None and buy_index < real_place_order_index: |
| | | return True, data, "" |
| | | return False, None, "" |
| | | |
| | | def place_order_success(self, code): |
| | | self.clear(code) |
| | | |
| | | def cancel_success(self, code): |
| | | self.clear(code) |
| | | |
| | | |
| | | # ---------------------------------独苗撤------------------------------- |
| | |
| | | from l2.l2_sell_manager import L2MarketSellManager, L2LimitUpSellManager |
| | | from l2.transaction_progress import TradeBuyQueue |
| | | from log_module import async_log_util, log_export |
| | | from third_data import kpl_data_manager, block_info |
| | | from third_data import kpl_data_manager, block_info, history_k_data_util |
| | | from third_data.history_k_data_util import HistoryKDatasUtils |
| | | from utils import global_util, ths_industry_util, tool |
| | | import l2_data_util |
| | | from db import redis_manager_delegate as redis_manager |
| | |
| | | from l2 import l2_data_manager, l2_log, l2_data_source_util, code_price_manager, \ |
| | | transaction_progress, cancel_buy_strategy, l2_data_log |
| | | from l2.cancel_buy_strategy import SecondCancelBigNumComputer, HourCancelBigNumComputer, DCancelBigNumComputer, \ |
| | | LCancelBigNumComputer, LatestCancelIndexManager, FastCancelBigNumComputer, LCancelRateManager |
| | | LCancelBigNumComputer, LatestCancelIndexManager, FastCancelBigNumComputer, LCancelRateManager, GCancelBigNumComputer |
| | | from l2.l2_data_manager import L2DataException, OrderBeginPosInfo |
| | | from l2.l2_data_util import local_today_datas, L2DataUtil, local_today_num_operate_map, local_today_buyno_map, \ |
| | | local_latest_datas, local_today_canceled_buyno_map |
| | |
| | | __SecondCancelBigNumComputer = SecondCancelBigNumComputer() |
| | | __HourCancelBigNumComputer = HourCancelBigNumComputer() |
| | | __LCancelBigNumComputer = LCancelBigNumComputer() |
| | | __GCancelBigNumComputer = GCancelBigNumComputer() |
| | | __TradeStateManager = trade_manager.TradeStateManager() |
| | | __CodesTradeStateManager = trade_manager.CodesTradeStateManager() |
| | | __PauseBuyCodesManager = gpcode_manager.PauseBuyCodesManager() |
| | |
| | | pass |
| | | return None, "" |
| | | |
| | | # G撤 |
| | | def g_cancel(_buy_single_index, _buy_exec_index): |
| | | try: |
| | | b_need_cancel, b_cancel_data, extra_msg = cls.__GCancelBigNumComputer.need_cancel(code, |
| | | _buy_exec_index, |
| | | start_index, |
| | | end_index) |
| | | if b_need_cancel and b_cancel_data: |
| | | return b_cancel_data, f"G撤({extra_msg})" |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_error, |
| | | f"G撤出错 参数:buy_single_index-{_buy_single_index} buy_exec_index-{_buy_exec_index} 错误原因:{str(e)}") |
| | | # logger_l2_error.exception(e) |
| | | async_log_util.exception(logger_l2_error, e) |
| | | finally: |
| | | # l2_data_log.l2_time(code, round(t.time() * 1000) - _start_time, "已下单-L撤大单计算") |
| | | pass |
| | | return None, "" |
| | | |
| | | if start_index < 0: |
| | | start_index = 0 |
| | | |
| | |
| | | cancel_data, cancel_msg = None, "" |
| | | if order_begin_pos.mode == OrderBeginPosInfo.MODE_FAST: |
| | | cancel_data, cancel_msg = f_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index) |
| | | |
| | | if not cancel_data: |
| | | cancel_data, cancel_msg = g_cancel(order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index) |
| | | |
| | | # 依次处理 |
| | | if not cancel_data: |
| | |
| | | # if cls.__TradeTargetCodeModeManager.get_mode_cache() == TradeTargetCodeModeManager.MODE_ONLY_BUY_WANT_CODES: |
| | | # return False, True, f"只买想买单中的代码" |
| | | |
| | | if HighIncreaseCodeManager().is_in(code): |
| | | return False, True, f"涨幅过高,5天内3次涨停" |
| | | return cls.can_buy_first(code, limit_up_price) |
| | | # else: |
| | | # return True, False, "在想买名单中" |
| | |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.6: |
| | | return False, True, f"股价创新高或者逼近前高且30天内有涨停,当日量比({cls.volume_rate_info[code][0]})小于0.6" |
| | | |
| | | # 前一天炸板之后,今日10:00之前才能下单 |
| | | # 上5个交易日有炸板/跌停之后 |
| | | if k_format and len(k_format) >= 11 and k_format[10]: |
| | | if now_timestamp > int("100000"): |
| | | return False, True, f"上个交易日炸板,当日10点以后不下单" |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.6: |
| | | return False, True, f"上5个交易日炸板/跌停,量未达到60%({cls.volume_rate_info[code][0]})" |
| | | |
| | | # 获取量的参考日期 |
| | | if code in global_util.max60_volumn: |
| | | day = global_util.max60_volumn[code][1] |
| | | if day in HistoryKDatasUtils.get_latest_trading_date_cache(5): |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.6: |
| | | return False, True, f"参考量在最近5天,量未达到60%({cls.volume_rate_info[code][0]})" |
| | | |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb >= 40 * 100000000: |
| | | return False, True, f"40亿以上的都不买({zyltgb})" |
| | | |
| | | if HighIncreaseCodeManager().is_in(code): |
| | | if code in cls.volume_rate_info and cls.volume_rate_info[code][0] < 0.8: |
| | | return False, True, f"5天内3次涨停,量未达到80%({cls.volume_rate_info[code][0]})" |
| | | |
| | | msg_list = [] |
| | | if can_buy_result[3] and now_timestamp <= int("094000"): |
| | | if now_timestamp <= int("094000"): |
| | | msg_list.append("强势10分钟") |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | # 独苗 |
| | | if not can_buy_result[0] and can_buy_result[1]: |
| | | msg_list.append("独苗") |
| | |
| | | return True, False, can_buy_result[2] |
| | | return True, False, can_buy_result[2] |
| | | else: |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | # 非强势10分钟只买主线 |
| | | if not can_buy_result[0] and can_buy_result[1]: |
| | | return False, True, f"非强势10分钟,独苗不下单" |
| | |
| | | day = tool.get_now_date_str() |
| | | data_dict = {} |
| | | for i in range(0, 2): |
| | | day = HistoryKDatasUtils.get_previous_trading_date(day) |
| | | day = HistoryKDatasUtils.get_previous_trading_date_cache(day) |
| | | data_list = list(block_info.KPLLimitUpDataRecordManager.list_all(day)) |
| | | codes_set = set() |
| | | if data_list: |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | code_str = "603178" |
| | | code_str = "002861" |
| | | codes = code_str.split(",") |
| | | for code in codes: |
| | | if not tool.is_shsz_code(code): |
| | | continue |
| | | try: |
| | | datas = init_data_util.get_volumns_by_code(code, 120) |
| | | result = is_too_high(datas) |
| | | if result: |
| | | print(code, result) |
| | | limit_up_price = 16.96 |
| | | volumes_data = init_data_util.get_volumns_by_code(code, 150) |
| | | volumes_data = volumes_data[1:] |
| | | volumes = init_data_util.parse_max_volume(volumes_data[:90], |
| | | code_nature_analyse.is_new_top( |
| | | limit_up_price, |
| | | volumes_data[:90]) or code_nature_analyse.is_near_top( |
| | | limit_up_price, |
| | | volumes_data[:90])) |
| | | print(volumes) |
| | | except: |
| | | print(code, "出错") |
| | |
| | | if now_day in __blocks_dict: |
| | | return __blocks_dict[now_day] |
| | | now_date = datetime.datetime.now() |
| | | end_date = HistoryKDatasUtils.get_previous_trading_date(tool.get_now_date_str()) |
| | | end_date = HistoryKDatasUtils.get_previous_trading_date_cache(tool.get_now_date_str()) |
| | | start_date = now_date - datetime.timedelta(days=(day_count * 2 + 10)) |
| | | start_date = start_date.strftime("%Y-%m-%d") |
| | | days = HistoryKDatasUtils.get_trading_dates(start_date, end_date) |
| | |
| | | from db.redis_manager_delegate import RedisUtils |
| | | from utils import tool, middle_api_protocol |
| | | from db import redis_manager_delegate as redis_manager |
| | | |
| | | |
| | | # import gm.api as gmapi |
| | | |
| | | |
| | |
| | | |
| | | |
| | | class HistoryKDatasUtils(object): |
| | | __previous_trading_date_cache={} |
| | | __previous_trading_date_cache = {} |
| | | __latest_trading_date_cache = {} |
| | | |
| | | @classmethod |
| | | def get_gp_latest_info(cls, codes, fields=None): |
| | |
| | | if fdata: |
| | | cls.__previous_trading_date_cache[date] = fdata |
| | | return fdata |
| | | |
| | | # 获取最近的交易日 |
| | | @classmethod |
| | | def get_latest_trading_date(cls, day_count): |
| | | now_day = tool.get_now_date_str() |
| | | days = [] |
| | | for i in range(day_count): |
| | | pday = cls.get_previous_trading_date_cache(now_day) |
| | | days.append(pday) |
| | | now_day = pday |
| | | return days |
| | | |
| | | @classmethod |
| | | def get_latest_trading_date_cache(cls, day_count): |
| | | key = f"{tool.get_now_date_str()}-{day_count}" |
| | | if key in cls.__latest_trading_date_cache: |
| | | return cls.__latest_trading_date_cache[key] |
| | | days = cls.get_latest_trading_date(day_count) |
| | | cls.__latest_trading_date_cache[key] = days |
| | | return days |
| | | |
| | | # 返回指定日期的下个交易日 |
| | | @classmethod |
| | |
| | | |
| | | if __name__ == "__main__": |
| | | constant.JUEJIN_LOCAL_API = False |
| | | print(HistoryKDatasUtils.get_lowest_price_rate("000725", 30)) |
| | | print(tool.get_now_time_str()) |
| | | print(HistoryKDatasUtils.get_latest_trading_date(5)) |
| | | print(tool.get_now_time_str()) |
| | | print(HistoryKDatasUtils.get_latest_trading_date(5)) |
| | | print(tool.get_now_time_str()) |
| | | print(HistoryKDatasUtils.get_latest_trading_date(5)) |
| | |
| | | if limit_up_price: |
| | | rate = round(total_deal_nums / (thresh_hold_money // (float(limit_up_price) * 100)), 2) |
| | | LCancelRateManager().set_big_num_deal_rate(code, rate) |
| | | try: |
| | | need_cancel, msg = cls.__GCancelBigNumComputer.start_cancel(code, f"{order_no}", |
| | | l2_data_util.local_today_datas.get( |
| | | code), m_val_num) |
| | | if need_cancel: |
| | | # 需要撤单 |
| | | l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, "G撤撤单", "G撤") |
| | | async_log_util.info(logger_l2_g_cancel, f"{code}-需要撤单:{msg}") |
| | | else: |
| | | async_log_util.info(logger_l2_g_cancel, f"{code}-不需要撤单:{msg}") |
| | | except Exception as e: |
| | | async_log_util.error(logger_l2_g_cancel, f"{code}-撤单异常:{str(e)}") |
| | | |
| | | @classmethod |
| | | def test_sell(cls): |
| | |
| | | |
| | | from l2 import l2_data_manager |
| | | from l2.cancel_buy_strategy import HourCancelBigNumComputer, SecondCancelBigNumComputer, \ |
| | | LCancelBigNumComputer, DCancelBigNumComputer, FastCancelBigNumComputer |
| | | LCancelBigNumComputer, DCancelBigNumComputer, FastCancelBigNumComputer, GCancelBigNumComputer |
| | | from l2.l2_data_manager import OrderBeginPosInfo |
| | | from l2.l2_data_util import local_today_datas, local_today_num_operate_map |
| | | from l2.l2_sell_manager import L2MarketSellManager |
| | |
| | | SecondCancelBigNumComputer().cancel_success(code) |
| | | DCancelBigNumComputer().cancel_success(code) |
| | | LCancelBigNumComputer().cancel_success(code) |
| | | GCancelBigNumComputer().cancel_success(code) |
| | | # dask.compute(f1, f2, f5, f6, f7, f8) |
| | | |
| | | |
| | |
| | | logging.exception(e) |
| | | logger_l2_error.exception(e) |
| | | |
| | | def g_cancel(code): |
| | | try: |
| | | GCancelBigNumComputer().place_order_success(code) |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | logger_l2_error.exception(e) |
| | | |
| | | order_begin_pos = tradePointManager.get_buy_compute_start_data_cache( |
| | | code) |
| | | |
| | |
| | | # H撤暂时不生效 |
| | | h_cancel(code, order_begin_pos.buy_single_index, order_begin_pos.buy_exec_index) |
| | | l_cancel(code) |
| | | g_cancel(code) |
| | | if order_begin_pos.mode == OrderBeginPosInfo.MODE_FAST: |
| | | f_cancel(code) |
| | | # 记录卖盘统计时间被用 |
| | |
| | | DCancelBigNumComputer().cancel_success(code) |
| | | LCancelBigNumComputer().cancel_success(code) |
| | | FastCancelBigNumComputer().cancel_success(code) |
| | | GCancelBigNumComputer().cancel_success(code) |
| | | |
| | | |
| | | if __name__ == "__main__": |