From 994079acd0ac30a32e2b0391881890be16b0afc0 Mon Sep 17 00:00:00 2001 From: Administrator <admin@example.com> Date: 星期二, 17 六月 2025 11:01:13 +0800 Subject: [PATCH] ‘功能完善 --- strategy/test.py | 18 + strategy/data_analyzer.py | 29 + strategy/time_series_backtest.py | 25 + third_data/kpl_api.py | 2 strategy/strategy_variable_factory.py | 40 +++ strategy/strategy_script_v7.py | 167 +++++++++++++ strategy/strategy_script_v6.py | 37 +-- api/outside_api_callback.py | 29 ++ third_data/kpl_block_manager.py | 55 ++++ strategy/strategy_manager.py | 14 strategy/low_suction_strategy.py | 29 ++ strategy/back_test.py | 5 main.py | 41 +++ server/local_data_server.py | 167 +++++++++++++ strategy/strategy_params_settings.py | 2 strategy/env_info.py | 11 16 files changed, 616 insertions(+), 55 deletions(-) diff --git a/api/outside_api_callback.py b/api/outside_api_callback.py index 647730f..be5a8fe 100644 --- a/api/outside_api_callback.py +++ b/api/outside_api_callback.py @@ -3,11 +3,13 @@ import threading from api.outside_api_command_manager import ActionCallback +from huaxin_client import l1_subscript_codes_manager from huaxin_client.client_network import SendResponseSkManager from strategy import strategy_params_settings, env_info from strategy.env_info import RealTimeEnvInfo from strategy.strategy_variable_factory import DataLoader from third_data.history_k_data_manager import TradeDateManager +from third_data.kpl_block_manager import KPLCodeJXBlocksManager from utils import socket_util, middle_api_protocol, tool @@ -87,6 +89,11 @@ # 濡傛灉鍦�16:00涔嬪悗閲囩敤涓嬩竴涓氦鏄撴棩 day = tool.get_now_date_str() fdata["history_data"]["k_bars_count"] = env_info.get_history_k_bars(day) + + day = tool.get_now_date_str() + fdata["history_data"]["kpl_code_jx_blocks_count"] = env_info.get_kpl_code_jx_blocks(day) + + return {"code": 0, "data": fdata, "msg": "娴嬭瘯缁撴灉"} def __on_update_leading_limit_up_datas(self): @@ -111,6 +118,23 @@ threading.Thread(target=lambda: update(), daemon=True).start() return {"code": 0} + def __on_update_kpl_code_jx_blocks_datas(self): + """ + 鏇存柊寮�鐩樺暒绮鹃�夋澘鍧楁暟鎹� + @return: + """ + + def update(): + codes = set() + codes_sh, codes_sz = l1_subscript_codes_manager.get_codes() + codes |= set([x.decode() for x in codes_sh]) + codes |= set([x.decode() for x in codes_sz]) + KPLCodeJXBlocksManager(day, codes).start_download_blocks() + # 濡傛灉鍦�16:00涔嬪墠閲囩敤褰撳墠鏃ユ湡 + day = tool.get_now_date_str() + threading.Thread(target=lambda: update(), daemon=True).start() + return {"code": 0} + def OnCommonRequest(self, client_id, request_id, data): ctype = data["ctype"] result_json = {} @@ -120,7 +144,12 @@ del data["ctype"] result_json = self.__on_set_settings(data) elif ctype == 'get_env': + # 鑾峰彇鐜鏁版嵁 result_json = self.__on_get_env(data.get("history")) elif ctype == 'update_leading_limit_up_datas': + # 鏇存柊棰嗘定鏁版嵁 result_json = self.__on_update_leading_limit_up_datas() + elif ctype == 'update_kpl_code_jx_blocks_datas': + # 鏇存柊寮�鐩樺暒绮鹃�夋暟鎹� + result_json = self.__on_update_kpl_code_jx_blocks_datas() self.send_response(result_json, client_id, request_id) diff --git a/main.py b/main.py index 2e20643..c9ad640 100644 --- a/main.py +++ b/main.py @@ -4,17 +4,19 @@ import time import requests +import schedule from api import outside_api_callback from api.outside_api_command_manager import ApiCommandManager from db.redis_manager_delegate import RedisUtils -from huaxin_client import l2_market_client, trade_client +from huaxin_client import l2_market_client, trade_client, l1_subscript_codes_manager from log_module import async_log_util from log_module.log import logger_debug from server import data_server from strategy import strategy_manager from strategy.env_info import RealTimeEnvInfo from third_data import hx_qc_value_util +from third_data.kpl_block_manager import KPLCodeJXBlocksManager from trade.huaxin import huaxin_trade_api from utils import tool, middle_api_protocol @@ -27,7 +29,7 @@ if data.get("type") == 'set_target_codes': # [(浠g爜, 鏃堕棿鎴�, 浠锋牸, 鎬讳氦鏄撻噺, 鎬讳氦鏄撻, 涔�5, 鍗�5)] market_data_list = data["data"]["data"] - if strategy_manager.low_suction_strtegy: + if strategy_manager.low_suction_strtegy: strategy_manager.low_suction_strtegy.add_ticks(market_data_list) RealTimeEnvInfo().ticks = (tool.get_now_time_str(), len(market_data_list)) except Exception as e: @@ -39,6 +41,32 @@ args=(queue_l1_w_strategy_r,)) l2MarketProcess.start() read_results() + + +def __init(): + """ + 鍒濆鍖� + @return: + """ + + # 瀹氭椂鏇存柊浠g爜绮鹃�夋澘鍧� + def run_pending(): + # 鏇存柊浠婃棩浠g爜绮鹃�夋澘鍧� + codes = set() + codes_sh, codes_sz = l1_subscript_codes_manager.get_codes() + codes |= set([x.decode() for x in codes_sh]) + codes |= set([x.decode() for x in codes_sz]) + day = tool.get_now_date_str() + schedule.every().day.at("11:05:00").do(lambda: KPLCodeJXBlocksManager(day, codes).start_download_blocks()) + while True: + try: + schedule.run_pending() + except: + pass + finally: + time.sleep(1) + + threading.Thread(target=run_pending, daemon=True).start() def test(): @@ -66,9 +94,9 @@ threading.Thread(target=lambda: RedisUtils.run_loop(), daemon=True).start() # --------鍚姩鏈湴API鎺ュ彛---------- - manager = ApiCommandManager(middle_api_protocol.SERVER_HOST, middle_api_protocol.SERVER_PORT, outside_api_callback.MyAPICallback()) + manager = ApiCommandManager(middle_api_protocol.SERVER_HOST, middle_api_protocol.SERVER_PORT, + outside_api_callback.MyAPICallback()) manager.run(blocking=False) - # --------鍚姩浜ゆ槗---------- huaxin_trade_api.run() @@ -76,9 +104,14 @@ threading.Thread(target=test, daemon=True).start() # test() + # ----鍒濆鍖�------------ + __init() + # 鍒濆鍖栨暟鎹� strategy_manager.low_suction_strtegy = strategy_manager.LowSuctionStrategy(tool.get_now_date_str()) + + # -------鍚姩L2 market璁㈤槄------ __run_l2_market_subscript() print("鍚姩瀹屾垚") diff --git a/server/local_data_server.py b/server/local_data_server.py new file mode 100644 index 0000000..9e5ebd9 --- /dev/null +++ b/server/local_data_server.py @@ -0,0 +1,167 @@ +""" +鏈湴http鏈嶅姟鍣� +""" +import json +from http.server import SimpleHTTPRequestHandler, HTTPServer +import urllib.parse as urlparse +from urllib.parse import parse_qs + +import constant +from db.mysql_data_delegate import Mysqldb + +from strategy.low_suction_strategy import LowSuctionOriginDataExportManager +from strategy.strategy_variable_factory import DataLoader +from third_data import kpl_util +from utils import tool, output_util, huaxin_util + + +class CORSRequestHandler(SimpleHTTPRequestHandler): + def end_headers(self): + # 娣诲姞 CORS 澶� + self.send_header('Access-Control-Allow-Origin', '*') + self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') + self.send_header('Access-Control-Allow-Headers', 'Content-Type') + super().end_headers() + + # 澶勭悊 OPTIONS 棰勬璇锋眰 + def do_OPTIONS(self): + self.send_response(200) + self.end_headers() + + def do_GET(self) -> None: + path = self.path + url = urlparse.urlparse(path) + ps_dict = dict([(k, v[0]) for k, v in parse_qs(url.query).items()]) + response_data = "" + if url.path == "/get_limit_up_plate_list": + date = ps_dict.get("date") + time_str = ps_dict.get("time") + __LowSuctionOriginDataExportManager = LowSuctionOriginDataExportManager(date) + # [(浠g爜, 浠g爜鍚嶇О, 娑ㄥ仠鍘熷洜, 娑ㄥ仠鏃堕棿, 楂樺害淇℃伅, 鑷敱娴侀�氬競鍊硷紝鏄惁鐐告澘)] + results = __LowSuctionOriginDataExportManager.export_current_limit_up_records() + results = [x for x in results if tool.to_time_str(int(x[3])) <= time_str] + code_plates = __LowSuctionOriginDataExportManager.export_code_plates() + # 鏈�缁堟定鍋滅殑浠g爜 + limit_up_codes = [x[0] for x in results if not x[6]] + if date == tool.get_now_date_str(): + limit_up_list = __LowSuctionOriginDataExportManager.export_limit_up_list() + if limit_up_list: + limit_up_list = [x for x in limit_up_list if x[0][:8] <= time_str] + limit_up_list = limit_up_list[-1][1] + limit_up_codes = [x[0] for x in limit_up_list] + + code_infos = {x[0]: x for x in results} + plate_codes = {} + for code in code_infos.keys(): + plates = code_plates.get(code) + if not plates: + plates = {kpl_util.filter_block(code_infos[code][2])} + plates -= constant.KPL_INVALID_BLOCKS + for p in plates: + if p not in plate_codes: + plate_codes[p] = set() + plate_codes[p].add(code) + # (鏉垮潡鍚嶇О, 娑ㄥ仠鏁帮紝鐐告澘鏁�) + data = [(p, len(plate_codes[p]), len([code for code in plate_codes[p] if code not in limit_up_codes])) for p + in + plate_codes] + data.sort(key=lambda x: x[1] - x[2], reverse=True) + response_data = json.dumps({"code": 0, "data": data}) + + elif url.path == "/get_plate_codes": + date = ps_dict.get("date") + plate = ps_dict.get("plate") + time_str = ps_dict.get("time") + __LowSuctionOriginDataExportManager = LowSuctionOriginDataExportManager(date) + results = __LowSuctionOriginDataExportManager.export_current_limit_up_records() + for r in results: + r[3] = tool.to_time_str(int(r[3])) + r[5] = output_util.money_desc(r[5]) + results = [x for x in results if x[3] <= time_str] + # 鏈�缁堟定鍋滅殑浠g爜 + limit_up_codes = [x[0] for x in results if not x[6]] + if date == tool.get_now_date_str(): + limit_up_list = __LowSuctionOriginDataExportManager.export_limit_up_list() + if limit_up_list: + limit_up_list = [x for x in limit_up_list if x[0][:8] <= time_str] + limit_up_list = limit_up_list[-1][1] + limit_up_codes = [x[0] for x in limit_up_list] + for x in results: + x[6] = x[0] not in limit_up_codes + + # [(浠g爜, 浠g爜鍚嶇О, 娑ㄥ仠鍘熷洜, 娑ㄥ仠鏃堕棿, 楂樺害淇℃伅, 鑷敱娴侀�氬競鍊硷紝鏄惁鐐告澘)] + code_plates = __LowSuctionOriginDataExportManager.export_code_plates() + code_infos = {x[0]: x for x in results} + plate_codes = {} + for code in code_infos.keys(): + plates = code_plates.get(code) + if not plates: + plates = {kpl_util.filter_block(code_infos[code][2])} + plates -= constant.KPL_INVALID_BLOCKS + for p in plates: + if p not in plate_codes: + plate_codes[p] = set() + plate_codes[p].add(code) + codes = plate_codes.get(plate) + datas = [code_infos[code] for code in codes] + datas.sort(key=lambda x: x[3]) + response_data = json.dumps({"code": 0, "data": datas}) + elif url.path == "/get_big_order_list": + date = ps_dict.get("date") + code = ps_dict.get("code") + __LowSuctionOriginDataExportManager = LowSuctionOriginDataExportManager(date) + big_orders_dict = __LowSuctionOriginDataExportManager.export_all_big_order_deal(200e4) + datas = big_orders_dict.get(code, []) + for x in datas: + x[2][3] = huaxin_util.convert_time(x[2][3], with_ms=False) + if len(x[2]) > 5: + x[2][5] = huaxin_util.convert_time(x[2][5], with_ms=False) + order_ids = set() + datas.reverse() + fdatas = [] + for d in datas: + if d[2][0] in order_ids: + continue + fdatas.append(d) + order_ids.add(d[2][0]) + + response_data = json.dumps({"code": 0, "data": fdatas}) + elif url.path == "/get_block_in_datas": + date = ps_dict.get("date") + time_str = ps_dict.get("time") + __LowSuctionOriginDataExportManager = LowSuctionOriginDataExportManager(date) + block_in_datas = __LowSuctionOriginDataExportManager.export_block_in_datas() + fdatas = [] + for d in reversed(block_in_datas): + if d[0] <= time_str: + fdatas = d[1] + break + fdatas = [(x[0], output_util.money_desc(x[1])) for x in fdatas] + response_data = json.dumps({"code": 0, "data": fdatas}) + + elif url.path == "/get_codes_by_jx_plates": + # 鏍规嵁绮鹃�夋澘鍧楄幏鍙栦唬鐮� + plates = ps_dict.get("plates") + plates = set(json.loads(plates)) + sql = " select code, jx_blocks from kpl_code_blocks where " + " and ".join( + [f"jx_blocks like '%{p}%'" for p in plates]) + datas = Mysqldb().select_all(sql) + fdatas = [(x[0], "銆�".join([ f"<red>{dd}</red>" if dd in plates else dd for dd in json.loads(x[1])])) for x in datas if len(set(json.loads(x[1])) & plates) == len(plates)] + response_data = json.dumps({"code": 0, "data": fdatas}) + + print("GET璇锋眰") + self.send_response(200) + # 鍙戠粰璇锋眰瀹㈡埛绔殑鍝嶅簲鏁版嵁 + self.send_header('Content-type', 'application/json') + self.end_headers() + self.wfile.write(response_data.encode()) + + def do_POST(self) -> None: + print("POST璇锋眰") + + +if __name__ == '__main__': + server_address = ('', 8000) + httpd = HTTPServer(server_address, CORSRequestHandler) + print("Server running on http://localhost:8000") + httpd.serve_forever() diff --git a/strategy/back_test.py b/strategy/back_test.py index ee571d3..4b81a36 100644 --- a/strategy/back_test.py +++ b/strategy/back_test.py @@ -9,6 +9,7 @@ from code_attribute import global_data_loader from log_module.log import logger_debug +from strategy.data_analyzer import KTickLineAnalyzer from strategy.data_downloader import DataDownloader from strategy.low_suction_strategy import LowSuctionOriginDataExportManager from strategy.strategy_variable_factory import DataLoader, StrategyVariableFactory @@ -368,4 +369,6 @@ if __name__ == "__main__": - __back_test2() + data_loader = DataLoader("2025-06-10") + kline_1d_dict = data_loader.load_kline_data() + KTickLineAnalyzer.get_third_limit_up_days(kline_1d_dict.get("002907"), 10) diff --git a/strategy/data_analyzer.py b/strategy/data_analyzer.py index 5b7acde..882999f 100644 --- a/strategy/data_analyzer.py +++ b/strategy/data_analyzer.py @@ -272,6 +272,18 @@ return count @classmethod + def __is_limit_up(cls, code, close, pre_close): + """ + 鏄惁娑ㄥ仠 + @param code: + @param close: + @param pre_close: + @return: + """ + return abs(close - cls.calculate_upper_limit_price(code, + pre_close)) < 0.01 + + @classmethod def get_third_limit_up_days(cls, k_data, days): """ 鑾峰彇杩戝嚑涓氦鏄撴棩鐨勪笁鏉垮ぉ鏁� @@ -280,18 +292,17 @@ @return: 涓夋澘澶╂暟 """ count = 0 + k_data = k_data[:days] + k_data = k_data[::-1] for i in range(days): if i + 3 >= len(k_data): continue # 鍒ゆ柇杩炵画涓夋棩娑ㄥ仠涓旂鍥涙棩闈炴定鍋� - if (k_data[i]['close'] >= cls.calculate_upper_limit_price(k_data[i]["sec_id"], k_data[i]["pre_close"])) and \ - (k_data[i + 1]['close'] >= cls.calculate_upper_limit_price(k_data[i + 1]["sec_id"], - k_data[i + 1]["pre_close"])) and \ - (k_data[i + 2]['close'] >= cls.calculate_upper_limit_price(k_data[i + 2]["sec_id"], - k_data[i + 2]["pre_close"])) and \ - (k_data[i + 3]['close'] < cls.calculate_upper_limit_price(k_data[i + 3]["sec_id"], - k_data[i + 3]["pre_close"])): - count += 1 + if cls.__is_limit_up(k_data[i]["sec_id"], k_data[i]['close'], k_data[i]["pre_close"]): + if cls.__is_limit_up(k_data[i+1]["sec_id"], k_data[i+1]['close'], k_data[i+1]["pre_close"]): + if cls.__is_limit_up(k_data[i+2]["sec_id"], k_data[i+2]['close'], k_data[i+2]["pre_close"]): + if not cls.__is_limit_up(k_data[i+3]["sec_id"], k_data[i+3]['close'], k_data[i+3]["pre_close"]): + count += 1 return count @classmethod @@ -528,5 +539,5 @@ if reason not in block_days: block_days[reason] = set() block_days[reason].add(date) - return set([b for b in block_days if len(block_days[b])==len(days_list)]) + return set([b for b in block_days if len(block_days[b]) == len(days_list)]) return set() diff --git a/strategy/env_info.py b/strategy/env_info.py index b4129bd..439a7ea 100644 --- a/strategy/env_info.py +++ b/strategy/env_info.py @@ -5,6 +5,7 @@ from strategy.strategy_variable_factory import DataLoader from third_data.history_k_data_manager import HistoryKDataManager +from third_data.kpl_block_manager import KPLCodeJXBlocksManager from utils import tool @@ -58,5 +59,15 @@ return count +def get_kpl_code_jx_blocks(day): + """ + 鑾峰彇寮�鐩樺暒浠g爜绮鹃�夋澘鍧楁暟閲� + @param day: + @return: + """ + count = KPLCodeJXBlocksManager(day, set()).get_all_code_blocks_count() + return count + + if __name__ == "__main__": print(get_history_k_bars("2025-06-04")) diff --git a/strategy/low_suction_strategy.py b/strategy/low_suction_strategy.py index c6cd149..7ae9c54 100644 --- a/strategy/low_suction_strategy.py +++ b/strategy/low_suction_strategy.py @@ -5,6 +5,7 @@ import os import constant +from db.mysql_data_delegate import Mysqldb from strategy import strategy_variable @@ -191,6 +192,25 @@ fdatas[data[0]].append(data[2]) return fdatas + def export_all_big_order_deal(self, min_money=299e4): + """ + 鎵�鏈夊ぇ鍗曟垚浜わ紝鍖呭惈涔帮紝鍗� + @return: {"浠g爜":[浠g爜,鍗�/涔�, (涔板崟鍙�, 閲�, 閲戦, 鏃堕棿, 鏈�缁堟垚浜や环)]} + """ + + fdatas = {} + lines = self.__export_logs(f"logs/huaxin_local/l2/transaction_accurate_big_order.{self.day}.log") + if lines: + for line in lines: + line = line[line.find(" - ") + 3:].strip() + data = eval(line) + if data[2][2] < min_money: + continue + if data[0] not in fdatas: + fdatas[data[0]] = [] + fdatas[data[0]].append(data) + return fdatas + def export_big_sell_order_deal(self, min_money=299e4): """ 澶у崟鎴愪氦 @@ -267,6 +287,15 @@ data = eval(line) return data + def export_current_limit_up_records(self): + """ + 瀵煎嚭褰撴棩鍘嗗彶娑ㄥ仠 + @return: [(浠g爜, 浠g爜鍚嶇О, 娑ㄥ仠鍘熷洜, 娑ㄥ仠鏃堕棿, 楂樺害淇℃伅, 鑷敱娴侀�氬競鍊硷紝鏄惁鐐告澘)] + """ + results = Mysqldb().select_all( + f"select r.`_code`, r.`_code_name`, r.`_hot_block_name`, r.`_limit_up_time`, r.`_limit_up_high_info`, r.`_zylt_val`, r.`_open` from kpl_limit_up_record r where r._day = '{self.day}'") + return results + class LowSuctionDataManager: """ diff --git a/strategy/strategy_manager.py b/strategy/strategy_manager.py index c2c8ca5..5aed98f 100644 --- a/strategy/strategy_manager.py +++ b/strategy/strategy_manager.py @@ -7,6 +7,8 @@ from db import redis_manager_delegate as redis_manager from db.mysql_data_delegate import Mysqldb from db.redis_manager_delegate import RedisUtils +from log_module import async_log_util +from log_module.log import logger_trade from strategy.data_analyzer import KPLLimitUpDataAnalyzer from strategy.low_suction_strategy import LowSuctionOriginDataExportManager from strategy.strategy_params_settings import StrategyParamsSettingsManager @@ -101,7 +103,9 @@ """ 浣庡惛绛栫暐 """ - def __init__(self, day, script_name="strategy_script_v6.py", settings=StrategyParamsSettingsManager().get_settings()): + + def __init__(self, day, script_name="strategy_script_v6.py", + settings=StrategyParamsSettingsManager().get_settings()): self.now_day = day # 涔板ぇ鍗曪細{浠g爜:[澶у崟鏁版嵁]} self.big_order_buy = {} @@ -135,7 +139,8 @@ self.current_block_in_datas = [] # 鍔犺浇绛栫暐鑴氭湰鏂囦欢 - with open(script_name if constant.is_windows() else f'{constant.get_path_prefix()}/{script_name}', mode='r', encoding='utf-8') as f: + with open(script_name if constant.is_windows() else f'{constant.get_path_prefix()}/{script_name}', mode='r', + encoding='utf-8') as f: lines = f.readlines() scripts = "\n".join(lines) # 娉ㄩ噴鎺夐噷闈㈢殑import涓庡彉閲� @@ -225,7 +230,6 @@ """ if code_ in self.stock_variables_dict: return - stock_variables = StrategyVariableFactory.create_from_history_data( self.kline_data.get(code_), None, self.limit_up_record_data.get(code_), self.data_loader.trade_days) @@ -382,6 +386,8 @@ # 鍒ゆ柇鏄惁鍙互涔� for b in compute_result[3]: DealCodesManager().place_order(b, code) + async_log_util.info(logger_trade, f"{code}涓嬪崟锛屾澘鍧楋細{compute_result[3]}") + # 褰撳墠鐨勪綆鍚哥瓥鐣ュ璞� -low_suction_strtegy = None \ No newline at end of file +low_suction_strtegy = None diff --git a/strategy/strategy_params_settings.py b/strategy/strategy_params_settings.py index b987e71..a183bcc 100644 --- a/strategy/strategy_params_settings.py +++ b/strategy/strategy_params_settings.py @@ -31,7 +31,7 @@ # 鏄ㄦ棩涓嶈兘璺屽仠 self.cant_yesterday_limit_down = True # 鏄ㄦ棩涓嶈兘鐐告澘 - self.cant_yesterday_open_limit_up = False + self.cant_yesterday_open_limit_up = True # 鏈夋定鍋滅殑浜ゆ槗鏃ユ暟閲� self.has_limit_up_days = 10 # xx涓氦鏄撴棩鍐呬笉鑳芥湁xx娆℃定鍋� diff --git a/strategy/strategy_script_v6.py b/strategy/strategy_script_v6.py index 8f481a6..53cf2d5 100644 --- a/strategy/strategy_script_v6.py +++ b/strategy/strategy_script_v6.py @@ -91,6 +91,9 @@ if sv.鍏釜浜ゆ槗鏃ユ定骞呰繃楂�: return False, f"6涓氦鏄撴棩娑ㄥ箙杩囬珮" + if sv.鏃ヤ笁鏉夸釜鏁癬10 >= 1: + return False, f"10涓氦鏄撴棩鏈�>=3杩炴澘" + # if sv.褰撳墠浠� > sv.鏄ㄦ棩鏈�浣庝环 * 1.1: # return False, f"涔板叆鏃剁殑浠锋牸蹇呴』鈮ゆ槰鏃ユ渶浣庝环*110%" @@ -112,8 +115,8 @@ # 鐩爣绁ㄦ澘鍧楁定鍋滀釜鏁�>=2 # 鏉垮潡鍙兘涔板叆涓�涓唬鐮� - # if sv.鏉垮潡鎴愪氦浠g爜: - # can_buy_plates -= set(sv.鏉垮潡鎴愪氦浠g爜.keys()) + if sv.鏉垮潡鎴愪氦浠g爜: + can_buy_plates -= set(sv.鏉垮潡鎴愪氦浠g爜.keys()) if not can_buy_plates: return False, f"娌℃湁娑ㄥ仠鐨勬澘鍧�: {[(plate, sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(plate)) for plate in sv.浠g爜鏉垮潡 if sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋淽} 杩炵画鑰侀鏉愶細{sv.杩炵画鑰侀鏉恾" @@ -138,7 +141,7 @@ if sv.浠婃棩澶у崟鏁版嵁: # print(sv.浠婃棩澶у崟鏁版嵁[-1][3], format_time(sv.浠婃棩澶у崟鏁版嵁[-1][3])) # filter_orders = [(o[0], o[2]) for o in sv.浠婃棩澶у崟鏁版嵁 if format_time(o[3]) >= sv.浠婃棩閲忓淇℃伅[0]] - filter_orders = [(o[0], o[2]) for o in sv.浠婃棩澶у崟鏁版嵁 if o[2] >= 200e4] + filter_orders = [(o[0], o[2]) for o in sv.浠婃棩澶у崟鏁版嵁] filter_orders.reverse() orderids = set() for o in filter_orders: @@ -146,34 +149,20 @@ continue orderids.add(o[0]) big_order_money += o[1] - big_sell_order_money = 0 - if sv.浠婃棩鍗栧ぇ鍗曟暟鎹�: - filter_orders = [(o[0], o[2]) for o in sv.浠婃棩鍗栧ぇ鍗曟暟鎹� if o[2] >= 200e4] - filter_orders.reverse() - orderids = set() - for o in filter_orders: - if o[0] in orderids: - continue - orderids.add(o[0]) - big_sell_order_money += o[1] - threshold_money = max(sv.鑷敱娴侀�氬競鍊� // 1000, 200e4) limit_up_codes_count = max([(p, len(sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(p, []))) for p in can_buy_plates], key=lambda x: x[1])[1] - # threshold_money *= max(min(10 - limit_up_codes_count + 1, 10), 5) / 10 - threshold_money *= 0.5 + threshold_money *= max(10 - limit_up_codes_count + 3, 5) / 10 + if big_order_money < threshold_money: + return False, f"({big_order_money}/{threshold_money})澶у崟閲戦涓嶈冻" - # print(target_code, sv.鑷敱娴侀�氬競鍊�, threshold_money, limit_up_codes_count) + big_sell_order_money = 0 - # threshold_money = 200e4 # int(sv.鏄ㄦ棩鎴愪氦閲� * 0.2 * sv.浠婃棩娑ㄥ仠浠� * 0.05) + if big_order_money < threshold_money: + return False, f"({round(big_order_money / 1e4, 2)}涓�/{round(threshold_money / 1e4, 2)}涓�)澶у崟閲戦涓嶈冻" - final_big_order_money = big_order_money - big_sell_order_money - - if final_big_order_money < threshold_money: - return False, f"({round(final_big_order_money / 1e4, 2)}涓�/{round(threshold_money / 1e4, 2)}涓�)澶у崟閲戦涓嶈冻" - - return True, f" \n\t澶у崟淇℃伅锛歿round(final_big_order_money / 1e4, 2)}涓囷紙涔帮細{round(big_order_money / 1e4, 2)}涓� 鍗栵細{round(big_sell_order_money / 1e4, 2)}涓囷級/{round(threshold_money / 1e4, 2)}涓� \n\t閲忓淇℃伅锛歿sv.浠婃棩閲忓淇℃伅}\n\t浠婃棩鏈�楂樹环:{sv.浠婃棩鏈�楂樹环淇℃伅} \n\t5鏃ユ渶楂樹环锛歿sv.鏃ユ渶楂樹环_5}", f"\n\t鏉垮潡淇℃伅锛歿[(p, sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(p)) for p in can_buy_plates]}", can_buy_plates + return True, f" \n\t澶у崟淇℃伅锛歿round(big_order_money / 1e4, 2)}涓囷紙涔帮細{round(big_order_money / 1e4, 2)}涓� 鍗栵細{round(big_sell_order_money / 1e4, 2)}涓囷級/{round(threshold_money / 1e4, 2)}涓� \n\t閲忓淇℃伅锛歿sv.浠婃棩閲忓淇℃伅}\n\t浠婃棩鏈�楂樹环:{sv.浠婃棩鏈�楂樹环淇℃伅} \n\t5鏃ユ渶楂樹环锛歿sv.鏃ユ渶楂樹环_5}", f"\n\t鏉垮潡淇℃伅锛歿[(p, sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(p)) for p in can_buy_plates]}", can_buy_plates compute_result = can_buy() diff --git a/strategy/strategy_script_v7.py b/strategy/strategy_script_v7.py new file mode 100644 index 0000000..191dd45 --- /dev/null +++ b/strategy/strategy_script_v7.py @@ -0,0 +1,167 @@ +import logging + +from strategy.strategy_params_settings import StrategyParamsSettings +from strategy.strategy_variable import StockVariables + +sv = StockVariables() +settings = StrategyParamsSettings() +target_code = '' + + +def format_time(huaxin_timestamp): + huaxin_timestamp = str(huaxin_timestamp) + if huaxin_timestamp.find("9") == 0: + return f"0{huaxin_timestamp[0]}:{huaxin_timestamp[1: 3]}:{huaxin_timestamp[3: 5]}" + return f"{huaxin_timestamp[0:2]}:{huaxin_timestamp[2: 4]}:{huaxin_timestamp[4: 6]}" + + +def can_buy(): + """ + @return: 鏄惁鍙拱, 涓嶈兘涔扮殑鍘熷洜/鍙拱鐨勬澘鍧�, 鏄惁閲忓 + """ + # print(f"{target_code}:鎵ц绛栫暐") + if not settings.can_buy_ge_code: + if target_code.find("60") != 0 and target_code.find("00") != 0: + return False, "鍒涗笟鏉�/绉戝垱鏉跨殑绁ㄤ笉涔�" + else: + if target_code.find("60") != 0 and target_code.find("00") != 0 and target_code.find("30") != 0: + return False, "绉戝垱鏉跨殑绁ㄤ笉涔�" + + if sv.鏉垮潡鎴愪氦浠g爜: + deal_codes = set() + for p in sv.鏉垮潡鎴愪氦浠g爜: + deal_codes |= set(sv.鏉垮潡鎴愪氦浠g爜[p]) + if len(deal_codes) >= settings.max_buy_codes_count: + return False, f"涔板叆浠g爜鏁拌秴闄�({len(deal_codes)}/{settings.max_buy_codes_count})" + + # 鐩爣绁ㄦ澘鍧楁定鍋滀釜鏁�>=2 + can_buy_plates = set() + for plate in sv.浠g爜鏉垮潡: + if not sv.璧勯噾娴佸叆鏉垮潡 or plate not in sv.璧勯噾娴佸叆鏉垮潡: + continue + if plate in sv.杩炵画鑰侀鏉�: + continue + if plate in sv.鏃ュ嚭鐜扮殑鏉垮潡_2: + # 鑰侀鏉� + threshold_count = settings.limit_up_count_of_old_plate + else: + # 鏂伴鏉� + threshold_count = settings.limit_up_count_of_new_plate + if len(sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(plate, [])) >= threshold_count: + can_buy_plates.add(plate) + + if not sv.褰撳墠浠�: + return False, "鏃犲綋鍓嶄环" + + # if getattr(sv, f"娑ㄥ仠鏁癬{settings.has_limit_up_days}") < 1 and getattr(sv, f"鐐告澘鏁癬{settings.has_limit_up_days}") < 1: + # return False, f"杩憑settings.has_limit_up_days}涓氦鏄撴棩鏃犳定鍋�/鏃犵偢鏉�" + + if settings.cant_yesterday_limit_down and not sv.鏄ㄦ棩闈炶穼鍋�: + return False, "鏄ㄦ棩璺屽仠" + if settings.cant_yesterday_limit_up and not sv.鏄ㄦ棩闈炴定鍋�: + return False, "鏄ㄦ棩娑ㄥ仠" + if settings.cant_yesterday_open_limit_up and not sv.鏄ㄦ棩闈炵偢鏉�: + return False, "鏄ㄦ棩鐐告澘" + + if sv.浠婃棩娑ㄥ仠浠� > settings.price_range[1] or sv.浠婃棩娑ㄥ仠浠� < settings.price_range[0]: + return False, f"浠婃棩娑ㄥ仠浠烽珮浜巤settings.price_range[1]}/浣庝簬{settings.price_range[0]}" + + if sv.鑷敱娴侀�氬競鍊� > settings.zyltgb_range[1] * 1e8 or sv.鑷敱娴侀�氬競鍊� < settings.zyltgb_range[0] * 1e8: + return False, f"鑷敱甯傚�硷紙{sv.鑷敱娴侀�氬競鍊紏锛変笉婊¤冻瑕佹眰" + + if sv.鍏釜浜ゆ槗鏃ユ定骞呰繃楂�: + return False, f"6涓氦鏄撴棩娑ㄥ箙杩囬珮" + + if sv.鏃ヤ笁鏉夸釜鏁癬10 >= 1: + return False, f"10涓氦鏄撴棩鏈�>=3杩炴澘" + + # if sv.褰撳墠浠� > sv.鏄ㄦ棩鏈�浣庝环 * 1.1: + # return False, f"涔板叆鏃剁殑浠锋牸蹇呴』鈮ゆ槰鏃ユ渶浣庝环*110%" + + if (sv.褰撳墠浠� - sv.浠婃棩鏈�浣庝环) / sv.鏄ㄦ棩鏀剁洏浠� > 0.03: + return False, f"涔板叆鏃剁殑浠锋牸涓嶈兘楂樹簬浠婃棩鏈�浣庝环鐨�3%" + + # if abs((sv.褰撳墠浠� - round(sv.浠婃棩鎴愪氦棰� / sv.浠婃棩鎴愪氦閲�, 2)) / sv.鏄ㄦ棩鏀剁洏浠�) >= settings.max_rate_than_average_price: + # return False, f"涔板叆浠烽珮浜庡潎浠穥settings.max_rate_than_average_price}({abs((sv.褰撳墠浠� - round(sv.浠婃棩鎴愪氦棰� / sv.浠婃棩鎴愪氦閲�, 2)) / sv.鏄ㄦ棩鏀剁洏浠�)})" + # + # if (sv.浠婃棩鏈�楂樹环淇℃伅[0] - sv.褰撳墠浠�) / sv.鏄ㄦ棩鏀剁洏浠� > settings.min_rate_of_highest_and_price: + # return False, f"浣庝簬鍒嗘椂楂樹环{settings.min_rate_of_highest_and_price}" + + if not settings.can_buy_limited_up and abs(sv.浠婃棩鏈�楂樹环淇℃伅[0] - sv.浠婃棩娑ㄥ仠浠�) <= 0.001: + return False, f"浠婃棩鏈夋定鍋�" + + # if sv.娑ㄥ仠鏁癬30 <= 0 and not sv.鏃ユ斁鍊嶉噺鏃ユ湡_15: + # return False, "30涓氦鏄撴棩鏃犳定鍋滀笖15涓氦鏄撴棩鏃犲�嶉噺" + + # 鐩爣绁ㄦ澘鍧楁定鍋滀釜鏁�>=2 + + # 鏉垮潡鍙兘涔板叆涓�涓唬鐮� + # if sv.鏉垮潡鎴愪氦浠g爜: + # can_buy_plates -= set(sv.鏉垮潡鎴愪氦浠g爜.keys()) + + if not can_buy_plates: + return False, f"娌℃湁娑ㄥ仠鐨勬澘鍧�: {[(plate, sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(plate)) for plate in sv.浠g爜鏉垮潡 if sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋淽} 杩炵画鑰侀鏉愶細{sv.杩炵画鑰侀鏉恾" + # new_plates = set(can_buy_plates) - sv.鏃ュ嚭鐜扮殑鏉垮潡_2 + # if new_plates: + # # 鏈夋柊棰樻潗锛屽垽鏂槸鍚﹁繃鏄ㄦ棩鍓嶉珮 + # if sv.浠婃棩鏈�楂樹环淇℃伅[0] - sv.鏄ㄦ棩鏈�楂樹环 < 0.02: + # return False, "浠婃棩鏈�楂樹环闇�澶т簬鏄ㄦ棩鏈�楂樹环" + # else: + # if sv.浠婃棩鏈�楂樹环淇℃伅[0] - sv.鏃ユ渶楂樹环_5 < 0.02: + # return False, "浠婃棩鏈�楂樹环闇�澶т簬5鏃ユ渶楂樹环" + + if settings.trade_days_count_of_limit_up_price_over_high and sv.浠婃棩娑ㄥ仠浠� <= getattr(sv, + f"鏃ユ渶楂樹环_{settings.trade_days_count_of_limit_up_price_over_high}"): + return False, f"浠婃棩娑ㄥ仠浠疯绐佺牬{settings.trade_days_count_of_limit_up_price_over_high}鏃ユ渶楂樹环" + + # if sv.浠婃棩鎴愪氦閲� < sv.鏄ㄦ棩鎴愪氦閲� * 0.8: + # return False, f"瀹炴椂鎴愪氦閲忓繀椤烩墺80%鏄ㄦ棩鎬绘垚浜ら噺" + + # =======鎴愪氦澶у崟===== + big_order_money = 0 + if sv.浠婃棩澶у崟鏁版嵁: + # print(sv.浠婃棩澶у崟鏁版嵁[-1][3], format_time(sv.浠婃棩澶у崟鏁版嵁[-1][3])) + # filter_orders = [(o[0], o[2]) for o in sv.浠婃棩澶у崟鏁版嵁 if format_time(o[3]) >= sv.浠婃棩閲忓淇℃伅[0]] + filter_orders = [(o[0], o[2]) for o in sv.浠婃棩澶у崟鏁版嵁 if o[2] >= 299e4 and o[4] > sv.鏄ㄦ棩鏀剁洏浠穄 + if not filter_orders: + return False, "鏃犳定骞呭ぇ浜�0%鐨勫ぇ鍗�" + filter_orders = [(o[0], o[2]) for o in sv.浠婃棩澶у崟鏁版嵁 if o[2] >= 299e4] + filter_orders.reverse() + orderids = set() + for o in filter_orders: + if o[0] in orderids: + continue + orderids.add(o[0]) + big_order_money += o[1] + big_sell_order_money = 0 + if sv.浠婃棩鍗栧ぇ鍗曟暟鎹�: + filter_orders = [(o[0], o[2]) for o in sv.浠婃棩鍗栧ぇ鍗曟暟鎹� if o[2] >= 100e4] + filter_orders.reverse() + orderids = set() + for o in filter_orders: + if o[0] in orderids: + continue + orderids.add(o[0]) + big_sell_order_money += o[1] + + threshold_money = max(sv.鑷敱娴侀�氬競鍊� // 1000, 200e4) + + limit_up_codes_count = max([(p, len(sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(p, []))) for p in can_buy_plates], key=lambda x: x[1])[1] + + # threshold_money *= max(min(10 - limit_up_codes_count + 1, 10), 5) / 10 + threshold_money *= 0.5 + + # print(target_code, sv.鑷敱娴侀�氬競鍊�, threshold_money, limit_up_codes_count) + + # threshold_money = 200e4 # int(sv.鏄ㄦ棩鎴愪氦閲� * 0.2 * sv.浠婃棩娑ㄥ仠浠� * 0.05) + + final_big_order_money = big_order_money - big_sell_order_money + + if final_big_order_money <= 200e4: + # 澶у崟鍑�棰濊澶т簬200w + return False, f"({round(final_big_order_money / 1e4, 2)}涓�/{round(threshold_money / 1e4, 2)}涓�)澶у崟閲戦涓嶈冻" + + return True, f" \n\t澶у崟淇℃伅锛歿round(final_big_order_money / 1e4, 2)}涓囷紙涔帮細{round(big_order_money / 1e4, 2)}涓� 鍗栵細{round(big_sell_order_money / 1e4, 2)}涓囷級/{round(threshold_money / 1e4, 2)}涓� \n\t閲忓淇℃伅锛歿sv.浠婃棩閲忓淇℃伅}\n\t浠婃棩鏈�楂樹环:{sv.浠婃棩鏈�楂樹环淇℃伅} \n\t5鏃ユ渶楂樹环锛歿sv.鏃ユ渶楂樹环_5}", f"\n\t鏉垮潡淇℃伅锛歿[(p, sv.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(p)) for p in can_buy_plates]}", can_buy_plates + + +compute_result = can_buy() diff --git a/strategy/strategy_variable_factory.py b/strategy/strategy_variable_factory.py index 97b9e28..c79673b 100644 --- a/strategy/strategy_variable_factory.py +++ b/strategy/strategy_variable_factory.py @@ -7,7 +7,7 @@ import re import constant -from code_attribute import global_data_loader +from code_attribute import global_data_loader, gpcode_manager from db import mysql_data_delegate from strategy.data_analyzer import KTickLineAnalyzer, KPLLimitUpDataAnalyzer, K60SLineAnalyzer from strategy.strategy_variable import StockVariables @@ -235,7 +235,7 @@ results = [x for x in results if (tool.is_can_buy_code(x[0]) and x[0] in valid_codes and x[0] not in exclude_codes)] # 鍙栧墠1/3涓旀定鍋滄暟鏄墠10 - max_count = len(results) // 2 if len(results) % 2 == 0 else len(results) // 2 + 1 + max_count = len(results) // 3 if len(results) % 3 == 0 else len(results) // 3 + 1 results = results[:max_count] # 鍙栧墠10 results = results[:10] @@ -636,7 +636,41 @@ print(code, code_blocks[code]) +def __load_target_codes_v1(): + """ + 50浜夸互涓嬬殑 + @return: + """ + + def get_zylt(code): + zylt_volume_map = global_util.zylt_volume_map + last_trade_day = __DataLoader.trade_days[0] + volume = zylt_volume_map.get(code) + # 浠婃棩娑ㄥ仠浠疯绐佺牬鏄ㄦ棩鏈�楂樹环 + k_bars = HistoryKDataManager().get_history_bars(code, last_trade_day) + return k_bars[0]["close"] * volume * tool.get_limit_up_rate(code) + + __DataLoader = DataLoader('2025-06-13') + global_data_loader.load_zyltgb_volume_from_db() + results = __DataLoader.load_target_plate_and_codes() + # for k in results: + # print(k, results[k]) + plates = ["澶╃劧姘�", "鍐涘伐"] + print("==========鏂伴鏉�=======") + for p in plates: + codes = [x for x in results.get(p) ] # if get_zylt(x) < 31e8 + print("======", p) + for code in codes: + print("\t\t", code, gpcode_manager.CodesNameManager().get_code_name(code)) + + + + + if __name__ == "__main__": + + __load_target_codes_v1() + __DataLoader = DataLoader("2025-06-12") # __test_jx_blocks(__DataLoader) @@ -655,7 +689,7 @@ results = __DataLoader.load_target_plate_and_codes() # for k in results: # print(k, results[k]) - plates = ["姹借溅闆堕儴浠�", "绋�鍦熸案纾�", "鍖栧伐", "鍖昏嵂", "鍏変紡"] + plates = ["姹借溅闆堕儴浠�", "鏂囧寲浼犲獟", "璋峰瓙缁忔祹"] print("==========鏂伴鏉�=======") for p in plates: print(p, results.get(p)) diff --git a/strategy/test.py b/strategy/test.py index 2b50ce9..da567f2 100644 --- a/strategy/test.py +++ b/strategy/test.py @@ -1,8 +1,11 @@ +from huaxin_client import l1_subscript_codes_manager from strategy import strategy_manager from strategy.strategy_variable import StockVariables - # 缁熻褰撴棩鐨勫钩鍧囨孩浠风巼 +from third_data.kpl_block_manager import KPLCodeJXBlocksManager + + def statistic_average(path): rate_list = [] with open(path, mode='r', encoding='utf-8') as f: @@ -23,6 +26,13 @@ # statistic_average(r"C:\Users\Administrator\Desktop\3涓エ娑ㄥ仠涔嬪悗涔�.txt") # print("======3涓エ娑ㄥ仠涔嬪悗涔�+涓嶉檺寮�鐩樻定骞�+3涓定鍋滀箣鍚庡ぇ鍗曟墦鎶�") # statistic_average(r"C:\Users\Administrator\Desktop\3涓エ娑ㄥ仠涔嬪悗涔癬涓嶉檺寮�鐩樻定骞�.txt") - strategy_manager.low_suction_strtegy - - + codes = set() + codes_sh, codes_sz = l1_subscript_codes_manager.get_codes() + codes |= set([x.decode() for x in codes_sh]) + codes |= set([x.decode() for x in codes_sz]) + KPLCodeJXBlocksManager('2025-06-17', codes).start_download_blocks() + # target_block = {"鐭虫补鐭冲寲", "澶╃劧姘�", "鍖栧伐"} + # for code in code_blocks: + # blocks = code_blocks.get(code) + # if len(blocks & target_block) == len(target_block): + # print(code, blocks) diff --git a/strategy/time_series_backtest.py b/strategy/time_series_backtest.py index a8196a5..b5128c2 100644 --- a/strategy/time_series_backtest.py +++ b/strategy/time_series_backtest.py @@ -298,6 +298,9 @@ if code_ in self.stock_variables_dict: return + if code_ == '002907': + print("") + stock_variables = StrategyVariableFactory.create_from_history_data( timeline_data["kline_data"].get(code_), timeline_data["minute_data"].get(code_), timeline_data["limit_up_record_data"].get(code_), timeline_data["trade_days"]) @@ -583,6 +586,19 @@ most_real_kpl_plate_limit_up_codes_info[p] = [] most_real_kpl_plate_limit_up_codes_info[p].append(code) + # ---------娴嬭瘯-------- + # test_plate = "鍖栧伐" + # if len(most_real_kpl_plate_limit_up_codes_info.get(test_plate, [])) >= 3: + # print("娴嬭瘯寮�濮�=========") + # code_plates_for_buy = self.current_data["code_plates_for_buy"] + # plate_codes = [c for c in code_plates_for_buy if test_plate in code_plates_for_buy[c]] + # print(f"{test_plate}婊¤冻", time_str, plate_codes) + # for c in plate_codes: + # sv: StockVariables = self.stock_variables_dict.get(c) + # if sv and sv.褰撳墠浠� > sv.鏄ㄦ棩鏀剁洏浠�: + # print(c) + # print("娴嬭瘯瀹屾瘯=========") + if ticks: for tick in ticks: code = tick["symbol"][-6:] @@ -650,6 +666,7 @@ stock_variables.浠婃棩鏈�浣庝环 = tick["price"] if most_real_kpl_plate_limit_up_codes_info: stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� = most_real_kpl_plate_limit_up_codes_info + # if time_str >= '09:30:00': # if stock_variables.浠婃棩澶у崟鏁版嵁 and stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋� and max( # [len(stock_variables.寮�鐩樺暒鏈�姝f澘鍧楁定鍋�.get(x, [])) for x in stock_variables.浠g爜鏉垮潡]) >= 3: @@ -768,7 +785,7 @@ stock_variables.鏉垮潡鎴愪氦浠g爜 = self.deal_block_codes -# DEBUG_CODES = ['603040', '603758', '603286', '603586', '605255', '002048', '605208', '002806', '603266', '603788'] +# DEBUG_CODES = ['600727'] DEBUG_CODES = [] VOLUME_LOG_ENABLE = False @@ -777,7 +794,7 @@ DEBUG_BLOCKS = [] -BIG_ORDER_MONEY_THRESHOLD = 100e4 +BIG_ORDER_MONEY_THRESHOLD = 200e4 if __name__ == "__main__": back_test_dict = {} @@ -786,9 +803,9 @@ days = ["2025-05-12", "2025-05-13", "2025-05-14", "2025-05-15", "2025-05-16", "2025-05-19", "2025-05-20", "2025-05-21", "2025-05-22", "2025-05-23", "2025-05-26", "2025-05-27", "2025-05-28", "2025-05-29", "2025-05-30", "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-11", "2025-06-12", "2025-06-13", "2025-06-16"] - # days = ["2025-06-09"] + # days = ["2025-06-13"] days.reverse() for day in days: diff --git a/third_data/kpl_api.py b/third_data/kpl_api.py index 552e7fc..af721f9 100644 --- a/third_data/kpl_api.py +++ b/third_data/kpl_api.py @@ -361,7 +361,7 @@ # print(d) # # print(result) - print(getCodeJingXuanBlocks("002519")) + print(getCodeJingXuanBlocks("002878")) # results = getHistoryCodesByPlateOrderByLZCS("801199", "2025-05-16", "0930", 3) # results = json.loads(results)["list"] # for result in results: diff --git a/third_data/kpl_block_manager.py b/third_data/kpl_block_manager.py new file mode 100644 index 0000000..8d48f9a --- /dev/null +++ b/third_data/kpl_block_manager.py @@ -0,0 +1,55 @@ +""" +寮�鐩樺暒鏉垮潡绠$悊 +""" +import json + +import constant + +from db.mysql_data_delegate import Mysqldb +from third_data import kpl_api, kpl_util +from utils import tool + + +class KPLCodeJXBlocksManager: + """ + 寮�鐩樺暒绮鹃�夋澘鍧楃鐞� + """ + + def __init__(self, day, target_codes): + self.day = day + self.mysql_db = Mysqldb() + self.target_codes = target_codes + + def __download_blocks(self, code): + datas = kpl_api.getCodeJingXuanBlocks(code) + blocks = json.dumps([kpl_util.filter_block(x[1]) for x in datas], ensure_ascii=False) + block_ids = json.dumps([x[0] for x in datas], ensure_ascii=False) + block_details = json.dumps(datas, ensure_ascii=False) + id = f"{self.day}_{code}" + self.mysql_db.execute( + f"insert into kpl_code_blocks(id,code, day,jx_blocks, jx_block_ids, jx_blocks_detail, create_time) values('{id}','{code}','{self.day}','{blocks}', '{block_ids}','{block_details}', now())") + + def start_download_blocks(self): + codes = self.mysql_db.select_all(f"select code from kpl_code_blocks where day='{self.day}'") + codes = set([x[0] for x in codes]) + need_update_codes = set(self.target_codes) - codes + for code in need_update_codes: + self.__download_blocks(code) + + def get_all_code_blocks(self): + """ + 鑾峰彇鎵�鏈変唬鐮佺殑鏉垮潡 + @return: + """ + sql = f"select code, jx_blocks from kpl_code_blocks where day = '{self.day}'" + results = self.mysql_db.select_all(sql) + return {x[0]: set(json.loads(x[1])) - constant.KPL_INVALID_BLOCKS for x in results} + + def get_all_code_blocks_count(self): + """ + 鑾峰彇鎵�鏈変唬鐮佺殑鏉垮潡鐨勬暟閲� + @return: + """ + sql = f"select count(*) from kpl_code_blocks where day = '{self.day}'" + results = self.mysql_db.select_one(sql) + return int(results[0]) -- Gitblit v1.8.0