| | |
| | | |
| | | class BackTest: |
| | | |
| | | def __init__(self, day, script_name="低吸脚本_辨识度_v3.py", settings=StrategyParamsSettingsManager().get_settings()): |
| | | def __init__(self, day, script_name="低吸脚本_辨识度_v3.py", settings=StrategyParamsSettingsManager().get_settings(), |
| | | target_codes=set()): |
| | | self.day = day |
| | | scripts = "" |
| | | with open(script_name, mode='r', encoding='utf-8') as f: |
| | |
| | | self.settings = settings |
| | | self.scripts = scripts |
| | | self.RANGE_TIMES = ("09:25:00", "11:30:00") |
| | | self.current_time = '09:25:00' |
| | | self.current_time = self.RANGE_TIMES[0] |
| | | |
| | | self.stock_variables_dict = {} |
| | | self.data_loader: DataLoader = None |
| | |
| | | self.deal_codes = set() |
| | | # 板块已经成交的代码 |
| | | self.deal_block_codes = {} |
| | | self.target_codes = target_codes |
| | | self.backtest_results = [] |
| | | self.finish = False |
| | | |
| | | def set_script(self, script): |
| | | self.scripts = script |
| | |
| | | exec(self.scripts, global_dict) |
| | | return global_dict["compute_result"] |
| | | |
| | | def __filter_codes(self, current_data, timeline_data): |
| | | code_plates = current_data["code_plates"] |
| | | start_time, end_time = self.RANGE_TIMES[0], self.RANGE_TIMES[1] |
| | | fplates = set() |
| | | for i in range(60 * 60 * 5): |
| | | time_str = tool.trade_time_add_second(start_time, i) |
| | | if time_str > end_time: |
| | | break |
| | | self.current_time = time_str |
| | | # 统计当前涨停数据 |
| | | current_limit_up_list = current_data["limit_up_list"].get(time_str) |
| | | if current_limit_up_list: |
| | | # 统计板块涨停 |
| | | plate_codes_info = {} |
| | | for x in current_limit_up_list: |
| | | plates = code_plates.get(x[0]) |
| | | if plates: |
| | | for p in plates: |
| | | if p not in plate_codes_info: |
| | | plate_codes_info[p] = [] |
| | | plate_codes_info[p].append((x[0], x[2])) |
| | | # print(time_str, "汽车零部件", plate_codes_info.get("汽车零部件")) |
| | | # 有效的板块 |
| | | valid_plates = set([p for p in plate_codes_info if len(plate_codes_info[p]) >= 2]) |
| | | fplates |= valid_plates |
| | | codes = set([code for code in code_plates if code_plates[code] & fplates]) |
| | | fcodes = set() |
| | | for c in codes: |
| | | if c not in timeline_data["kline_data"]: |
| | | continue |
| | | # 自由流通市值30-300亿 |
| | | pre_close = timeline_data["kline_data"].get(c)[0]["close"] |
| | | if 30e8 <= current_data["zylt_volume"].get(c) * pre_close <= 300e8: |
| | | fcodes.add(c) |
| | | |
| | | return fcodes |
| | | |
| | | def __get_target_codes_v4(self): |
| | | valid_codes = self.timeline_data["valid_codes"] |
| | | return set(self.current_data["code_plates_for_buy"].keys()) & valid_codes |
| | |
| | | stock_variables.新代码板块 = timeline_data["code_blocks"].get(code_) |
| | | stock_variables.辨识度代码 = self.fcodes |
| | | stock_variables.领涨板块信息 = self.head_rise_code_blocks.get(code_) |
| | | if code_ in DEBUG_CODES: |
| | | print(code_, stock_variables.领涨板块信息) |
| | | |
| | | for day in [2, 5, 10, 30, 60, 120]: |
| | | days = timeline_data["trade_days"][:day] |
| | |
| | | max_day=days[0])) |
| | | stock_variables.连续老题材 = KPLLimitUpDataAnalyzer.get_continuous_limit_up_reasons( |
| | | timeline_data["limit_up_record_data_list"], self.data_loader.trade_days[:2]) |
| | | |
| | | |
| | | stock_variables.连续老题材.clear() |
| | | self.stock_variables_dict[code_] = stock_variables |
| | | |
| | | def load_data(self): |
| | |
| | | return ";".join([f"{x[0]}==净额:{x[1]},买单:{x[2]},卖单:{x[3]}" for x in infos]) |
| | | |
| | | def run(self): |
| | | try: |
| | | self.load_data() |
| | | # print(self.fcodes) |
| | | limit_up_record_data_dict = {} |
| | |
| | | all_new_plates = set() |
| | | |
| | | for i in range(60 * 60 * 5): |
| | | if self.finish: |
| | | break |
| | | time_str = tool.trade_time_add_second(start_time, i) |
| | | # print(f"[{tool.get_now_time_str()}]", time_str) |
| | | if time_str > end_time: |
| | | break |
| | | self.current_time = time_str |
| | | ticks = self.current_tick_data.get(time_str) if self.current_tick_data else None |
| | | # ===============统计当前涨停数据 |
| | | origin_current_limit_up_list = self.current_data["limit_up_list"].get(time_str, []) |
| | | current_limit_up_list = [x for x in origin_current_limit_up_list if kpl_util.get_high_level_count(x[4]) < 3] |
| | | current_limit_up_list = [x for x in origin_current_limit_up_list if |
| | | kpl_util.get_high_level_count(x[4]) < 3] |
| | | |
| | | if current_limit_up_list: |
| | | latest_current_limit_up_list = current_limit_up_list |
| | |
| | | code = tick["symbol"][-6:] |
| | | if code not in self.fcodes: |
| | | continue |
| | | if DEBUG_CODES and code not in DEBUG_CODES: |
| | | if self.target_codes and code not in self.target_codes: |
| | | continue |
| | | |
| | | if code not in self.stock_variables_dict: |
| | |
| | | if tick["created_at"][-8:] < '09:30:00': |
| | | stock_variables.今日开盘价 = tick["price"] |
| | | # 今日开盘涨幅 |
| | | stock_variables.今日开盘涨幅 = round((tick["price"] - stock_variables.昨日收盘价) / stock_variables.昨日收盘价, |
| | | stock_variables.今日开盘涨幅 = round( |
| | | (tick["price"] - stock_variables.昨日收盘价) / stock_variables.昨日收盘价, |
| | | 4) |
| | | stock_variables.今日成交量 = tick["cum_volume"] |
| | | stock_variables.今日成交额 = tick["cum_amount"] |
| | |
| | | code = big_order[0] |
| | | if code not in self.fcodes: |
| | | continue |
| | | if DEBUG_CODES and code not in DEBUG_CODES: |
| | | if self.target_codes and code not in self.target_codes: |
| | | continue |
| | | self.init_stock_variables(code, self.timeline_data, self.current_data) |
| | | stock_variables: StockVariables = self.stock_variables_dict.get(code) |
| | |
| | | logging.exception(e) |
| | | |
| | | print("可买题材:", all_new_plates) |
| | | finally: |
| | | self.finish = True |
| | | |
| | | def __process_test_result(self, code, stock_variables: StockVariables, next_trade_day, buy_price, time_str, |
| | | compute_result): |
| | | |
| | | # if code == '000628': |
| | | # print(time_str, code, compute_result) |
| | | # (时间,(代码,代码名称), 涨幅 , 买入结果) |
| | | backtest_result = [time_str, (code, gpcode_manager.get_code_name(code)), |
| | | round((buy_price - stock_variables.昨日收盘价) * 100 / stock_variables.昨日收盘价, 2), |
| | | compute_result] |
| | | |
| | | try: |
| | | if not compute_result[0]: |
| | | if code in DEBUG_CODES: |
| | | if code in self.target_codes: |
| | | print(time_str, code, compute_result[1]) |
| | | # if compute_result[1].find("大单") >= 0 or compute_result[1].find("价格超过昨日最低价") >= 0: |
| | | pass |
| | |
| | | c_rate = round((bar[0]["close"] - buy_price) * 100 / bar[0]["pre_close"], 2) |
| | | else: |
| | | c_rate = "未知" |
| | | backtest_result.append(c_rate) |
| | | backtest_result.append(t_rate) |
| | | print(f"{len(self.deal_codes)}==回测结果:", code, gpcode_manager.CodesNameManager().get_code_name(code), |
| | | f"溢价率:{t_rate},当日盈亏:{c_rate},下单时间:{time_str},涨幅:{round((buy_price - stock_variables.昨日收盘价) * 100 / stock_variables.昨日收盘价, 2)}", |
| | | compute_result[1], |
| | |
| | | self.deal_block_codes[b].add(code) |
| | | stock_variables.板块成交代码 = self.deal_block_codes |
| | | |
| | | finally: |
| | | self.backtest_results.append(backtest_result) |
| | | |
| | | |
| | | # 锂电池 ['002882', '002667', '002846', '300530', '002074', '301662', '002580', '300584', '603399', '601515'] |
| | | # 化工 ['600610', '002427', '002165', '002809', '000565', '002365', '603192', '600370', '600800', '603188'] |
| | | DEBUG_CODES = ['605005', '002590', '002813', '000826', '002973', '603686', '001230', '600684', '000981', '002232'] |
| | | # DEBUG_CODES = [] |
| | | |
| | | VOLUME_LOG_ENABLE = False |
| | | # 备用大单 |
| | |
| | | "2025-05-30", "2025-06-03", "2025-06-04", "2025-06-05", "2025-06-06", "2025-06-09", "2025-06-10"] |
| | | days = ["2025-06-03", "2025-06-04", "2025-06-05", "2025-06-06", "2025-06-09", "2025-06-10", |
| | | "2025-06-11", "2025-06-12", "2025-06-13", "2025-06-16", "2025-06-17", "2025-06-18", "2025-06-19", |
| | | "2025-06-20", "2025-06-23", "2025-06-24", "2025-06-25"] |
| | | "2025-06-20", "2025-06-23", "2025-06-24", "2025-06-25", "2025-06-26", "2025-06-27", "2025-06-30"] |
| | | |
| | | # days = ["2025-05-23"] |
| | | # |