| | |
| | | TRADE_ENABLE = False |
| | | |
| | | # 是否需要报警 |
| | | NEED_ALERT =True |
| | | NEED_ALERT = False |
| | | |
| | | # 水下捞累计连续水下时间最小值 |
| | | UNDER_WATER_PRICE_TIME_AS_SECONDS = 1200 |
| | |
| | | L2_CODE_COUNT_PER_DEVICE = 6 |
| | | |
| | | # 买入分数分档 |
| | | BUY_SCORE_RANK_0 = 170 |
| | | BUY_SCORE_RANK_0 = 150 |
| | | BUY_SCORE_RANK_1 = 220 |
| | | BUY_SCORE_RANK_2 = 240 |
| | | BUY_SCORE_RANK_3 = 260 |
| | | |
| | | # 开盘啦 |
| | | KPL_INVALID_BLOCKS = ["一季报增长", "二季报增长", "三季报增长", "四季报增长", "业绩增长", "中报增长", "年报增长", "年报预增", "无", "次新股", "ST摘帽", "超跌", |
| | | "股权转让", "并购重组", "再融资", "年报预增", "次新股", " 专精特新", "壳资源"] |
| | |
| | | from trade import l2_trade_util |
| | | from trade.l2_trade_factor import L2TradeFactorUtil |
| | | from ocr import ocr_server |
| | | from third_data import data_server |
| | | from third_data import data_server, kpl_data_manager, kpl_util |
| | | |
| | | from server import * |
| | | import l2.l2_data_util |
| | | |
| | | # 读取server进程的消息 |
| | | from trade.trade_data_manager import CodeActualPriceProcessor |
| | | from ui.my_widget import FlatButton |
| | | |
| | | |
| | | def __read_server_pipe(pipe): |
| | |
| | | text = Text(frame, height=100, undo=True) |
| | | text.place(x=0, y=40) |
| | | |
| | | btn = Button(frame, text="运行环境检测", command=click) |
| | | btn = FlatButton(frame, text="运行环境检测", command=click) |
| | | btn.place(x=5, y=5) |
| | | |
| | | frame.grid(row=1, column=2) |
| | |
| | | # table.model.setValueAt(data["apply_time"], index, 2) |
| | | index += 1 |
| | | table.redraw() |
| | | # 刷新开盘啦数据 |
| | | def refresh_kpl_data(): |
| | | kpl_data_manager.KPLDataManager().get_data(kpl_util.KPLDataType.LIMIT_UP) |
| | | kpl_data_manager.KPLDataManager().get_data(kpl_util.KPLDataType.OPEN_LIMIT_UP) |
| | | kpl_data_manager.KPLDataManager().get_data(kpl_util.KPLDataType.BEST_FENG_KOU) |
| | | kpl_data_manager.KPLDataManager().get_data(kpl_util.KPLDataType.FENG_KOU) |
| | | kpl_data_manager.KPLDataManager().get_data(kpl_util.KPLDataType.FENG_XIANG) |
| | | |
| | | |
| | | start_y = 225 |
| | | btn = Button(frame, text="刷新收盘价", command=refresh_close_price_data) |
| | | btn = FlatButton(frame, text="刷新收盘价", command=refresh_close_price_data) |
| | | btn.place(x=5, y=start_y) |
| | | |
| | | sv_num = StringVar(value="获取到收盘价数量:未知") |
| | | cl = Label(frame, textvariable=sv_num, bg="#DDDDDD", fg="#666666") |
| | | cl.place(x=5, y=start_y + 30) |
| | | |
| | | btn = Button(frame, text="重新获取收盘价", command=re_get_close_price) |
| | | btn.place(x=130, y=start_y) |
| | | |
| | | btn = Button(frame, text="今日涨停", command=get_limit_up_codes_win) |
| | | btn.place(x=250, y=start_y) |
| | | btn = FlatButton(frame, text="重新获取收盘价", command=re_get_close_price) |
| | | btn.place(x=80, y=start_y) |
| | | kpl_data = Label(text="涨停:\n炸板:\n最强:\n风向:\n风口:",bg="#DDDDDD",fg="#666666") |
| | | kpl_data.place(x=190, y=start_y) |
| | | |
| | | trade_win_datas = [] |
| | | # draw_trade_buy_win(360, 140) |
| | |
| | | refresh_trade_buy_win_data() |
| | | refresh_close_price_data() |
| | | |
| | | btn = Button(frame, text="刷新", command=refresh_trade_buy_win_data, height=1) |
| | | btn = FlatButton(frame, text="刷新", command=refresh_trade_buy_win_data) |
| | | btn.place(x=450 - 35, y=start_y) |
| | | |
| | | def re_distribute_buy_win(): |
| | |
| | | except Exception as e: |
| | | showerror("分配出错", str(e)) |
| | | |
| | | btn = Button(frame, text="重新分配窗口", command=re_distribute_buy_win, height=1) |
| | | btn = FlatButton(frame, text="重新分配窗口", command=re_distribute_buy_win) |
| | | btn.place(x=450 - 83, y=start_y + 30) |
| | | |
| | | # 绘制交易状态 |
| | |
| | | |
| | | start_y = 285 |
| | | |
| | | btn = Button(frame, text="刷新状态", command=refresh_data) |
| | | btn = FlatButton(frame, text="刷新状态", command=refresh_data) |
| | | btn.place(x=10, y=start_y) |
| | | |
| | | auo_refresh = IntVar() |
| | |
| | | win.resizable(height=False, width=False) |
| | | text = Text(win, height=100, undo=True) |
| | | text.place(x=0, y=30) |
| | | btn = Button(win, text="一键修复", command=repair) |
| | | btn = FlatButton(win, text="一键修复", command=repair) |
| | | btn.place(x=0, y=0) |
| | | |
| | | line = 0 |
| | |
| | | else: |
| | | accept_l2.set(0) |
| | | |
| | | btn = Button(frame, text="每日初始化", command=init) |
| | | btn = FlatButton(frame, text="每日初始化", command=init) |
| | | btn.place(x=width - 250, y=5) |
| | | |
| | | btn = Button(frame, text="刷新数据", command=refresh_data) |
| | | btn = FlatButton(frame, text="刷新数据", command=refresh_data) |
| | | btn.place(x=width - 150, y=5) |
| | | auo_refresh = IntVar() |
| | | ch1 = Checkbutton(frame, text='自动刷新', variable=auo_refresh, onvalue=1, offvalue=0, background="#DDDDDD", |
| | |
| | | menu.add_command(label="环境检测", command=check_env) |
| | | menu.add_command(label="同花顺测速", command=ths_test_speed) |
| | | |
| | | device_index =0 |
| | | for key in self.l2_codes: |
| | | |
| | | client_lb = Label(frame, text="设备:{}".format(key), background="#DDDDDD") |
| | | device_index += 1 |
| | | client_lb = Label(frame, text="设备:{} ID:{}".format(device_index,key), background="#DDDDDD") |
| | | client_lb.place(x=38, y=40 + l2_client_count * 30) |
| | | btn = Button(frame, text="检测", command=key) |
| | | btn = FlatButton(frame, text="检测", command=key) |
| | | btn.bind('<Button-3>', lambda event: pop_menu(event)) |
| | | btn.place(x=5, y=35 + l2_client_count * 30) |
| | | |
| | | client_state_lb = Label(frame, text="(未知)", padx=0, pady=0, background="#DDDDDD", font=('微软雅黑', 8)) |
| | | client_state_lb.place(x=82, y=40 + l2_client_count * 30) |
| | | client_state_lb.place(x=112, y=40 + l2_client_count * 30) |
| | | client_state[key] = client_state_lb |
| | | code_sv_map[key] = [] |
| | | code_labels[key] = [] |
| | |
| | | code_labels[key].append(code_label) |
| | | |
| | | code_label.place(x=0, y=0) |
| | | cframe.place(x=200 + i * 85, y=40 + l2_client_count * 30) |
| | | cframe.place(x=250 + i * 85, y=40 + l2_client_count * 30) |
| | | l2_client_count += 1 |
| | | # 添加更新线程 |
| | | t1 = threading.Thread(target=lambda: update_data()) |
| | |
| | | cl = Label(frame, textvariable=sv_trade_money, bg="#DDDDDD", fg="#666666") |
| | | cl.place(x=190, y=5) |
| | | |
| | | btn = Button(frame, text="刷新数据", command=refresh_data) |
| | | btn = FlatButton(frame, text="刷新数据", command=refresh_data) |
| | | btn.place(x=width - 150, y=5) |
| | | auo_refresh = IntVar() |
| | | ch1 = Checkbutton(frame, text='自动刷新', variable=auo_refresh, onvalue=1, offvalue=0, background="#DDDDDD", |
| | |
| | | entry = Entry(frame, textvariable=token_var, width=30) |
| | | entry.place(x=left + 60, y=top + 60) |
| | | |
| | | btn = Button(frame, text="设置掘金参数", command=click) |
| | | btn = FlatButton(frame, text="设置掘金参数", command=click) |
| | | btn.place(x=left + 60, y=top + 90) |
| | | # frame.place(x=260,y=10) |
| | | frame.grid(row=0, column=2, pady=5, padx=5) |
| | |
| | | code = Entry(frame) |
| | | code.place(x=50, y=70) |
| | | |
| | | btn = Button(frame, text="设置代码", command=lambda: setGPCode(ep_client.get(), ep.get(), code.get()), ) |
| | | btn = FlatButton(frame, text="设置代码", command=lambda: setGPCode(ep_client.get(), ep.get(), code.get()), ) |
| | | btn.place(x=10, y=100) |
| | | |
| | | btn = Button(frame, text="修复L2数据", command=lambda: L2CodeOperate.get_instance().repaire_l2_data(code.get())) |
| | | btn = FlatButton(frame, text="修复L2数据", command=lambda: L2CodeOperate.get_instance().repaire_l2_data(code.get())) |
| | | btn.place(x=70 |
| | | , y=100) |
| | | |
| | | btn = Button(frame, text="导出L2数据", command=lambda: export_l2_data(code.get())) |
| | | btn = FlatButton(frame, text="导出L2数据", command=lambda: export_l2_data(code.get())) |
| | | btn.place(x=145, y=100) |
| | | |
| | | btn = Button(frame, text="导出L2原始数据", command=lambda: export_l2_data_origin(code.get())) |
| | | btn = FlatButton(frame, text="导出L2原始数据", command=lambda: export_l2_data_origin(code.get())) |
| | | btn.place(x=220, y=100) |
| | | |
| | | btn = Button(frame, text="获取m值", command=lambda: compute_m(code.get())) |
| | | btn = FlatButton(frame, text="获取m值", command=lambda: compute_m(code.get())) |
| | | btn.place(x=10, y=130) |
| | | |
| | | btn = Button(frame, text="导出交易日志", command=lambda: log.export_l2_log(code.get())) |
| | | btn = FlatButton(frame, text="导出交易日志", command=lambda: log.export_l2_log(code.get())) |
| | | btn.place(x=80, y=130) |
| | | |
| | | btn = Button(frame, text="清空l2数据", command=lambda: clear_l2(code.get())) |
| | | btn = FlatButton(frame, text="清空l2数据", command=lambda: clear_l2(code.get())) |
| | | btn.place(x=150, y=130) |
| | | |
| | | btn = Button(frame, text="撤销挂单", command=lambda: cancel_order(code.get())) |
| | | btn = FlatButton(frame, text="撤销挂单", command=lambda: cancel_order(code.get())) |
| | | btn.place(x=230, y=130) |
| | | |
| | | # 交易按钮 |
| | | btn = Button(frame, textvariable=btntext, command=startJueJinGui) |
| | | btn = FlatButton(frame, textvariable=btntext, command=startJueJinGui) |
| | | btn.place(x=10, y=160) |
| | | btntext.set("启动掘金") |
| | | |
| | | btn = Button(frame, text="重新订阅行情", command=resub) |
| | | btn = FlatButton(frame, text="重新订阅行情", command=resub) |
| | | btn.place(x=10, y=190) |
| | | |
| | | btn = Button(frame, text="刷新窗口句柄", command=refresh_hwnds) |
| | | btn = FlatButton(frame, text="刷新窗口句柄", command=refresh_hwnds) |
| | | btn.place(x=200, y=190) |
| | | |
| | | def create_gui(self): |
| | |
| | | from db import redis_manager |
| | | import ths_industry_util |
| | | import tool |
| | | from trade import trade_manager, trade_queue_manager, l2_trade_factor, l2_trade_util, \ |
| | | from third_data.code_plate_key_manager import CodePlateKeyBuyManager |
| | | from trade import trade_manager, trade_queue_manager, l2_trade_factor, l2_trade_util, \ |
| | | trade_result_manager, first_code_score_manager |
| | | from l2 import safe_count_manager, l2_data_manager, l2_data_log, l2_log, l2_data_source_util, code_price_manager |
| | | from l2.cancel_buy_strategy import SecondCancelBigNumComputer, HourCancelBigNumComputer, L2LimitUpMoneyStatisticUtil, \ |
| | |
| | | def h_cancel(): |
| | | _start_time = round(t.time() * 1000) |
| | | try: |
| | | b_need_cancel, b_cancel_data = HourCancelBigNumComputer.need_cancel(code,buy_single_index, buy_exec_index, start_index, |
| | | b_need_cancel, b_cancel_data = HourCancelBigNumComputer.need_cancel(code, buy_single_index, |
| | | buy_exec_index, start_index, |
| | | end_index, total_data, |
| | | local_today_num_operate_map.get( |
| | | code), |
| | |
| | | if buy1_price is None: |
| | | return False, True, f"尚未获取到买1价" |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | |
| | | dif = float(limit_up_price) - float(buy1_price) |
| | | if zyltgb >= 80 * 100000000: |
| | | # 大于2档 |
| | |
| | | |
| | | if not gpcode_manager.WantBuyCodesManager.is_in(code): |
| | | |
| | | if float(limit_up_price) >= 40: |
| | | return False, True, "股价大于40块" |
| | | |
| | | # 判断板块 |
| | | plate_can_buy, msg = CodePlateKeyBuyManager.can_buy(code) |
| | | if not plate_can_buy: |
| | | return False, True, msg |
| | | |
| | | # 查看分数等级 |
| | | score_index = cls.__l2PlaceOrderParamsManagerDict[code].score_index |
| | | score = cls.__l2PlaceOrderParamsManagerDict[code].score |
| | |
| | | limit_up_time = score_info[1][7] |
| | | if limit_up_time is None: |
| | | limit_up_time = tool.get_now_time_str() |
| | | if int(limit_up_time.replace(":", "")) > int("143000"): |
| | | if not score_info[1][3][6][0]: |
| | | return False, True, f"尾盘偷跑:无任何形态" |
| | | if score_info[1][5]["limit_up_codes_count"] > 1: |
| | | return False, True, f"尾盘偷跑:板块{score_info[1][5]['target_block_info'][0]}-涨停数{score_info[1][5]['limit_up_codes_count']}" |
| | | if float(gpcode_manager.get_limit_up_price(code)) > 30: |
| | | return False, True, f"尾盘偷跑:股价大于30" |
| | | |
| | | # 尾盘偷跑暂时不要 |
| | | # if int(limit_up_time.replace(":", "")) > int("143000"): |
| | | # if not score_info[1][3][6][0]: |
| | | # return False, True, f"尾盘偷跑:无任何形态" |
| | | # if score_info[1][5]["limit_up_codes_count"] > 1: |
| | | # return False, True, f"尾盘偷跑:板块{score_info[1][5]['target_block_info'][0]}-涨停数{score_info[1][5]['limit_up_codes_count']}" |
| | | # if float(gpcode_manager.get_limit_up_price(code)) > 30: |
| | | # return False, True, f"尾盘偷跑:股价大于30" |
| | | |
| | | if score_index < 0: |
| | | return False, True, f"分值:{score}未达到需要买入的分数线" |
| | | if score_index >= 3: |
| | | return False, True, f"分值:{score}未达到主动买入分数线" |
| | | return True, False, "" |
| | | # if -1 < score_index < 3 and (0.499 <= cls.volume_rate_info[code][0] <= 0.949): |
| | | # return True, False, f"分值:{score}达到主动买入的分数线且量足够,买入等级:f{score_index},量比:{cls.volume_rate_info[code][0]}" |
| | | is_limited_up = gpcode_manager.FirstCodeManager.is_limited_up(code) |
| | | gpcode_manager.FirstCodeManager.add_limited_up_record([code]) |
| | | if not code_price_manager.Buy1PriceManager.is_can_buy(code): |
| | | return False, True, f"首板代码,没在想要买名单中且未打开涨停板,分数:{score}" |
| | | if not is_limited_up: |
| | | return False, True, f"首板代码,没在想要买名单中且未涨停过,分数:{score}" |
| | | # if score_index >= 3: |
| | | # return False, True, f"分值:{score}未达到主动买入分数线" |
| | | return True, False, "" |
| | | else: |
| | | return True, False, "在想买名单中" |
| | |
| | | filter=lambda record: record["extra"].get("name") == "place_order_score", |
| | | rotation="00:00", compression="zip", enqueue=True) |
| | | |
| | | logger.add(self.get_path("kpl", "kpl_limit_up_reason_change"), |
| | | filter=lambda record: record["extra"].get("name") == "kpl_limit_up_reason_change", |
| | | rotation="00:00", compression="zip", enqueue=True) |
| | | |
| | | logger.add(self.get_path("kpl", "kpl_limit_up"), |
| | | filter=lambda record: record["extra"].get("name") == "kpl_limit_up", |
| | | rotation="00:00", compression="zip", enqueue=True) |
| | | |
| | | def get_path(self, dir_name, log_name): |
| | | return "D:/logs/gp/{}/{}".format(dir_name, log_name) + ".{time:YYYY-MM-DD}.log" |
| | | |
| | |
| | | logger_trade_record = __mylogger.get_logger("trade_record") |
| | | |
| | | logger_place_order_score = __mylogger.get_logger("place_order_score") |
| | | |
| | | logger_kpl_limit_up_reason_change = __mylogger.get_logger("kpl_limit_up_reason_change") |
| | | |
| | | logger_kpl_limit_up = __mylogger.get_logger("kpl_limit_up") |
| | | |
| | | |
| | | class LogUtil: |
| | | @classmethod |
| | |
| | | |
| | | def export_logs(code): |
| | | code_name = gpcode_manager.get_code_name(code) |
| | | date = datetime.datetime.now().strftime("%Y-%m-%d") |
| | | date = datetime.datetime.now().strftime("%Y-%m-%d") |
| | | target_dir = f"D:/logs/gp/l2/export/{code}_{code_name}_{date}" |
| | | if os.path.exists(target_dir): |
| | | shutil.rmtree(target_dir) |
| | | os.makedirs(target_dir) |
| | | log_names = ["l2_process", "l2_trade", "l2_trade_cancel", "l2_process_time", "l2_trade_buy", "l2_trade_buy_progress", "cancel/h_cancel"] |
| | | log_names = ["l2_process", "l2_trade", "l2_trade_cancel", "l2_process_time", "l2_trade_buy", |
| | | "l2_trade_buy_progress", "cancel/h_cancel"] |
| | | # 导出交易日志 |
| | | for log_name in log_names: |
| | | key = f"code={code}" |
| | |
| | | LogUtil.extract_log_from_key(key, f"D:/logs/gp/l2/{log_name}.{date}.log", |
| | | target_path) |
| | | |
| | | |
| | | def export_trade_progress(code): |
| | | path =f"D:/logs/gp/l2/l2_trade_buy_progress.{tool.get_now_date_str()}.log" |
| | | index_set=set() |
| | | with open(path,mode='r',encoding="utf-8") as f: |
| | | path = f"D:/logs/gp/l2/l2_trade_buy_progress.{tool.get_now_date_str()}.log" |
| | | index_set = set() |
| | | with open(path, mode='r', encoding="utf-8") as f: |
| | | lines = f.readlines() |
| | | for line in lines: |
| | | if line.find(f"code-{code}") > -1 and line.find("确定交易进度成功")>-1: |
| | | index= line.split("index-")[1].split(" ")[0] |
| | | if line.find(f"code-{code}") > -1 and line.find("确定交易进度成功") > -1: |
| | | index = line.split("index-")[1].split(" ")[0] |
| | | index_set.add(int(index)) |
| | | results = list(index_set) |
| | | results.sort() |
| | | return results |
| | | |
| | | |
| | | |
| | | |
| | | # 加载买入得分记录 |
| | |
| | | time_str = line[11:19] |
| | | data = line[line.find("data=") + 5:] |
| | | type = line[line.find("type=") + 5:line.find(" ", line.find("type="))] |
| | | fdatas.append((time_str, type, eval("{"+data+"}"))) |
| | | fdatas.append((time_str, type, eval("{" + data + "}"))) |
| | | return fdatas |
| | | |
| | | |
| | | def load_kpl_reason_changes(): |
| | | path = f"D:/logs/gp/kpl/kpl_limit_up_reason_change.{tool.get_now_date_str()}.log" |
| | | fdatas = [] |
| | | if os.path.exists(path): |
| | | with open(path, 'r', encoding="utf-8") as f: |
| | | lines = f.readlines() |
| | | for line in lines: |
| | | data = line[line.find("code-") + 5:] |
| | | code = data.split(":")[0] |
| | | from_r = data.split(":")[1].split("-")[0] |
| | | to_r = eval(data.split(":")[1].split("-")[1]) |
| | | fdatas.append((code, from_r, to_r)) |
| | | return fdatas |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | print(logger_place_order_score.info("002681")) |
| | | |
| | | |
| | | print(load_kpl_reason_changes()) |
| | | |
| | | # logger_l2_h_cancel.info("test") |
| | | # logger_l2_process_time.info("test123") |
| | |
| | | |
| | | |
| | | def get_output_html(code): |
| | | def money_desc(money): |
| | | if money > 100000000: |
| | | return f"{round(money / 100000000, 2)}亿" |
| | | else: |
| | | return f"{round(money / 10000, 2)}万" |
| | | return render(get_output_params(code)) |
| | | |
| | | |
| | | def money_desc(money): |
| | | if money > 100000000: |
| | | return f"{round(money / 100000000, 2)}亿" |
| | | else: |
| | | return f"{round(money / 10000, 2)}万" |
| | | |
| | | |
| | | def get_output_params(code): |
| | | params = { |
| | | "base_url": "http://192.168.3.252/kp/", |
| | | } |
| | |
| | | deal_indexes = trade.deal_big_money_manager.get_traded_indexes(code) |
| | | deal_info = "" |
| | | params["score_data"]["deal_big_money"] = {"score": score_list[8], "money": score_source_list[8][0] // 10000, |
| | | "base_money": score_source_list[8][1] // 10000} |
| | | "base_money": score_source_list[8][1] // 10000, |
| | | "rate": round(score_source_list[8][0] / score_source_list[8][1], 2)} |
| | | if deal_indexes: |
| | | temps = [] |
| | | for index in deal_indexes: |
| | |
| | | for k in range(0, len(score_source_list[3])): |
| | | if k == 0: |
| | | if score_source_list[3][k][0]: |
| | | k_source.append("涨幅过高") |
| | | k_source.append(("涨幅过高", score_list[3][k])) |
| | | elif k == 1: |
| | | if score_source_list[3][k][0]: |
| | | k_source.append("突破前高") |
| | | k_source.append(("突破前高", score_list[3][k])) |
| | | elif k == 2: |
| | | if score_source_list[3][k][0]: |
| | | k_source.append("超跌补涨") |
| | | k_source.append(("超跌补涨", score_list[3][k])) |
| | | elif k == 3: |
| | | if score_source_list[3][k][0]: |
| | | k_source.append(f"逼近前高-{score_source_list[3][k][1]}】") |
| | | k_source.append((f"逼近前高-{score_source_list[3][k][1]}】", score_list[3][k])) |
| | | elif k == 4: |
| | | if score_source_list[3][k][0]: |
| | | k_source.append("N字型") |
| | | k_source.append(("N字型", score_list[3][k])) |
| | | elif k == 5: |
| | | if score_source_list[3][k][0]: |
| | | k_source.append("V字型") |
| | | k_source.append(("V字型", score_list[3][k])) |
| | | elif k == 6: |
| | | if not score_source_list[3][k][0]: |
| | | k_source.append("不满足任何形态") |
| | | k_source.append(("不满足任何形态", score_list[3][k])) |
| | | elif k == 7: |
| | | if score_source_list[3][k][0]: |
| | | k_source.append("天量大阳") |
| | | k_source.append(("天量大阳", score_list[3][k])) |
| | | |
| | | params["score_data"]["k_form"] = {"score": k_score, "datas": k_source} |
| | | |
| | |
| | | for k in score_list[4]: |
| | | nature_score += k |
| | | |
| | | code_nature_datas = {"score": nature_score, "limit_up_count": score_source_list[4][0]} |
| | | |
| | | for n in range(0, len(score_source_list[4])): |
| | | if n == 0: |
| | | nature_source.append(f"涨停次数【{score_source_list[4][n]}】") |
| | | elif n == 1: |
| | | if score_source_list[4][n]: |
| | | nature_source.append(f"首板溢价率【{round(score_source_list[4][n], 2)}】") |
| | | code_nature_datas["first_limit_up_yijia"] = round(score_source_list[4][1], 2) |
| | | else: |
| | | nature_source.append(f"无首板") |
| | | code_nature_datas["first_limit_up_yijia"] = "无首板" |
| | | elif n == 2: |
| | | if score_source_list[4][n]: |
| | | nature_source.append(f"首板炸板溢价率【{round(score_source_list[4][n], 2)}】") |
| | | code_nature_datas["first_open_limit_up_yijia"] = round(score_source_list[4][2], 2) |
| | | else: |
| | | nature_source.append(f"无首板炸板") |
| | | code_nature_datas["first_open_limit_up_yijia"] = "无首板炸板" |
| | | |
| | | params["score_data"]["code_nature"] = {"score": nature_score, "data_desc": ",".join(nature_source)} |
| | | params["score_data"]["code_nature"] = code_nature_datas |
| | | |
| | | # 板块热度 |
| | | hot_block_score = 0 |
| | |
| | | "limit_up_index": hot_block_source_data['limit_up_index'] + 1, |
| | | "block_name": hot_block_source_data['target_block_info'][0], |
| | | "limit_up_count": hot_block_source_data['limit_up_codes_count'], |
| | | "block_history_count": hot_block_source_data['target_block_info'][2], |
| | | "open_limit_up_count": hot_block_source_data['break_size']} |
| | | |
| | | # 上板时间 |
| | |
| | | global_data_loader.load_zyltgb() |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | base_m = L2TradeFactorUtil.get_base_safe_val(zyltgb) |
| | | params["trade_data"]["m_val"] = {"base": base_m // 10000, "now": m[0] // 10000}, |
| | | params["trade_data"]["m_val"] = {"base": base_m // 10000, "now": m[0] // 10000} |
| | | # 买前大单 |
| | | big_num = __L2PlaceOrderParamsManager.get_big_num_count() |
| | | base_big_num = __base_L2PlaceOrderParamsManager.get_big_num_count() |
| | |
| | | elif trade_state == trade_manager.TRADE_STATE_BUY_SUCCESS: |
| | | params["trade_data"]["trade_state"]["desc"] = "已成交" |
| | | |
| | | ##############################选股宝################################## |
| | | |
| | | params["xgb_code_infos"] = [] |
| | | |
| | | ##############################热门风口################################## |
| | | |
| | | params["xgb_infos"] = [] |
| | | |
| | | ##############################主动买,被动买################################## |
| | | # 返回主动买,被动买,不买的列表(代码, 名称, 得分, 是否涨停) |
| | | codes_score = __load_codes_scores() |
| | | params["initiative_buy_codes"] = [] |
| | |
| | | for d in codes_score[1]: |
| | | params["passive_buy_codes"].append( |
| | | {"name": d[1], "code": d[0], "score": d[2], "limit_up": d[3], "open_limit_up": d[4]}) |
| | | # 主动买与被动买不能超过11行 |
| | | initiative_count = len(params["initiative_buy_codes"]) |
| | | passive_count = len(params["passive_buy_codes"]) |
| | | buy_row = 0 |
| | | buy_row += initiative_count // 3 |
| | | if initiative_count % 3 > 0: |
| | | buy_row += 1 |
| | | max_passive_count = (10 - buy_row) * 3 |
| | | if max_passive_count < 0: |
| | | max_passive_count = 0 |
| | | params["passive_buy_codes"] = params["passive_buy_codes"][:max_passive_count] |
| | | |
| | | trade_info = __load_trade_record(code, total_datas) |
| | | params["trade_record"] = {"open_limit_up": trade_info[0], "records": trade_info[2]} |
| | | |
| | | ##############################开盘啦相关信息################################## |
| | | params["kpl_code_info"] = {} |
| | | params["kpl_code_info"] = {"industry":global_util.code_industry_map.get(code)} |
| | | # 获取开盘啦板块 |
| | | plate_info = kpl_api.getStockIDPlate(code) |
| | | if plate_info: |
| | |
| | | plate_info.reverse() |
| | | params["kpl_code_info"]["plate"] = plate_info |
| | | |
| | | # 获取代码的历史涨停数据 |
| | | params["kpl_code_info"]["code_records"] = KPLLimitUpDataRecordManager.get_latest_infos(code, 4) |
| | | # 获取代码的历史涨停数据,(涨停原因,日期,板块) |
| | | params["kpl_code_info"]["code_records"] = KPLLimitUpDataRecordManager.get_latest_infos(code, 4, False)[:2] |
| | | |
| | | # 获取今日板块 |
| | | block = block_info.get_target_block(code, False) |
| | | if block is None: |
| | | block = "无板块" |
| | | # 获取最近的4个交易日 |
| | | today = tool.get_now_date_str() |
| | | days = [] |
| | | day = today |
| | | for i in range(3): |
| | | day = juejin.JueJinManager.get_previous_trading_date(day) |
| | | days.append(day) |
| | | days.insert(0, today) |
| | | # 获取这几天的涨停代码 |
| | | kpl_record_datas = {} |
| | | for d in days: |
| | | tem_datas = KPLLimitUpDataRecordManager.list_by_block(block, d) |
| | | tem_datas = list(tem_datas) |
| | | # 根据涨停时间排序 |
| | | tem_datas.sort(key=lambda x: int(x[5])) |
| | | if not KPLLimitUpDataRecordManager.total_datas: |
| | | KPLLimitUpDataRecordManager.load_total_datas() |
| | | for d in KPLLimitUpDataRecordManager.total_datas: |
| | | if d[3] == code: |
| | | # 获取今日 |
| | | params["kpl_code_info"]["today"] = (d[2], d[1], d[6]) |
| | | break |
| | | |
| | | kpl_record_datas[d] = {"codes": [], "hot_block": block, "index": -1, "limit_up_count": 0} |
| | | for i in range(len(tem_datas)): |
| | | temp = tem_datas[i] |
| | | __code = temp[3] |
| | | kpl_record_datas[d]["codes"].append( |
| | | {"name": temp[4], "code": __code, "limit_up": False, "open_limit_up": False,"ss":(__code.find("00")==0 or __code.find("60")==0) }) |
| | | if __code == code: |
| | | kpl_record_datas[d]["blocks"] = temp[6].split("、") |
| | | kpl_record_datas[d]["index"] = i + 1 |
| | | kpl_record_datas[d]["limit_up_time"] = time.strftime("%H:%M:%S", time.localtime(int(temp[5]))) |
| | | # 获取今日代码的得分 |
| | | __score_dict = {} |
| | | for fs in codes_score: |
| | | for s in fs: |
| | | # (得分,是否涨停) |
| | | __score_dict[s[0]] = (s[2], s[3]) |
| | | # 获取分值 |
| | | for d in kpl_record_datas[today]["codes"]: |
| | | __code = d["code"] |
| | | if __code in __score_dict: |
| | | d["score"] = __score_dict[__code][0] |
| | | # 获取是否涨停,统计涨停数量 |
| | | for d in kpl_record_datas: |
| | | # 获取涨停代码信息 |
| | | limit_up_datas = __kplDataManager.get_from_file(kpl_util.KPLDataType.LIMIT_UP, d) |
| | | if limit_up_datas is None: |
| | | limit_up_datas = [] |
| | | limit_up_codes = set([x[0] for x in limit_up_datas]) |
| | | limit_up_count = 0 |
| | | for code_info in kpl_record_datas[d]["codes"]: |
| | | __code = code_info["code"] |
| | | if __code in limit_up_codes: |
| | | code_info["limit_up"] = True |
| | | code_info["open_limit_up"] = False |
| | | limit_up_count += 1 |
| | | else: |
| | | code_info["limit_up"] = False |
| | | code_info["open_limit_up"] = True |
| | | kpl_record_datas[d]["limit_up_count"] = limit_up_count |
| | | |
| | | block_records = [[key, kpl_record_datas[key]] for key in kpl_record_datas] |
| | | block_records.sort(key=lambda x: x[0]) |
| | | block_records.reverse() |
| | | for i in range(len(block_records)): |
| | | if i == 0: |
| | | block_records[i][0] = "今天" |
| | | elif i == 1: |
| | | block_records[i][0] = "昨天" |
| | | elif i == 2: |
| | | block_records[i][0] = "前天" |
| | | elif i == 3: |
| | | block_records[i][0] = "之前" |
| | | |
| | | params["kpl_code_info"]["block_records"] = block_records |
| | | |
| | | return render(params) |
| | | return params |
| | | |
| | | |
| | | def __load_codes_scores(): |
| | |
| | | } |
| | | |
| | | .table-name { |
| | | height: 30px; |
| | | height: 50px; |
| | | width: 520px; |
| | | line-height: 30px; |
| | | line-height: 50px; |
| | | padding-left: 10px; |
| | | margin-top: 12px; |
| | | font-size: 16px; |
| | |
| | | <span class="bold">{{trade_data.star.desc}}</span> |
| | | {% endif %} |
| | | {% for i in range(0,trade_data.star.count) %} |
| | | <img src="{{base_url}}images/star.png" / style="margin-left: 3px;"></span> |
| | | <img src="{{base_url}}images/star.png" style="margin-left: 3px;"></span> |
| | | {% endfor %} |
| | | </td> |
| | | </tr> |
New file |
| | |
| | | """ |
| | | 涨停数据过滤器 |
| | | """ |
| | | |
| | | # 判断是龙几,判断是否涨停,判断是否炸板,加载分数 |
| | | import redis |
| | | |
| | | import code_volumn_manager |
| | | import gpcode_manager |
| | | import limit_up_time_manager |
| | | import tool |
| | | from db import redis_manager |
| | | from third_data.kpl_data_manager import KPLDataManager |
| | | from third_data.kpl_util import KPLDataType |
| | | from trade import first_code_score_manager |
| | | |
| | | __kplDataManager = KPLDataManager() |
| | | |
| | | |
| | | # 忽略代码管理器 |
| | | class IgnoreCodeManager: |
| | | __redisManager = redis_manager.RedisManager(3) |
| | | |
| | | def __get_redis(self): |
| | | return self.__redisManager.getRedis() |
| | | |
| | | def ignore_code(self, type, code): |
| | | self.__get_redis().sadd(f"kp_ignore_codes_{type}", code) |
| | | self.__get_redis().expire(f"kp_ignore_codes_{type}", tool.get_expire()) |
| | | |
| | | def list_ignore_codes(self, type): |
| | | return self.__get_redis().smembers(f"kp_ignore_codes_{type}") |
| | | |
| | | |
| | | # 获取涨停顺序(按涨停原因分组) |
| | | def get_limit_up_time_rank_dict(datas): |
| | | datas.sort(key=lambda x: int(x[5])) |
| | | max_record = {} |
| | | rank_dict = {} |
| | | for d in datas: |
| | | if d[2] not in max_record: |
| | | max_record[d[2]] = 0 |
| | | max_record[d[2]] = max_record[d[2]] + 1 |
| | | rank_dict[d[3]] = max_record[d[2]] |
| | | return rank_dict |
| | | |
| | | |
| | | # 获取涨停信息 |
| | | def get_limit_up_info(codes): |
| | | limit_up_data = __kplDataManager.get_data(KPLDataType.LIMIT_UP) |
| | | limit_up_codes = set([val[0] for val in limit_up_data]) |
| | | open_limit_up_data = __kplDataManager.get_data(KPLDataType.OPEN_LIMIT_UP) |
| | | open_limit_up_codes = set() |
| | | if open_limit_up_data: |
| | | open_limit_up_codes = set([val[0] for val in open_limit_up_data]) |
| | | dict_ = {} |
| | | for code in codes: |
| | | dict_[code] = (code in limit_up_codes, code in open_limit_up_codes) |
| | | return dict_, limit_up_codes, open_limit_up_codes |
| | | |
| | | |
| | | # 获取代码分数字典 |
| | | def get_codes_scores_dict(codes): |
| | | # 获取所有监听中的代码 |
| | | first_codes = gpcode_manager.get_first_gp_codes() |
| | | scores = {} |
| | | for code in codes: |
| | | if code not in first_codes: |
| | | continue |
| | | if code not in scores: |
| | | # 获取分数 |
| | | try: |
| | | limit_up_time = limit_up_time_manager.get_limit_up_time(code) |
| | | volume_rate, volume_info = code_volumn_manager.get_volume_rate(code, True) |
| | | (score, score_list), score_source_list = first_code_score_manager.get_score(code, volume_rate, |
| | | limit_up_time, |
| | | True) |
| | | scores[code] = score |
| | | except: |
| | | pass |
| | | return scores |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | get_limit_up_info() |
New file |
| | |
| | | import time |
| | | |
| | | |
| | | def money_desc(money): |
| | | if money > 100000000: |
| | | return f"{round(money / 100000000, 2)}亿" |
| | | else: |
| | | return f"{round(money / 10000, 2)}万" |
| | | |
| | | |
| | | def time_format(timestamp): |
| | | if timestamp: |
| | | return time.strftime("%H:%M:%S", time.localtime(int(timestamp))) |
| | | return "" |
| | |
| | | import ths_util |
| | | import tool |
| | | from output import code_info_output |
| | | from third_data import hot_block_data_process, block_info |
| | | from third_data import hot_block_data_process, block_info, kpl_api, kpl_util |
| | | from third_data.code_plate_key_manager import TargetCodePlateKeyManager |
| | | from third_data.kpl_data_manager import KPLCodeLimitUpReasonManager, KPLLimitUpDataRecordManager |
| | | from ths import l2_listen_pos_health_manager |
| | | from trade import trade_gui, trade_data_manager, trade_manager, l2_trade_util, deal_big_money_manager, \ |
| | | first_code_score_manager, current_price_process_manager |
| | |
| | | first_tick_datas = [] |
| | | latest_oringin_data = {} |
| | | last_l2_listen_health_time = {} |
| | | __KPLCodeLimitUpReasonManager = KPLCodeLimitUpReasonManager() |
| | | __TargetCodePlateKeyManager = TargetCodePlateKeyManager() |
| | | |
| | | def setup(self): |
| | | super().setup() # 可以不调用父类的setup()方法,父类的setup方法什么都没做 |
| | |
| | | if gpcode_manager.get_limit_up_price(code) is None: |
| | | juejin.re_set_price_pres([code], True) |
| | | |
| | | # 板块关键字准备 |
| | | for code in codes: |
| | | if self.__TargetCodePlateKeyManager.get_history_limit_up_reason(code) is None: |
| | | self.__TargetCodePlateKeyManager.set_history_limit_up_reason(code, |
| | | KPLLimitUpDataRecordManager.get_latest_blocks_set( |
| | | code)) |
| | | if self.__TargetCodePlateKeyManager.get_blocks(code) is None: |
| | | try: |
| | | results = kpl_api.getStockIDPlate(code) |
| | | bs = [r[1] for r in results] |
| | | self.__TargetCodePlateKeyManager.set_blocks(code, bs) |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | pass |
| | | |
| | | # 获取60天最大记录 |
| | | for code in codes: |
| | | need_get_volumn = False |
| | |
| | | # 加入首板涨停 |
| | | gpcode_manager.FirstCodeManager.add_limited_up_record([code]) |
| | | pricePre = gpcode_manager.get_price_pre(code) |
| | | if pricePre is None: |
| | | juejin.re_set_price_pres([code]) |
| | | |
| | | rate = round((float(price) - pricePre) * 100 / pricePre, 1) |
| | | prices.append( |
| | | {"code": code, "time": limit_up_time, "rate": rate, |
| | |
| | | __start_time = time.time() |
| | | final_data = {'code': code, 'data': code_info_output.get_output_html(code)} |
| | | return_str = json.dumps({"code": 0, "data": final_data}) |
| | | print("代码信息获取时间",code,round((time.time()-__start_time)*1000)) |
| | | print("代码信息获取时间", code, round((time.time() - __start_time) * 1000)) |
| | | pass |
| | | # 获取最近2个交易日涨停代码 |
| | | elif type == 72: |
| | |
| | | results = juejin.JueJinManager.get_gp_codes_names([code]) |
| | | if results: |
| | | gpcode_manager.CodesNameManager.add_first_code_name(code, results[code]) |
| | | if "plates" in data["data"]: |
| | | for i in range(len(data["data"]["plates"])): |
| | | self.__KPLCodeLimitUpReasonManager.save_reason(codes[i], data["data"]["plates"][i]) |
| | | |
| | | return_str = json.dumps({"code": 0}) |
| | | elif type == 402: |
| | | data = json.loads(_str) |
| | | codes = data["data"]["codes"] |
| | |
| | | gpcode_manager.WantBuyCodesManager.remove_code(code) |
| | | return_str = json.dumps({"code": 0}) |
| | | elif type == 403: |
| | | plate = None |
| | | include_codes = set() |
| | | if _str: |
| | | data = json.loads(_str) |
| | | plate = data.get("plate") |
| | | if plate: |
| | | code_map = self.__KPLCodeLimitUpReasonManager.list_all() |
| | | for k in code_map: |
| | | if code_map[k] == plate: |
| | | include_codes.add(k) |
| | | |
| | | codes = gpcode_manager.WantBuyCodesManager.list_code() |
| | | datas = [] |
| | | for code in codes: |
| | | if plate and plate != '其他' and code not in include_codes: |
| | | continue |
| | | name = gpcode_manager.get_code_name(code) |
| | | datas.append(f"{name}:{code}") |
| | | |
| | | return_str = json.dumps({"code": 0, "data": datas}) |
| | | elif type == 501: |
| | | data = json.loads(_str) |
| | |
| | | elif type == 502: |
| | | can_buy = trade_manager.TradeStateManager.is_can_buy() |
| | | return_str = json.dumps({"code": 0, "data": {"can_buy": can_buy}}) |
| | | elif type == 601: |
| | | pass |
| | | # 加自选 |
| | | elif type == 602: |
| | | pass |
| | | # 移除自选 |
| | | |
| | | sk.send(return_str.encode()) |
| | | |
| | |
| | | """ |
| | | import datetime |
| | | |
| | | import constant |
| | | import juejin |
| | | import tool |
| | | from third_data import kpl_util, kpl_data_manager |
| | |
| | | for data in limit_up_datas: |
| | | if data[0] == code: |
| | | block = data[5] |
| | | if block in kpl_data_manager.INVALID_BLOCKS and filter: |
| | | if block in constant.KPL_INVALID_BLOCKS and filter: |
| | | continue |
| | | blocks.append(block) |
| | | return blocks |
| | |
| | | return blocks |
| | | |
| | | |
| | | def get_target_block(code, filter=False): |
| | | def get_target_block_info(code, filter=False): |
| | | latest_datas = __kplDataManager.get_data(kpl_util.KPLDataType.LIMIT_UP) |
| | | blocks = __get_blocks(code, latest_datas, filter) |
| | | if not blocks: |
| | |
| | | target_block = None |
| | | if blocks: |
| | | for block in blocks: |
| | | if block in kpl_data_manager.INVALID_BLOCKS and filter: |
| | | if block in constant.KPL_INVALID_BLOCKS and filter: |
| | | continue |
| | | target_block = block |
| | | break |
| | |
| | | target_block = None |
| | | if blocks: |
| | | for block in blocks: |
| | | if block in kpl_data_manager.INVALID_BLOCKS: |
| | | if block in constant.KPL_INVALID_BLOCKS: |
| | | continue |
| | | target_block = block |
| | | break |
| | |
| | | # 是否出现过高位板 |
| | | high_block_infos = [] |
| | | for block in blocks: |
| | | if block in kpl_data_manager.INVALID_BLOCKS: |
| | | if block in constant.KPL_INVALID_BLOCKS: |
| | | continue |
| | | if latest_datas: |
| | | has_high, high_code_info = __is_has_high_code(block, latest_datas) |
| | |
| | | re_limit_codes = set() |
| | | # 炸板: |
| | | # (代码,名称,涨幅,板块,实际流通) |
| | | for data in open_limit_up_datas: |
| | | blocks = set(data[3].split("、")) |
| | | if target_block not in blocks: |
| | | continue |
| | | code_ = data[0] |
| | | break_codes.add(code_) |
| | | if open_limit_up_datas: |
| | | for data in open_limit_up_datas: |
| | | blocks = set(data[3].split("、")) |
| | | if target_block not in blocks: |
| | | continue |
| | | code_ = data[0] |
| | | break_codes.add(code_) |
| | | # 统计回封 |
| | | for data in latest_datas: |
| | | if data[5] != target_block: |
New file |
| | |
| | | """ |
| | | 代码行业关键词管理 |
| | | """ |
| | | |
| | | # 涨停代码关键词板块管理 |
| | | import json |
| | | |
| | | import constant |
| | | import global_data_loader |
| | | import global_util |
| | | import log |
| | | import tool |
| | | from db import redis_manager |
| | | |
| | | from log import logger_kpl_limit_up |
| | | from trade import trade_manager |
| | | |
| | | |
| | | # 实时开盘啦市场数据 |
| | | class RealTimeKplMarketData: |
| | | # 精选前5 |
| | | top_5_reason_set = set() |
| | | # 行业前5 |
| | | top_5_industry_set = set() |
| | | |
| | | @classmethod |
| | | def set_top_5_reasons(cls, datas): |
| | | temp_set = set() |
| | | base_count = 5 |
| | | for i in range(0, len(datas)): |
| | | if datas[i][1] in constant.KPL_INVALID_BLOCKS: |
| | | base_count += 1 |
| | | if i >= base_count: |
| | | break |
| | | if datas[i][3] > 5000 * 10000: |
| | | temp_set.add(datas[i][1]) |
| | | cls.top_5_reason_set = temp_set |
| | | |
| | | @classmethod |
| | | def set_top_5_industry(cls, datas): |
| | | temp_set = set() |
| | | base_count = 5 |
| | | for i in range(0, len(datas)): |
| | | if datas[i][1] in constant.KPL_INVALID_BLOCKS: |
| | | base_count += 1 |
| | | if i >= base_count: |
| | | break |
| | | |
| | | if datas[i][2] > 5000 * 10000: |
| | | temp_set.add(datas[i][1]) |
| | | cls.top_5_reason_set = temp_set |
| | | |
| | | # 获取能够买的行业关键字set |
| | | @classmethod |
| | | def get_can_buy_key_set(cls): |
| | | temp_set = cls.top_5_reason_set | cls.top_5_industry_set |
| | | return temp_set |
| | | |
| | | @classmethod |
| | | def is_in_top(cls, keys): |
| | | reasons = cls.get_can_buy_key_set() |
| | | temp_set = keys & reasons |
| | | if temp_set: |
| | | return True, temp_set |
| | | else: |
| | | return False, None |
| | | |
| | | |
| | | class LimitUpCodesPlateKeyManager: |
| | | # 今日涨停原因 |
| | | today_limit_up_reason_dict = {} |
| | | today_total_limit_up_reason_dict = {} |
| | | total_code_keys_dict = {} |
| | | total_key_codes_dict = {} |
| | | __redisManager = redis_manager.RedisManager(1) |
| | | |
| | | def __get_redis(self): |
| | | return self.__redisManager.getRedis() |
| | | |
| | | # 获取今日涨停数据,格式:[(代码,涨停原因)] |
| | | def set_today_limit_up(self, datas): |
| | | temp_dict = {} |
| | | if datas: |
| | | for item in datas: |
| | | temp_dict[item[0]] = item[1] |
| | | self.today_limit_up_reason_dict = temp_dict |
| | | if datas: |
| | | for item in datas: |
| | | self.__set_total_keys(item[0]) |
| | | self.set_today_total_limit_up(datas) |
| | | |
| | | # 设置今日历史涨停数据 |
| | | def set_today_total_limit_up(self, datas): |
| | | for item in datas: |
| | | code = item[0] |
| | | self.today_total_limit_up_reason_dict[code] = item[1] |
| | | |
| | | # 今日涨停原因变化 |
| | | def set_today_limit_up_reason_change(self, code, from_reason, to_reason): |
| | | self.__get_redis().sadd(f"kpl_limit_up_reason_his-{code}", from_reason) |
| | | self.__get_redis().expire(f"kpl_limit_up_reason_his-{code}", tool.get_expire()) |
| | | self.__set_total_keys(code) |
| | | |
| | | def __set_total_keys(self, code): |
| | | keys = set() |
| | | keys_his = self.__get_redis().smembers(f"kpl_limit_up_reason_his-{code}") |
| | | keys |= keys_his |
| | | if code in self.today_limit_up_reason_dict: |
| | | keys.add(self.today_limit_up_reason_dict.get(code)) |
| | | self.total_code_keys_dict[code] = keys |
| | | for k in keys: |
| | | if k not in self.total_key_codes_dict: |
| | | self.total_key_codes_dict[k] = set() |
| | | self.total_key_codes_dict[k].add(code) |
| | | |
| | | logger_kpl_limit_up.info("{}板块关键词:{}", code, keys) |
| | | |
| | | def get_codes_by_key_without_mine(self, key, code): |
| | | # 只比较今日涨停原因 |
| | | codes_set = set() |
| | | if key in self.total_key_codes_dict: |
| | | codes_set |= self.total_key_codes_dict[key] |
| | | codes_set.discard(code) |
| | | return codes_set |
| | | |
| | | |
| | | # 目标代码关键词管理 |
| | | class TargetCodePlateKeyManager: |
| | | __redisManager = redis_manager.RedisManager(1) |
| | | # 历史涨停原因 |
| | | __history_limit_up_reason_dict = {} |
| | | # 二级行业 |
| | | __second_industry_dict = {} |
| | | # 板块 |
| | | __blocks_dict = {} |
| | | |
| | | def __get_redis(self): |
| | | return self.__redisManager.getRedis() |
| | | |
| | | def set_history_limit_up_reason(self, code, reasons): |
| | | self.__history_limit_up_reason_dict[code] = set(reasons) |
| | | self.__get_redis().setex(f"kpl_his_limit_up_reason-{code}", tool.get_expire(), json.dumps(list(reasons))) |
| | | |
| | | # 如果返回值不为None表示已经加载过历史原因了 |
| | | def get_history_limit_up_reason(self, code): |
| | | reasons = self.__history_limit_up_reason_dict.get(code) |
| | | if reasons is None: |
| | | # 从内存中加载 |
| | | val = self.__get_redis().get(f"kpl_his_limit_up_reason-{code}") |
| | | if val is not None: |
| | | val = set(json.loads(val)) |
| | | self.__history_limit_up_reason_dict[code] = val |
| | | return self.__history_limit_up_reason_dict.get(code) |
| | | else: |
| | | return reasons |
| | | |
| | | def set_blocks(self, code, blocks): |
| | | self.__blocks_dict[code] = set(blocks) |
| | | self.__get_redis().setex(f"kpl_blocks-{code}", tool.get_expire(), json.dumps(list(blocks))) |
| | | |
| | | def get_blocks(self, code): |
| | | reasons = self.__blocks_dict.get(code) |
| | | if reasons is None: |
| | | # 从内存中加载 |
| | | val = self.__get_redis().get(f"kpl_blocks-{code}") |
| | | if val is not None: |
| | | val = set(json.loads(val)) |
| | | self.__blocks_dict[code] = val |
| | | return self.__blocks_dict.get(code) |
| | | else: |
| | | return reasons |
| | | |
| | | # 返回key集合(排除无效板块),今日涨停原因,今日历史涨停原因,历史涨停原因,二级,板块 |
| | | def get_plate_keys(self, code): |
| | | keys = set() |
| | | k1 = set() |
| | | if code in LimitUpCodesPlateKeyManager.today_total_limit_up_reason_dict: |
| | | k1 = {LimitUpCodesPlateKeyManager.today_total_limit_up_reason_dict[code]} |
| | | # 加载历史原因 |
| | | k11 = self.__get_redis().smembers(f"kpl_limit_up_reason_his-{code}") |
| | | k2 = set() |
| | | if code in self.__history_limit_up_reason_dict: |
| | | k2 = self.__history_limit_up_reason_dict[code] |
| | | k3 = set() |
| | | industry = global_util.code_industry_map.get(code) |
| | | if industry: |
| | | k3 = {industry} |
| | | |
| | | k4 = set() |
| | | if code in self.__blocks_dict: |
| | | k4 = self.__blocks_dict[code] |
| | | for k in [k1, k11, k2, k3, k4]: |
| | | keys |= k |
| | | |
| | | # 排除无效的涨停原因 |
| | | keys = keys - set(constant.KPL_INVALID_BLOCKS) |
| | | |
| | | return keys, k1, k11, k2, k3, k4 |
| | | |
| | | |
| | | class CodePlateKeyBuyManager: |
| | | __TargetCodePlateKeyManager = TargetCodePlateKeyManager() |
| | | __LimitUpCodesPlateKeyManager = LimitUpCodesPlateKeyManager() |
| | | |
| | | # 是否可以下单 |
| | | @classmethod |
| | | def can_buy(cls, code): |
| | | keys, k1, k11, k2, k3, k4 = cls.__TargetCodePlateKeyManager.get_plate_keys(code) |
| | | # 板块Key是否在市场前5key中 |
| | | is_in, valid_keys = RealTimeKplMarketData.is_in_top(keys) |
| | | if not valid_keys: |
| | | return False, "板块未在市场流入前5" |
| | | # 相同板块中是否已经有别的票涨停 |
| | | is_back = False, '' |
| | | for key in valid_keys: |
| | | codes = cls.__LimitUpCodesPlateKeyManager.get_codes_by_key_without_mine(key, code) |
| | | if codes and len(codes) > 0: |
| | | is_back = True, key |
| | | break |
| | | if not is_back[0]: |
| | | return False, f"板块中首个涨停:{valid_keys}" |
| | | # 看板块中是否已经有已经下单的或者成交的代码 |
| | | codes = trade_manager.get_codes_by_trade_states( |
| | | {trade_manager.TRADE_STATE_BUY_DELEGATED, trade_manager.TRADE_STATE_BUY_PLACE_ORDER, |
| | | trade_manager.TRADE_STATE_BUY_SUCCESS}) |
| | | # 遍历已经成交/下单的代码,获取其涨停原因,然后和当前代码涨停原因做比较,有相同代码的不能买 |
| | | for c in codes: |
| | | keys_, k1_, k11_, k2_, k3_, k4_ = cls.__TargetCodePlateKeyManager.get_plate_keys(c) |
| | | # 实时涨停原因 |
| | | for k_ in k1_: |
| | | # 当前代码已经有挂的或者成交的 |
| | | if k_ in valid_keys: |
| | | return False, f"{k_}板块中的{c}已经下单/买入成功,同一板块中只能买1个票" |
| | | return True, f"涨停原因:{is_back[1]}" |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | datas = log.load_kpl_reason_changes() |
| | | for k in datas: |
| | | LimitUpCodesPlateKeyManager().set_today_limit_up_reason_change(k[0], k[1], k[2]) |
| | |
| | | import time |
| | | from http.server import BaseHTTPRequestHandler |
| | | import cv2 |
| | | import dask |
| | | |
| | | import global_util |
| | | import gpcode_manager |
| | | import log |
| | | import tool |
| | | from l2 import code_price_manager |
| | | from third_data import kpl_util, kpl_data_manager |
| | | from third_data.kpl_data_manager import KPLDataManager |
| | | from output.limit_up_data_filter import IgnoreCodeManager |
| | | from third_data import kpl_util, kpl_data_manager, kpl_api |
| | | from third_data.code_plate_key_manager import RealTimeKplMarketData |
| | | from third_data.kpl_data_manager import KPLDataManager, KPLLimitUpDataRecordManager, KPLPlatManager, \ |
| | | KPLCodeLimitUpReasonManager |
| | | from third_data.kpl_util import KPLDataType |
| | | import urllib.parse as urlparse |
| | | from urllib.parse import parse_qs |
| | | from output import code_info_output, limit_up_data_filter, output_util |
| | | |
| | | from trade import bidding_money_manager |
| | | from trade import bidding_money_manager, trade_manager |
| | | from trade.l2_trade_util import BlackListCodeManager |
| | | |
| | | |
| | | class DataServer(BaseHTTPRequestHandler): |
| | | ocr_temp_data = {} |
| | | __kplDataManager = KPLDataManager() |
| | | __IgnoreCodeManager = IgnoreCodeManager() |
| | | __KPLPlatManager = KPLPlatManager() |
| | | __KPLCodeLimitUpReasonManager = KPLCodeLimitUpReasonManager() |
| | | # 历史板块 |
| | | __history_plates_dict = {} |
| | | # 板块 |
| | | __blocks_dict = {} |
| | | |
| | | def __get_limit_up_list(self): |
| | | # 统计目前为止的代码涨停数量(分涨停原因) |
| | | now_limit_up_codes_info = self.__kplDataManager.get_data(KPLDataType.LIMIT_UP) |
| | | limit_up_reason_dict = {} |
| | | for d in now_limit_up_codes_info: |
| | | if d[5] not in limit_up_reason_dict: |
| | | limit_up_reason_dict[d[5]] = [0, 0] |
| | | limit_up_reason_dict[d[5]][0] += 1 |
| | | # 获取想买原因想买单的代码数量 |
| | | reason_map = self.__KPLCodeLimitUpReasonManager.list_all() |
| | | want_codes = gpcode_manager.WantBuyCodesManager.list_code() |
| | | # 其他想买单 |
| | | other_count = 0 |
| | | for k in reason_map: |
| | | reson = reason_map[k] |
| | | if k in want_codes and reson in limit_up_reason_dict: |
| | | limit_up_reason_dict[reson][1] += 1 |
| | | elif k in want_codes: |
| | | other_count += 1 |
| | | |
| | | limit_up_reason_statistic_info = [(k, limit_up_reason_dict[k][0], limit_up_reason_dict[k][1]) for k in |
| | | limit_up_reason_dict] |
| | | limit_up_reason_statistic_info.sort(key=lambda x: x[1]) |
| | | limit_up_reason_statistic_info.reverse() |
| | | if other_count > 0: |
| | | limit_up_reason_statistic_info.insert(0, ('其他', other_count, other_count)) |
| | | |
| | | total_datas = KPLLimitUpDataRecordManager.total_datas |
| | | if not total_datas: |
| | | KPLLimitUpDataRecordManager.load_total_datas() |
| | | total_datas = KPLLimitUpDataRecordManager.total_datas |
| | | # 通过涨停时间排序 |
| | | total_datas = list(total_datas) |
| | | |
| | | codes_set = set([d[3] for d in total_datas]) |
| | | # 判断是龙几,判断是否涨停,判断是否炸板,加载分数 |
| | | rank_dict = limit_up_data_filter.get_limit_up_time_rank_dict(total_datas) |
| | | limit_up_dict, limit_up_codes, open_limit_up_codes = limit_up_data_filter.get_limit_up_info(codes_set) |
| | | score_dict = limit_up_data_filter.get_codes_scores_dict(codes_set) |
| | | fresult = [] |
| | | ignore_codes = self.__IgnoreCodeManager.list_ignore_codes("1") |
| | | |
| | | total_datas.sort(key=lambda x: int(x[5])) |
| | | total_datas.reverse() |
| | | |
| | | # 获取涨停原因变化记录 |
| | | reason_changes = log.load_kpl_reason_changes() |
| | | reason_changes.reverse() |
| | | reason_changes_dict = {} |
| | | for r in reason_changes: |
| | | if r[0] not in reason_changes_dict: |
| | | reason_changes_dict[r[0]] = r[1] |
| | | |
| | | for d in total_datas: |
| | | code = d[3] |
| | | # (代码, 名称, 涨停状态(0 - 无状态 1-涨停 2-炸板), 龙几, 首板, 分值, 涨停时间, 原因, 相同原因代码数量, 自由流通, 涨停原因是否变化) |
| | | limit_up_state = 0 |
| | | if code in limit_up_dict: |
| | | if limit_up_dict[code][0]: |
| | | limit_up_state = 1 |
| | | elif limit_up_dict[code][1]: |
| | | limit_up_state = 2 |
| | | score = "" |
| | | if code in score_dict: |
| | | score = score_dict[code] |
| | | if code in ignore_codes: |
| | | continue |
| | | fresult.append((code, d[4], limit_up_state, f"龙{rank_dict.get(code)}", d[12], score, |
| | | output_util.time_format(int(d[5])), d[2], d[10], output_util.money_desc(d[13]), |
| | | reason_changes_dict.get(code))) |
| | | response_data = json.dumps({"code": 0, "data": {"limit_up_count": len(limit_up_codes), |
| | | "open_limit_up_count": len(open_limit_up_codes), |
| | | "limit_up_reason_statistic": limit_up_reason_statistic_info, |
| | | "limit_up_codes": fresult}}) |
| | | return response_data |
| | | |
| | | def __get_plate_info(self, ps_dict): |
| | | |
| | | @dask.delayed |
| | | def kpl_getStockIDPlate(code_): |
| | | temp_data = kpl_api.getStockIDPlate(code_) |
| | | return temp_data |
| | | |
| | | @dask.delayed |
| | | def kpl_getSonPlate(plate_code_): |
| | | if not plate_code: |
| | | return None |
| | | temp_data = kpl_api.getSonPlate(plate_code_) |
| | | return temp_data |
| | | |
| | | @dask.delayed |
| | | def kpl_getCodesByPlate(plate_code_): |
| | | if not plate_code: |
| | | return None |
| | | temp_data = kpl_api.getCodesByPlate(plate_code_) |
| | | return temp_data |
| | | |
| | | @dask.delayed |
| | | def request_data(f1_, f2_): |
| | | temp_data = f1_, f2_ |
| | | return temp_data |
| | | |
| | | # 获取板块的代码 |
| | | fresult = {} |
| | | code = ps_dict["code"] |
| | | code_info = KPLLimitUpDataRecordManager.list_by_code(code, tool.get_now_date_str())[0] |
| | | hot_block_name = code_info[2] |
| | | plate_code = self.__KPLPlatManager.get_plat(hot_block_name) |
| | | f1 = kpl_getStockIDPlate(code) |
| | | # f2 = kpl_getSonPlate(plate_code) |
| | | f3 = kpl_getCodesByPlate(plate_code) |
| | | dask_result = request_data(f1, f3) |
| | | plate_info, codes_by_plate_info = dask_result.compute() |
| | | |
| | | if plate_info: |
| | | plate_info.sort(key=lambda x: x[2]) |
| | | plate_info.reverse() |
| | | fresult["plate"] = plate_info |
| | | |
| | | # 获取代码的历史涨停数据,(涨停原因,日期,板块) |
| | | fresult["code_records"] = KPLLimitUpDataRecordManager.get_latest_infos(code, 4, False)[:2] |
| | | # 获取今日数据 |
| | | fresult["today"] = (code_info[2], code_info[1], code_info[6]) |
| | | fresult["industry"] = global_util.code_industry_map.get(code) |
| | | if plate_code: |
| | | # 获取强度 |
| | | # datas = son_plate_info |
| | | # # (代码,名称,强度) |
| | | # temp = kpl_util.parseSonPlat(datas) |
| | | # temp.sort(key=lambda x: x[2]) |
| | | # temp.reverse() |
| | | # fresult["plat_strength"] = temp |
| | | |
| | | # 获取涨停原因下面的列表 |
| | | datas = codes_by_plate_info |
| | | # (代码,名称,现价,涨幅,自由流通,几板,龙几,主力净额,300w净额,机构增仓) |
| | | temps = kpl_util.parsePlateCodes(datas) |
| | | # --数据准备开始-- |
| | | codes_set = set([d[0] for d in temps]) |
| | | limit_up_dict, limit_up_codes, open_limit_up_codes = limit_up_data_filter.get_limit_up_info(codes_set) |
| | | score_dict = limit_up_data_filter.get_codes_scores_dict(codes_set) |
| | | want_codes = gpcode_manager.WantBuyCodesManager.list_code() |
| | | black_codes = BlackListCodeManager.list_codes() |
| | | total_datas = KPLLimitUpDataRecordManager.total_datas |
| | | code_info_dict = {} |
| | | for val in total_datas: |
| | | code_info_dict[val[3]] = val |
| | | |
| | | # --数据准备结束-- |
| | | |
| | | ignore_codes = self.__IgnoreCodeManager.list_ignore_codes("2") |
| | | # 最终结果:(代码,名称,涨停状态(0-无状态 1-涨停 2-炸板),龙几,首板,分值,涨停时间,原因,相同原因代码数量,自由流通,涨停原因是否变化,涨幅,现价,黑名单,想买单,主力净值,300w,) |
| | | codes_info_list = [] |
| | | for t in temps: |
| | | code = t[0] |
| | | limit_up_state = 0 |
| | | if code in limit_up_dict: |
| | | if limit_up_dict[code][0]: |
| | | limit_up_state = 1 |
| | | elif limit_up_dict[code][1]: |
| | | limit_up_state = 2 |
| | | score = "" |
| | | if code in score_dict: |
| | | score = score_dict[code] |
| | | |
| | | limit_up_time = '' |
| | | if code in code_info_dict: |
| | | limit_up_time = output_util.time_format(code_info_dict[code][5]) |
| | | final_code_info = {"code_info": ( |
| | | t[0], t[1], limit_up_state, t[6], t[5], score, limit_up_time, |
| | | code_info[2], code_info[10], output_util.money_desc(t[4]), 0, t[3], t[2], |
| | | "黑名单" if code in black_codes else "", "想买单" if code in want_codes else "", |
| | | output_util.money_desc(t[7]), output_util.money_desc(t[8]), output_util.money_desc(t[9]))} |
| | | if code in code_info_dict: |
| | | final_code_info["today"] = ( |
| | | code_info_dict[code][2], code_info_dict[code][1], code_info_dict[code][6]) |
| | | # 加载历史 |
| | | if code in self.__history_plates_dict: |
| | | final_code_info["code_records"] = self.__history_plates_dict[code][1] |
| | | # 加载板块 |
| | | if code in self.__blocks_dict: |
| | | final_code_info["plate"] = self.__blocks_dict[code][1] |
| | | |
| | | # 获取二级行业 |
| | | final_code_info["industry"] = global_util.code_industry_map.get(code) |
| | | |
| | | if code not in ignore_codes: |
| | | codes_info_list.append(final_code_info) |
| | | fresult["code_list_info"] = codes_info_list |
| | | response_data = json.dumps({"code": 0, "data": fresult}) |
| | | return response_data |
| | | |
| | | def do_GET(self): |
| | | path = self.path |
| | |
| | | response_data = "" |
| | | if url.path == "/get_kpl_data": |
| | | best_feng_kou = self.__kplDataManager.get_data(kpl_util.KPLDataType.BEST_FENG_KOU) |
| | | best_feng_kou=best_feng_kou[:22] |
| | | best_feng_kou = best_feng_kou[:22] |
| | | feng_kou = self.__kplDataManager.get_data(kpl_util.KPLDataType.FENG_KOU) |
| | | feng_kou = feng_kou[:22] |
| | | industry_rank = self.__kplDataManager.get_data(kpl_util.KPLDataType.INDUSTRY_RANK) |
| | |
| | | feng_xiang = feng_xiang[:22] |
| | | response_data = json.dumps({"code": 0, "data": {"best_feng_kou": best_feng_kou, "feng_kou": feng_kou, |
| | | "industry_rank": industry_rank, "feng_xiang": feng_xiang}}) |
| | | elif url.path == "/get_score_info": |
| | | ps_dict = dict([(k, v[0]) for k, v in parse_qs(url.query).items()]) |
| | | code = ps_dict['code'] |
| | | name = ps_dict.get('name') |
| | | |
| | | data = code_info_output.get_output_params(code) |
| | | if data["code_name"].find("None") > -1 and name: |
| | | data["code_name"] = f"{name} {code}" |
| | | |
| | | self.__history_plates_dict[code] = (time.time(), data["kpl_code_info"]["code_records"]) |
| | | self.__blocks_dict[code] = (time.time(), data["kpl_code_info"]["plate"]) |
| | | |
| | | response_data = json.dumps({"code": 0, "data": data}) |
| | | # 获取评分信息 |
| | | pass |
| | | elif url.path == "/kpl/get_limit_up_list": |
| | | response_data = self.__get_limit_up_list() |
| | | |
| | | elif url.path == "/kpl/get_plate_info": |
| | | ps_dict = dict([(k, v[0]) for k, v in parse_qs(url.query).items()]) |
| | | response_data = self.__get_plate_info(ps_dict) |
| | | |
| | | elif url.path == "/kpl/get_market_data": |
| | | # 获取板块信息 |
| | | ps_dict = dict([(k, v[0]) for k, v in parse_qs(url.query).items()]) |
| | | type_ = int(ps_dict['type']) |
| | | result = [] |
| | | if type_ == 0: |
| | | # 行业,主力净额倒序 |
| | | result = kpl_api.getMarketIndustryRealRankingInfo(True) |
| | | result = kpl_util.parseMarketIndustry(result) |
| | | elif type_ == 1: |
| | | # 行业,主力净额顺序 |
| | | result = kpl_api.getMarketIndustryRealRankingInfo(False) |
| | | result = kpl_util.parseMarketIndustry(result) |
| | | elif type_ == 2: |
| | | # 精选,主力净额倒序 |
| | | result = kpl_api.getMarketJingXuanRealRankingInfo(True) |
| | | result = kpl_util.parseMarketJingXuan(result) |
| | | elif type_ == 3: |
| | | # 精选,主力净额顺序 |
| | | result = kpl_api.getMarketJingXuanRealRankingInfo(False) |
| | | result = kpl_util.parseMarketJingXuan(result) |
| | | |
| | | response_data = json.dumps({"code": 0, "data": result}) |
| | | elif url.path == "/kpl/add_ignore_code": |
| | | ps_dict = dict([(k, v[0]) for k, v in parse_qs(url.query).items()]) |
| | | code = ps_dict['code'] |
| | | type_ = ps_dict['type'] |
| | | self.__IgnoreCodeManager.ignore_code(type_, code) |
| | | response_data = json.dumps({"code": 0}) |
| | | |
| | | self.send_response(200) |
| | | # 发给请求客户端的响应数据 |
| | | self.send_header('Content-type', 'application/json') |
| | |
| | | type_ = data["type"] |
| | | print("开盘啦type:", type_) |
| | | if type_ == KPLDataType.BIDDING.value: |
| | | result_list = kpl_util.parseDaBanData(data["data"], kpl_util.DABAN_TYPE_LIMIT_UP) |
| | | result_list = kpl_util.parseDaBanData(data["data"], kpl_util.DABAN_TYPE_BIDDING) |
| | | # 竞价取前20 |
| | | if result_list: |
| | | result_list.sort(key=lambda x: x[2]) |
| | |
| | | self.__kplDataManager.save_data(type_, result_list) |
| | | elif type_ == KPLDataType.INDUSTRY_RANK.value: |
| | | result_list = kpl_util.parseIndustryRank(data["data"]) |
| | | # 保存风向数据 |
| | | # 保存行业数据 |
| | | if result_list: |
| | | self.__kplDataManager.save_data(type_, result_list) |
| | | RealTimeKplMarketData.set_top_5_industry(result_list) |
| | | elif type_ == KPLDataType.JINGXUAN_RANK.value: |
| | | result_list = kpl_util.parseMarketJingXuan(data["data"]) |
| | | # 保存精选数据 |
| | | if result_list: |
| | | self.__kplDataManager.save_data(type_, result_list) |
| | | RealTimeKplMarketData.set_top_5_reasons(result_list) |
| | | return json.dumps({"code": 0}) |
| | | |
| | | def __send_response(self, data): |
| | |
| | | if int(result["errcode"]) != 0: |
| | | return None |
| | | return result["ListJX"] |
| | | |
| | | # 获取概念代码 |
| | | def getCodesByPlate(plate_code): |
| | | data = f"Order=1&a=ZhiShuStockList_W8&st=30&c=ZhiShuRanking&PhoneOSNew=1&old=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&IsZZ=0&Token=0&Index=0&apiv=w32&Type=6&IsKZZType=0&UserID=0&PlateID={plate_code}&" |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", |
| | | data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | |
| | | # 获取概念中的板块强度 |
| | | def getSonPlate(plate_code): |
| | | data = f"a=SonPlate_Info&apiv=w32&c=ZhiShuRanking&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&PlateID={plate_code}&" |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | |
| | | # 市场行情-行业 |
| | | def getMarketIndustryRealRankingInfo(orderJingE_DESC=True): |
| | | data = f"Order={ 1 if orderJingE_DESC else 0}&a=RealRankingInfo&st=80&apiv=w32&Type=5&c=ZhiShuRanking&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Index=0&ZSType=4&" |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", |
| | | data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | |
| | | # 市场行情-精选 |
| | | def getMarketJingXuanRealRankingInfo(orderJingE_DESC=True): |
| | | data = f"Order={ 1 if orderJingE_DESC else 0}&a=RealRankingInfo&st=80&apiv=w32&Type=5&c=ZhiShuRanking&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Index=0&ZSType=7&" |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", |
| | | data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | |
| | | import tool |
| | | |
| | | # 开盘啦历史涨停数据管理 |
| | | from db import mysql_data |
| | | from db import mysql_data, redis_manager |
| | | from l2 import code_price_manager |
| | | from log import logger_kpl_limit_up_reason_change |
| | | from third_data import kpl_util |
| | | from third_data.code_plate_key_manager import LimitUpCodesPlateKeyManager |
| | | |
| | | INVALID_BLOCKS = ["一季报增长", "二季报增长", "三季报增长", "四季报增长", "业绩增长", "中报增长", "年报增长", "年报预增", "无", "次新股", "ST摘帽", "超跌", "股权转让", |
| | | "并购重组"] |
| | | |
| | | # 代码对应的涨停原因保存 |
| | | class KPLCodeLimitUpReasonManager: |
| | | __redisManager = redis_manager.RedisManager(3) |
| | | |
| | | def __get_redis(self): |
| | | return self.__redisManager.getRedis() |
| | | |
| | | def save_reason(self, code, reason): |
| | | self.__get_redis().setex(f"kpl_limitup_reason-{code}", tool.get_expire(), reason) |
| | | |
| | | def list_all(self): |
| | | keys = self.__get_redis().keys("kpl_limitup_reason-*") |
| | | dict_ = {} |
| | | for k in keys: |
| | | val = self.__get_redis().get(k) |
| | | dict_[k.split("-")[1]] = val |
| | | return dict_ |
| | | |
| | | |
| | | class KPLPlatManager: |
| | | def save_plat(self, _id, name): |
| | | if not _id: |
| | | return |
| | | mysqldb = mysql_data.Mysqldb() |
| | | key = f"{_id}-{name}" |
| | | results = mysqldb.select_one(f"select * from kpl_plate where _name='{name}'") |
| | | if not results: |
| | | mysqldb.execute(f"insert into kpl_plate(_id,_name,_key) values({_id},'{name}','{key}')") |
| | | |
| | | def get_plat(self, name): |
| | | mysqldb = mysql_data.Mysqldb() |
| | | results = mysqldb.select_one(f"select * from kpl_plate where _name='{name}'") |
| | | if results: |
| | | return results[0] |
| | | return None |
| | | |
| | | def get_same_plat_names(self, name): |
| | | mysqldb = mysql_data.Mysqldb() |
| | | plate = self.get_plat(name) |
| | | if not plate: |
| | | return {name} |
| | | results = mysqldb.select_all(f"select _name from kpl_plate where _id='{plate}'") |
| | | return set([r[0] for r in results]) |
| | | |
| | | |
| | | class KPLLimitUpDataRecordManager: |
| | | total_datas = None |
| | | latest_datas = {} |
| | | __kplPlatManager = KPLPlatManager() |
| | | __LimitUpCodesPlateKeyManager = LimitUpCodesPlateKeyManager() |
| | | |
| | | @classmethod |
| | | def save_record(cls, day, records): |
| | |
| | | if not code_block_dict.get(code): |
| | | code_block_dict[code] = set() |
| | | code_block_dict[code].add(b) |
| | | # 设置涨停数据 |
| | | if records: |
| | | cls.__LimitUpCodesPlateKeyManager.set_today_limit_up([(r[0], r[5]) for r in records]) |
| | | |
| | | # 涨停数据记录 |
| | | mysqldb = mysql_data.Mysqldb() |
| | | # 统计涨停原因和概念代码 |
| | | plats = {} |
| | | for d in records: |
| | | # (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额) |
| | | plats[d[5]] = d[9] |
| | | for p in plats: |
| | | cls.__kplPlatManager.save_plat(plats[p], p) |
| | | |
| | | for d in records: |
| | | # (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额,涨停原因代码,涨停原因代码数量) |
| | | code = d[0] |
| | | _id = f"{day}_{code}_{d[5]}" |
| | | |
| | | result = mysqldb.select_one("select * from kpl_limit_up_record where _id='{}'".format(_id)) |
| | | if not result: |
| | | mysqldb.execute( |
| | | f"insert into kpl_limit_up_record(_id,_day,_hot_block_name,_code,_code_name,_limit_up_time,_blocks,_latest_limit_up_time,_update_time,_create_time) values('{_id}','{day}','{d[5]}','{d[0]}','{d[1]}','{d[2]}','{d[6]}','{d[3]}',now(),now())") |
| | | f"insert into kpl_limit_up_record(_id,_day,_hot_block_name,_code,_code_name,_limit_up_time,_blocks,_latest_limit_up_time,_update_time,_create_time,_hot_block_code_count,_limit_up_high_info,_zylt_val) values('{_id}','{day}','{d[5]}','{d[0]}','{d[1]}','{d[2]}','{d[6]}','{d[3]}',now(),now(),{d[10]},'{d[4]}',{d[7]})") |
| | | |
| | | else: |
| | | if _id in cls.latest_datas and json.dumps(cls.latest_datas.get(_id)) != json.dumps(d): |
| | | mysqldb.execute( |
| | | f"update kpl_limit_up_record set _latest_limit_up_time='{d[3]}',_limit_up_time='{d[2]}' ,_update_time=now() where _id='{_id}'") |
| | | f"update kpl_limit_up_record set _latest_limit_up_time='{d[3]}',_limit_up_time='{d[2]}',_hot_block_code_count={d[10]},_limit_up_high_info='{d[4]}' ,_update_time=now() where _id='{_id}'") |
| | | cls.latest_datas[_id] = d |
| | | cls.latest_datas[_id] = d |
| | | |
| | |
| | | for dd in old_datas: |
| | | if dd[2] not in code_block_dict[code]: |
| | | mysqldb.execute(f"delete from kpl_limit_up_record where _id='{dd[0]}'") |
| | | logger_kpl_limit_up_reason_change.info(f"code-{dd[3]}:{dd[2]}-{code_block_dict[code]}") |
| | | # 板块更改过 |
| | | mysqldb.execute( |
| | | f"update kpl_limit_up_record set _hot_block_change = f'{dd[2]}' where _day='{dd[1]}' and _code='{code}'") |
| | | |
| | | cls.__LimitUpCodesPlateKeyManager.set_today_limit_up_reason_change(code, dd[2], |
| | | code_block_dict[code]) |
| | | |
| | | if dd[0] in cls.latest_datas: |
| | | cls.latest_datas.pop(dd[0]) |
| | | cls.total_datas = KPLLimitUpDataRecordManager.list_all(tool.get_now_date_str()) |
| | |
| | | @classmethod |
| | | def load_total_datas(cls): |
| | | cls.total_datas = KPLLimitUpDataRecordManager.list_all(tool.get_now_date_str()) |
| | | cls.__LimitUpCodesPlateKeyManager.set_today_total_limit_up([(r[3], r[2]) for r in cls.total_datas]) |
| | | |
| | | @staticmethod |
| | | def list_all(day): |
| | |
| | | @staticmethod |
| | | def get_latest_blocks(code): |
| | | wheres = [] |
| | | for b in INVALID_BLOCKS: |
| | | for b in constant.KPL_INVALID_BLOCKS: |
| | | wheres.append(f"hb.`_hot_block_name` != '{b}'") |
| | | wheres = " and ".join(wheres) |
| | | sql = f"SELECT GROUP_CONCAT(_hot_block_name) FROM (SELECT hb.`_hot_block_name`,hb.`_day` FROM `kpl_limit_up_record` hb WHERE hb.`_code`='{code}' AND {wheres} ORDER BY hb.`_day` DESC LIMIT 10) a GROUP BY a._day ORDER BY a._day DESC LIMIT 1" |
| | |
| | | return mysqldb.select_one(sql) |
| | | |
| | | # 获取代码最近的板块,返回[(板块,日期)] |
| | | @staticmethod |
| | | def get_latest_infos(code, count): |
| | | sql = f"SELECT GROUP_CONCAT(_hot_block_name),`_day` FROM (SELECT hb.`_hot_block_name`,hb.`_day` FROM `kpl_limit_up_record` hb WHERE hb.`_code`='{code}' ORDER BY hb.`_day` DESC LIMIT 10) a GROUP BY a._day ORDER BY a._day DESC LIMIT {count}" |
| | | @classmethod |
| | | def get_latest_infos(cls, code, count, contains_today=True): |
| | | # 只获取最近180天的数据 |
| | | min_day = tool.date_sub(tool.get_now_date_str(), 180) |
| | | sql = f"SELECT GROUP_CONCAT(_hot_block_name),`_day`,_blocks FROM (SELECT hb.`_hot_block_name`,hb.`_day`,hb._blocks FROM `kpl_limit_up_record` hb WHERE hb.`_code`='{code}' and hb.`_day` > '{min_day}' ORDER BY hb.`_day` DESC LIMIT 10) a GROUP BY a._day ORDER BY a._day DESC LIMIT {count}" |
| | | mysqldb = mysql_data.Mysqldb() |
| | | return mysqldb.select_all(sql) |
| | | results = mysqldb.select_all(sql) |
| | | if results and not contains_today and results[0][1] == tool.get_now_date_str(): |
| | | return results[1:] |
| | | return results |
| | | |
| | | @classmethod |
| | | def get_latest_blocks_set(cls, code): |
| | | results = cls.get_latest_infos(code, 10, False) |
| | | bs = set([b[0] for b in results]) |
| | | return bs |
| | | |
| | | |
| | | class KPLDataManager: |
| | |
| | | line = lines[0] |
| | | result = json.loads(line) |
| | | list_ = kpl_util.parseDaBanData(result, kpl_util.DABAN_TYPE_LIMIT_UP) |
| | | KPLLimitUpDataRecordManager.save_record(day, list_) |
| | | # KPLLimitUpDataRecordManager.save_record(day, list_) |
| | | for r in list_: |
| | | print(r[-1], r[5]) |
| | | KPLPlatManager().save_plat(r[-1], r[5]) |
| | | |
| | | print(day, list_) |
| | | # print(day, list_) |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | print(KPLLimitUpDataRecordManager.get_latest_infos("000950", 4)) |
| | | ds = set(["1", "2", "3"]) |
| | | print(ds.pop()) |
| | |
| | | |
| | | |
| | | # 涨停代码: |
| | | # (代码,名称,首次涨停时间,最近涨停时间,几板,涨停原因,板块,实际流通,主力净额) |
| | | # (代码,名称,首次涨停时间,最近涨停时间,几板,涨停原因,板块,实际流通,主力净额,涨停原因代码,涨停原因代码数量) |
| | | # (0,1,6,25,9,16,11,15,12) |
| | | # 竞价代码: |
| | | # (代码,名称,涨停委买额,板块,竞价成交额,实际流通) |
| | |
| | | BEST_FENG_KOU = "best_feng_kou" |
| | | FENG_XIANG = "feng_xiang" |
| | | INDUSTRY_RANK = "industry_rank" |
| | | JINGXUAN_RANK = "jingxuan_rank" |
| | | |
| | | |
| | | def __parseDaBanItemData(data, type): |
| | | if type == DABAN_TYPE_BIDDING: |
| | | return data[0], data[1], data[18], data[11], data[22], data[15] |
| | | elif type == DABAN_TYPE_LIMIT_UP: |
| | | return data[0], data[1], data[6], data[25], data[9], data[16], data[11], data[15], data[12] |
| | | return data[0], data[1], data[6], data[25], data[9], data[16], data[11], data[15], data[12], data[26], data[27] |
| | | elif type == DABAN_TYPE_OPEN_LIMIT_UP: |
| | | return data[0], data[1], data[4], data[11], data[15] |
| | | elif type == DABAN_TYPE_LIMIT_DOWN: |
| | |
| | | pdata = __parseIndustry_rank(d) |
| | | if pdata: |
| | | fresult_.append(pdata) |
| | | return fresult_ |
| | | return fresult_ |
| | | |
| | | |
| | | # 解析板块代码 |
| | | def parsePlateCodes(data): |
| | | if type(data) == str: |
| | | data = json.loads(data) |
| | | if int(data["errcode"]) != 0: |
| | | raise Exception(f"解析数据出错,errcode:{data['errcode']}") |
| | | list_ = data["list"] |
| | | fresult_ = [] |
| | | for d in list_: |
| | | # (代码,名称,现价,涨幅,自由流通,几板,龙几,主力净额,300w净额,机构增仓) |
| | | fresult_.append((d[0], d[1], d[5], d[6], d[10], d[23], d[24], d[13], d[50], d[42])) |
| | | return fresult_ |
| | | |
| | | |
| | | # 解析概念中的板块强度 |
| | | def parseSonPlat(data): |
| | | if type(data) == str: |
| | | data = json.loads(data) |
| | | if int(data["errcode"]) != 0: |
| | | raise Exception(f"解析数据出错,errcode:{data['errcode']}") |
| | | list_ = data["List"] |
| | | fresult_ = [] |
| | | for d in list_: |
| | | # (代码,名称,强度) |
| | | fresult_.append((d[0], d[1], d[2])) |
| | | return fresult_ |
| | | |
| | | |
| | | def __money_desc(money): |
| | | if abs(money) > 100000000: |
| | | return f"{round(money / 100000000, 2)}亿" |
| | | else: |
| | | return f"{round(money / 10000, 2)}万" |
| | | |
| | | |
| | | def parseMarketIndustry(data): |
| | | if type(data) == str: |
| | | data = json.loads(data) |
| | | if int(data["errcode"]) != 0: |
| | | raise Exception(f"解析数据出错,errcode:{data['errcode']}") |
| | | list_ = data["list"] |
| | | fresult_ = [] |
| | | for d in list_: |
| | | # (代码,名称,涨幅,主力净额) |
| | | fresult_.append((d[0], d[1], d[3], d[6])) |
| | | return fresult_ |
| | | |
| | | |
| | | def parseMarketJingXuan(data): |
| | | if type(data) == str: |
| | | data = json.loads(data) |
| | | if int(data["errcode"]) != 0: |
| | | raise Exception(f"解析数据出错,errcode:{data['errcode']}") |
| | | list_ = data["list"] |
| | | fresult_ = [] |
| | | for d in list_: |
| | | # (代码,名称,强度,主力净额) |
| | | fresult_.append((d[0], d[1], d[2], d[6])) |
| | | return fresult_ |
| | |
| | | __code_map = {} |
| | | __industry_map = {} |
| | | mysqldb = mysql_data.Mysqldb() |
| | | results = mysqldb.select_all("select * from ths_industry_codes") |
| | | results = mysqldb.select_all("select _id,second_industry from ths_industry_codes") |
| | | for r in results: |
| | | code = r[0] |
| | | industry = r[1] |
| | |
| | | return date |
| | | |
| | | |
| | | # 日期减去多少天 |
| | | def date_sub(date_str, day, format="%Y-%m-%d"): |
| | | t_ = time.mktime(time.strptime(date_str, format)) |
| | | t_ -= day * 24 * 60 * 60 |
| | | return time.strftime(format, t.localtime(t_)) |
| | | |
| | | |
| | | def get_now_time_str(): |
| | | time_str = datetime.datetime.now().strftime("%H:%M:%S") |
| | | return time_str |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | print(trade_time_sub("13:18:00", "09:00:00")//60) |
| | | print(trade_time_sub("09:00:00","13:18:00") // 60) |
| | | print(trade_time_sub("13:18:00", "09:00:00") // 60) |
| | | print(trade_time_sub("09:00:00", "13:18:00") // 60) |
| | | print(trade_time_sub("09:00:00", "09:30:00") // 60) |
| | | print(trade_time_sub("09:30:00", "09:00:00") // 60) |
| | | print(date_sub("2023-05-12",180)) |
| | | # print(trade_time_sub("11:29:59", 5)) |
| | | # print(trade_time_sub("10:29:59", 10)) |
| | | # print(trade_time_add_second("13:29:59", 60)) |
| | |
| | | |
| | | @classmethod |
| | | def add_code(cls, code): |
| | | cls.__get_redis().sadd(cls.__key,code) |
| | | cls.__get_redis().sadd(cls.__key, code) |
| | | |
| | | @classmethod |
| | | def remove_code(cls, code): |
| | |
| | | @classmethod |
| | | def clear(cls): |
| | | cls.__get_redis().delete(cls.__key) |
| | | |
| | | |
| | | |
| | | # 获取交易状态 |
| | |
| | | if keys is not None: |
| | | for key in keys: |
| | | if int(redis.get(key)) == state: |
| | | codes.append(key.replace("trade-state-", '')) |
| | | return codes |
| | | |
| | | |
| | | def get_codes_by_trade_states(states): |
| | | redis = __redis_manager.getRedis() |
| | | keys = redis.keys("trade-state-*") |
| | | codes = [] |
| | | if keys is not None: |
| | | for key in keys: |
| | | if int(redis.get(key)) in states: |
| | | codes.append(key.replace("trade-state-", '')) |
| | | return codes |
| | | |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | set_trade_state("002351",TRADE_STATE_BUY_DELEGATED) |
| | | set_trade_state("002351", TRADE_STATE_BUY_DELEGATED) |
New file |
| | |
| | | from tkinter import * |
| | | |
| | | |
| | | class FlatButton(Button): |
| | | pixelVirtual = None |
| | | |
| | | def __init__(self, master=None, **kw): |
| | | if self.pixelVirtual is None: |
| | | self.pixelVirtual = PhotoImage(width=1, height=1) |
| | | kw['relief'] = FLAT |
| | | kw["image"] = self.pixelVirtual, |
| | | kw["compound"] = "c" |
| | | if "height" not in kw: |
| | | kw["height"] = 20 |
| | | super(FlatButton, self).__init__(master, kw) |