New file |
| | |
| | | """ |
| | | 可转债分析 |
| | | """ |
| | | from convertible_bonds import main |
| | | |
| | | if __name__ == '__main__': |
| | | main.run() |
New file |
| | |
| | | import logging |
| | | import queue |
| | | import time |
| | | |
| | | import wx |
| | | import matplotlib.pyplot as plt |
| | | from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas |
| | | from matplotlib.figure import Figure |
| | | |
| | | import juejin_core |
| | | from juejin_core import JueJinApi |
| | | from utils import tool |
| | | |
| | | APP_TITLE = "可转债分析" |
| | | |
| | | |
| | | class JueJinUtil: |
| | | @classmethod |
| | | def get_all_convertible_bonds_codes(cls): |
| | | """ |
| | | 获取所有的可转债代码 |
| | | :return: 所有代码合集[((可转债代码,可转债名称),股票代码)] |
| | | """ |
| | | results = JueJinApi.get_codes(8) |
| | | count = 0 |
| | | |
| | | symbols = [] |
| | | for result in results: |
| | | if int(tool.get_now_date_str("%Y%m%d")) < int(result['delisted_date'].strftime("%Y%m%d")): |
| | | count += 1 |
| | | symbols.append(((result['symbol'], result['sec_name']), result['underlying_symbol'])) |
| | | return symbols |
| | | |
| | | |
| | | # 绘图管理器 |
| | | class DrawManager: |
| | | X_RANGE_MINIUTES = 335 |
| | | X_DATA_MINIUTES = 335 |
| | | |
| | | h_lines_dict = {} |
| | | cost_mark_dict = {} |
| | | last_max_rate_dict = {} |
| | | cost_rate_dict = {} |
| | | sell_points_dict = {} |
| | | |
| | | @classmethod |
| | | def get_x_time_as_seconds(cls, created_at_str): |
| | | time_ = created_at_str[-8:] |
| | | if tool.get_time_as_second("13:00:00") > tool.get_time_as_second(time_) > tool.get_time_as_second( |
| | | "11:30:00"): |
| | | time_ = "11:30:00" |
| | | time_s = int(time_.split(":")[0]) * 3600 + int(time_.split(":")[1]) * 60 + int( |
| | | time_.split(":")[2]) - 9 * 3600 - 60 * 30 |
| | | |
| | | if int(time_.replace(":", "")) > int("11:30:00".replace(":", "")): |
| | | time_s -= 90 * 60 |
| | | return time_s |
| | | |
| | | @classmethod |
| | | def set_cost_rate(cls, code, rate): |
| | | cls.cost_rate_dict[code] = rate |
| | | |
| | | @classmethod |
| | | def __format_max_rate(cls, max_rate): |
| | | PERCENT_RATE = 1 |
| | | line_count = 0 |
| | | if max_rate % PERCENT_RATE < 0.0001: |
| | | line_count = int(round(max_rate // PERCENT_RATE)) |
| | | else: |
| | | line_count = int(round(max_rate // PERCENT_RATE)) + 1 |
| | | rate = line_count * PERCENT_RATE |
| | | # 还未接近涨停多增加PERCENT_RATE |
| | | if rate + PERCENT_RATE < 9.8: |
| | | rate += PERCENT_RATE |
| | | return rate, PERCENT_RATE |
| | | |
| | | @classmethod |
| | | def set_y_info(cls, code, max_rate, axes, axes2, price): |
| | | # 设置y轴数据 |
| | | max_rate, amplitude = cls.__format_max_rate(max_rate) |
| | | line_count = int(round(max_rate / amplitude)) |
| | | print("line_count", line_count) |
| | | yticks2 = [] |
| | | for i in range(0, line_count * 2 + 1): |
| | | if i >= line_count: |
| | | yticks2.append(0 - round(max_rate * (line_count - i) / line_count, 4)) |
| | | else: |
| | | yticks2.append(round(max_rate * (i - line_count) / line_count, 4)) |
| | | yticks2_labels = [] |
| | | yticks = [] |
| | | yticks_labels = [] |
| | | if code not in cls.h_lines_dict: |
| | | cls.h_lines_dict[code] = [] |
| | | |
| | | for line in cls.h_lines_dict[code]: |
| | | line.remove() |
| | | cls.h_lines_dict[code].clear() |
| | | |
| | | for i in range(0, len(yticks2)): |
| | | # if i % 2 == 0: |
| | | yticks2_labels.append("{}%".format(abs(round(yticks2[i], 2)))) |
| | | # else: |
| | | # yticks2_labels.append("") |
| | | price_ = round((1 + yticks2[i] / 100) * price, 2) |
| | | yticks.append(price_) |
| | | if i % 2 == 0 and False: |
| | | yticks_labels.append("") |
| | | # yticks_labels.append(round(yticks[i], 2)) |
| | | if i == line_count: |
| | | hline = axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=2) |
| | | cls.h_lines_dict[code].append(hline) |
| | | else: |
| | | # hline = axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=1.2) |
| | | # cls.h_lines_dict[code].append(hline) |
| | | pass |
| | | else: |
| | | # axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=0.5) |
| | | yticks_labels.append("") |
| | | axes2.set_ylabel(u'') |
| | | # 设置纵轴的值的范围 |
| | | axes2.set_ylim(0 - max_rate, max_rate) |
| | | axes.set_ylim(0 - max_rate, max_rate) |
| | | axes2.set_yticks(yticks2) |
| | | axes2.set_yticklabels(yticks2_labels) |
| | | # axes.axhline(0, color='firebrick', linewidth=2) |
| | | |
| | | # 设置纵坐标数值颜色 |
| | | for i in range(0, line_count): |
| | | # axes.get_yticklabels()[i].set_color("green") |
| | | axes2.get_yticklabels()[i].set_color("green") |
| | | for i in range(line_count, line_count): |
| | | # axes.get_yticklabels()[i].set_color("white") |
| | | axes2.get_yticklabels()[i].set_color("white") |
| | | for i in range(line_count + 1, line_count * 2 + 1): |
| | | # axes.get_yticklabels()[i].set_color("red") |
| | | axes2.get_yticklabels()[i].set_color("red") |
| | | |
| | | @classmethod |
| | | def mark_code_info(cls, code, max_rate, axes2, cost_rate): |
| | | ## 标记代码相关的信息 |
| | | # 设置成本线 |
| | | if code in cls.cost_mark_dict: |
| | | cls.cost_mark_dict[code].remove() |
| | | if cost_rate is None: |
| | | return |
| | | mark_x = axes2.get_xlim() |
| | | mark_y = axes2.get_ylim() |
| | | if cost_rate > max_rate: |
| | | scatter_cost = axes2.scatter((mark_x[0] + mark_x[1]) // 2, mark_y[1] - mark_y[1] / 25, c='#159EEC', |
| | | marker='^', s=50) |
| | | cls.cost_mark_dict[code] = scatter_cost |
| | | elif cost_rate < 0 and abs(cost_rate) > max_rate: |
| | | scatter_cost = axes2.scatter((mark_x[0] + mark_x[1]) // 2, 0 - mark_y[1] + mark_y[1] / 25, c='#159EEC', |
| | | marker='v', s=50) |
| | | cls.cost_mark_dict[code] = scatter_cost |
| | | else: |
| | | line1 = axes2.axhline(cost_rate, linestyle='--', color='#FF8020', lw=1) |
| | | cls.cost_mark_dict[code] = line1 |
| | | |
| | | # 更新数据 |
| | | def __update_data(self, code, axes, datas, pre_price, y_max_rate=10.5, cost_rate=None): |
| | | def on_pick(event): |
| | | ind = event.ind[0] |
| | | offset = event.artist.get_offsets()[ind] |
| | | x = offset[0] |
| | | y = offset[1] |
| | | TickCompareFrame.set_mouse_data(x, y, code, axes[4]) |
| | | print(f"Clicked on point ({x}, {y})") |
| | | |
| | | y_max_rate, a = self.__format_max_rate(y_max_rate) |
| | | if code not in self.last_max_rate_dict or self.last_max_rate_dict[code] < y_max_rate: |
| | | self.last_max_rate_dict[code] = y_max_rate |
| | | # 设置纵坐标的信息 |
| | | self.set_y_info(code, y_max_rate, axes[4], axes[0], pre_price) |
| | | # 标记代码相关的信息 |
| | | self.mark_code_info(code, self.last_max_rate_dict[code], axes[0], cost_rate) |
| | | |
| | | # 删除9:30以前的数据 |
| | | for i in range(0, len(datas)): |
| | | time_ = datas[i]["created_at"][-8:] |
| | | if int(time_.replace(":", "")) >= int("092600"): |
| | | datas = datas[i:] |
| | | break |
| | | # 取最近14分钟的数据 |
| | | for i in range(len(datas) - 1, -1, -1): |
| | | time_ = datas[i]["created_at"][-8:] |
| | | if tool.trade_time_sub(datas[-1]["created_at"][-8:], time_) >= self.X_DATA_MINIUTES * 60: |
| | | datas = datas[i:] |
| | | break |
| | | |
| | | xs = [] |
| | | ys_rate = [] |
| | | ys_average_rate_1m = [] |
| | | ys_average_rate = [] |
| | | for data in datas: |
| | | xs.append(self.get_x_time_as_seconds(data["created_at"])) |
| | | ys_rate.append(data["rate"] * 100) |
| | | |
| | | ys_average_rate_1m.append(data["average_rate"] * 100 + 1.5) |
| | | ys_average_rate.append(data["average_rate"] * 100) |
| | | |
| | | xticks = [] |
| | | xticklabels = [] |
| | | # 设置X轴范围为09:30:00 到15:00:00 |
| | | # x轴范围为0-15分钟 |
| | | # end_x = "0000-00-00 " + tool.trade_time_add_second(datas[0]["created_at"][-8:], self.X_RANGE_MINIUTES * 60) |
| | | # axes[0].set_xlim(self.get_x_time_as_seconds(datas[0]["created_at"]), self.get_x_time_as_seconds(end_x)) |
| | | |
| | | xms = axes[0].get_xlim() |
| | | yms = axes[0].get_ylim() |
| | | # 暂时不设置X坐标 |
| | | # step = (int(xms[1]) - int(xms[0])) // 30 |
| | | # for i in range(int(xms[0]), int(xms[1] + 1), step): |
| | | # xticks.append(i) |
| | | # xticklabels.append("") |
| | | # axes[0].set_xticks(xticks) |
| | | # axes[0].set_xticklabels(xticklabels) |
| | | |
| | | axes[1][0].set_data(xs, ys_rate) |
| | | |
| | | point_x = xs[0] + 1 |
| | | point_y = ys_rate[0] |
| | | |
| | | if code not in self.sell_points_dict: |
| | | self.sell_points_dict[code] = queue.Queue() |
| | | if code in self.sell_points_dict: |
| | | if not self.sell_points_dict[code].empty(): |
| | | item = self.sell_points_dict[code].get_nowait() |
| | | if item: |
| | | points = axes[0].scatter(item[0], item[1], s=15, c='green', zorder=2, picker=5) |
| | | # 设置点击事件 |
| | | axes[0].figure.canvas.mpl_connect('pick_event', on_pick) |
| | | |
| | | # 不需要一分钟均线 |
| | | # axes[2][0].set_data(xs, ys_average_rate_1m) |
| | | if axes[3]: |
| | | axes[3][0].set_data(xs, ys_average_rate) |
| | | texts = axes[0].texts |
| | | texts[0].set_text("{}% ".format(round(datas[-1]["rate"] * 100, 2))) |
| | | if datas[-1]["rate"] > 0: |
| | | texts[0].set_color('red') |
| | | elif datas[-1]["rate"] == 0: |
| | | texts[0].set_color('white') |
| | | else: |
| | | texts[0].set_color('green') |
| | | # texts[1].set_text("{}".format(datas[-1]["created_at"].split(" ")[1])) |
| | | texts[1].set_text("") |
| | | texts[0].set_x(xms[1] - 130) |
| | | texts[0].set_y(yms[1] + yms[1] / 20) |
| | | texts[1].set_x(xms[0]) |
| | | texts[1].set_y(yms[0] - yms[1] / 9) |
| | | |
| | | # 删除之前 |
| | | if code in self.lines: |
| | | for key in self.lines[code]: |
| | | line = self.lines[code][key] |
| | | line.remove() |
| | | self.lines.pop(code) |
| | | # 暂时不需要 绘制最大最小坐标 |
| | | # line_min = axes[0].axhline(min_rate, linestyle='--', color='yellow', lw=0.5) |
| | | # line_max = axes[0].axhline(max_rate, linestyle='--', color='yellow', lw=0.5) |
| | | # self.lines[code] = {"min": line_min, "max": line_max} |
| | | axes[0].figure.canvas.draw() |
| | | axes[0].figure.canvas.flush_events() |
| | | |
| | | def __init__(self, axes_list, codes_info): |
| | | self.axes_list = axes_list |
| | | self.codes_info = codes_info |
| | | self.lines = {} |
| | | |
| | | def update(self, code, pre_price, datas): |
| | | __start_time = time.time() |
| | | # 获取当前的坐标范围 |
| | | max_price = pre_price |
| | | for d in datas: |
| | | if abs(d['price'] - pre_price) > abs(max_price - pre_price): |
| | | max_price = d['price'] |
| | | y_max_rate = round(abs(max_price - pre_price) * 100 / pre_price, 2) |
| | | # 展示最近的600个 |
| | | # datas = datas[0 - self.X_DATA_MINIUTES * 20:] |
| | | # 修正量数据 |
| | | last_info = None |
| | | for i in range(1, len(datas)): |
| | | # 如果在 |
| | | if not last_info: |
| | | last_info = datas[i] |
| | | if int(datas[i]["created_at"][-2:]) - int(datas[i - 1]["created_at"][-2:]) < 0: |
| | | last_info = datas[i] |
| | | datas[i]['average_rate_1m'] = last_info['average_rate'] |
| | | datas[0]['average_rate_1m'] = datas[0]['average_rate'] |
| | | |
| | | for i in range(0, len(self.codes_info)): |
| | | if self.codes_info[i][0] == code: |
| | | try: |
| | | self.__update_data(code, self.axes_list[i], datas, pre_price, y_max_rate, |
| | | self.cost_rate_dict.get(code)) |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | # print("绘图花费时间:", time.time() - __start_time) |
| | | |
| | | |
| | | class TickCompareFrame(wx.Frame): |
| | | # 可转债代码数据 |
| | | __cb_datas = [] |
| | | mark_lines = {} |
| | | |
| | | @classmethod |
| | | def show_warning(cls, content, click=None): |
| | | toastone = wx.MessageDialog(None, content, "提示", wx.YES_DEFAULT | wx.ICON_WARNING) |
| | | if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 |
| | | if click is not None: |
| | | click() |
| | | toastone.Destroy() |
| | | |
| | | @classmethod |
| | | def show_info(cls, content, click): |
| | | toastone = wx.MessageDialog(None, content, "提示", wx.YES_DEFAULT | wx.ICON_INFORMATION) |
| | | if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 |
| | | click() |
| | | toastone.Destroy() |
| | | |
| | | def __init__(self): |
| | | super().__init__(None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE, |
| | | size=(800, 1000)) |
| | | self.SetBackgroundColour(wx.Colour(0, 0, 0)) |
| | | |
| | | self.Center() |
| | | |
| | | # 拉取数据线程 |
| | | self.cost_price_threads = {} |
| | | # 定义窗口关闭 |
| | | # self.Bind(wx.EVT_SIZE, self.OnResize) |
| | | self.panels = [] |
| | | self.col = 1 |
| | | self.ratio = 0.55 |
| | | |
| | | self.panel = wx.Panel(self, size=(-1, 50)) |
| | | self.panel.SetBackgroundColour(wx.Colour(255, 255, 255)) |
| | | bs1 = wx.BoxSizer(wx.HORIZONTAL) |
| | | self.edit_code1 = wx.TextCtrl(self.panel, size=(100, 25)) |
| | | self.btn_load_data = wx.Button(self.panel, label="加载数据", size=(80, 25)) |
| | | bs1.Add(wx.StaticText(self.panel, label="股票代码:"), proportion=0, flag=wx.ALL, border=12) |
| | | bs1.Add(self.edit_code1, proportion=0, flag=wx.ALL, border=10) |
| | | bs1.Add(self.btn_load_data, proportion=0, flag=wx.ALL, border=10) |
| | | self.panel.SetSizer(bs1) |
| | | |
| | | # 初始化 |
| | | # self.scroll = wx.ScrolledWindow(self, -1, size=(800, 1000)) |
| | | root_boxsier = wx.BoxSizer(wx.VERTICAL) |
| | | root_boxsier.Add(self.panel, proportion=0, flag=wx.EXPAND) |
| | | self.panel1 = wx.Panel(self, size=(-1, 400)) |
| | | self.panel2 = wx.Panel(self, size=(-1, 400)) |
| | | self.panel1.SetBackgroundColour(wx.Colour(255, 0, 0)) |
| | | self.panel2.SetBackgroundColour(wx.Colour(0, 255, 0)) |
| | | |
| | | root_boxsier.Add(self.panel1, proportion=0, flag=wx.EXPAND) |
| | | root_boxsier.Add(self.panel2, proportion=0, flag=wx.EXPAND) |
| | | self.SetSizer(root_boxsier) |
| | | self.Layout() |
| | | |
| | | self.btn_load_data.Bind(wx.EVT_BUTTON, lambda e: self.__load_data(e)) |
| | | |
| | | def __load_data(self, event): |
| | | code = self.edit_code1.GetValue() |
| | | # 获取可转债 |
| | | if not self.__cb_datas: |
| | | self.__cb_datas = JueJinUtil.get_all_convertible_bonds_codes() |
| | | cb_codes = None |
| | | for b in self.__cb_datas: |
| | | if b[1].find(code) >= 0: |
| | | cb_codes = b |
| | | break |
| | | if not cb_codes: |
| | | self.show_warning("无可转债") |
| | | return |
| | | # 获取基础信息 |
| | | base_infos = JueJinApi.get_gp_latest_info([cb_codes[0], cb_codes[1]], fields="symbol,sec_id,sec_name,pre_close") |
| | | fdatas = [] |
| | | for b in base_infos: |
| | | # 加载数据,获取tick |
| | | start_time, end_time = f"{tool.get_now_date_str()} 09:30:00", f"{tool.get_now_date_str()} {tool.get_now_time_str()}" |
| | | results = JueJinApi.get_history_tick(b['symbol'], start_time, end_time, frequency="tick") |
| | | datas = [] |
| | | for data in results: |
| | | data['created_at'] = data["created_at"].strftime("%Y-%m-%d %H:%M:%S") |
| | | datas.append(juejin_core.parse_tick(data)) |
| | | |
| | | # (代码,代码名称,收盘价) |
| | | fdatas.append((b['sec_id'], b['sec_name'], b['pre_close'], datas)) |
| | | |
| | | panels = [self.panel1, self.panel2] |
| | | |
| | | axes_list = [] |
| | | codes_name = [] |
| | | for i in range(len(fdatas)): |
| | | d = fdatas[i] |
| | | axes = self.__create_canvas(panels[i], d[0], d[1], d[2], d[3]) |
| | | axes_list.append(axes) |
| | | codes_name.append(d[1]) |
| | | drawManager = DrawManager(axes_list, codes_name) |
| | | for d in fdatas: |
| | | drawManager.update(d[0], d[2], d[3]) |
| | | |
| | | @classmethod |
| | | def set_mouse_data(cls, xdata, ydata, code, axes2): |
| | | try: |
| | | if code not in cls.mark_lines: |
| | | cls.mark_lines[code] = {} |
| | | if "mouse" not in cls.mark_lines[code]: |
| | | line_h = axes2.axhline(ydata, linestyle='-', color='white', lw=0.5, zorder=3) |
| | | line_v = axes2.axvline(xdata, linestyle='-', color='white', lw=0.5, zorder=3) |
| | | text_h = axes2.text(axes2.get_xlim()[1], ydata, r'', fontsize=10, color='white', |
| | | verticalalignment="center", bbox=dict(facecolor='white', alpha=0.9), zorder=3) |
| | | text_v = axes2.text(xdata, axes2.get_ylim()[0], r'', fontsize=10, color='red', |
| | | verticalalignment='top', horizontalalignment='center', |
| | | bbox=dict(facecolor='white', alpha=0.9), zorder=3) |
| | | |
| | | cls.mark_lines[code]["mouse"] = (line_h, line_v, text_h, text_v) |
| | | line = cls.mark_lines.get(code).get("mouse") |
| | | x = round(xdata) |
| | | y = round(ydata, 2) |
| | | |
| | | line[0].set_ydata(ydata) |
| | | line[1].set_xdata(xdata) |
| | | line[2].set_text(f"{y}%") |
| | | line[3].set_text(f"{tool.trade_time_add_second('09:30:00', x)}") |
| | | line[2].set_x(axes2.get_xlim()[1] * (1 + 0.005)) |
| | | line[2].set_y(y) |
| | | line[3].set_x(x) |
| | | line[3].set_y(axes2.get_ylim()[0] * (1 + 0.02)) |
| | | if y >= 0: |
| | | line[2].set_color('red') |
| | | else: |
| | | line[2].set_color('green') |
| | | axes2.figure.canvas.draw() |
| | | except Exception as e: |
| | | pass |
| | | |
| | | def __create_canvas(self, pannel, code, title, price, datas, close_callback=None): |
| | | def show_mouse_line(event): |
| | | # 删除之前的线 |
| | | self.set_mouse_data(event.xdata, event.ydata, code, axes) |
| | | |
| | | def clear_mouse_line(event): |
| | | print("clear_mouse_line") |
| | | if code in self.mark_lines: |
| | | if self.mark_lines.get(code): |
| | | line = self.mark_lines.get(code).get("mouse") |
| | | if line is not None: |
| | | for l in line: |
| | | l.remove() |
| | | self.mark_lines.get(code).pop("mouse") |
| | | axes.figure.canvas.draw() |
| | | |
| | | def close_canvas(event): |
| | | print("关闭", title) |
| | | close_callback(title) |
| | | |
| | | dpi = 100 |
| | | width_dpi = self.Size[0] / (dpi * self.col) |
| | | figure_score = Figure(figsize=(width_dpi, round(width_dpi * (self.ratio), 2)), dpi=dpi) |
| | | # 设置外边距 |
| | | right_padding_px = 85 |
| | | right = round((self.Size[0] - right_padding_px) / self.Size[0], 4) |
| | | figure_score.subplots_adjust(left=0.01, bottom=0.15, top=0.92, |
| | | right=right) |
| | | # 设置字体颜色 |
| | | plt.rcParams["text.color"] = "red" |
| | | plt.rcParams["axes.labelcolor"] = "red" |
| | | # 设置坐标轴数字颜色 |
| | | plt.rcParams["xtick.color"] = "white" |
| | | plt.rcParams["ytick.color"] = "white" |
| | | # 设置坐标轴颜色 |
| | | plt.rcParams["axes.edgecolor"] = "firebrick" |
| | | |
| | | # 解决中文乱码问题 |
| | | plt.rcParams["font.sans-serif"] = ["SimHei"] # 设置字体 |
| | | plt.rcParams["font.serif"] = ["SimHei"] |
| | | plt.rcParams["axes.unicode_minus"] = False # 该语句解决图像中的“-”负号的乱码问题 |
| | | |
| | | axes = figure_score.add_subplot(1, 1, 1) |
| | | axes.autoscale(True) |
| | | |
| | | # axes_score.plot(t_score, s_score, 'ro', t_score, s_score, 'k') |
| | | axes.set_title(title) |
| | | axes.grid(False) |
| | | axes.set_xlabel(f'时间({title})') |
| | | axes.dist = 0 |
| | | |
| | | # axes.set_ylabel(u'价格') |
| | | # 获取平开价 |
| | | extra = 0 # (tool.get_limit_up_price(price)-decimal.Decimal(price))*decimal.Decimal(0.02) |
| | | |
| | | axes.patch.set_facecolor('black') |
| | | figure_score.patch.set_facecolor('black') |
| | | |
| | | # 设置横坐标9:25-15:00 |
| | | xs_str = ["09:25", "09:30", "10:30", "11:30", "14:00", "15:00"] |
| | | xs_int = [DrawManager.get_x_time_as_seconds(f"0000-00-00 {x}:00") for x in xs_str] |
| | | axes.set_xticks(xs_int[1:]) |
| | | axes.set_xticklabels(xs_str[1:]) |
| | | axes.set_xlim([xs_int[0], xs_int[-1]]) |
| | | |
| | | axes2 = axes.twinx() |
| | | # axes2.grid(color='firebrick', ls='-', lw=0.5) |
| | | axes2.grid(color='firebrick', ls='-', lw=0.5) |
| | | # 鼠标在画布移动 |
| | | # axes2.figure.canvas.mpl_connect('motion_notify_event', show_mouse_line) |
| | | # # 鼠标离开画布 |
| | | # axes2.figure.canvas.mpl_connect('axes_leave_event', clear_mouse_line) |
| | | |
| | | # 设置纵坐标轴 |
| | | limit_up_price = float(tool.get_limit_up_price(price)) |
| | | max_rate = round((limit_up_price - price) / price, 4) * 100 |
| | | print("涨停最大比例", max_rate) |
| | | # 设置纵坐标信息 |
| | | # max_rate = 2 |
| | | DrawManager.set_y_info(code, max_rate, axes, axes2, price) |
| | | |
| | | line = axes2.plot([], [], color='white', linewidth=1) |
| | | average_line = axes2.plot([], [], color='yellow', linewidth=1, linestyle='-') |
| | | average_line_1m = axes2.plot([], [], color='yellow', linewidth=1, linestyle='-') |
| | | # axes2.legend(loc='upper left') |
| | | cannvas = FigureCanvas(pannel, -1, figure_score) |
| | | axes2.text(1, 11.5, r'', fontsize=15, color='red') |
| | | axes2.text(-1, -11.5, r'', fontsize=15, color='red') |
| | | |
| | | axes2.spines['top'].set_visible(False) |
| | | axes.spines['top'].set_visible(False) |
| | | axes2.spines['bottom'].set_visible(True) |
| | | axes.spines['bottom'].set_visible(False) |
| | | |
| | | # 中轴线加粗 |
| | | hline = axes2.axhline(0, linestyle='-', color='firebrick', lw=2, zorder=1) |
| | | |
| | | # 设置坐标轴标记点为黑色 |
| | | axes.tick_params(axis='x', colors='firebrick') |
| | | axes.tick_params(axis='y', colors='black') |
| | | axes2.tick_params(axis='x', colors='firebrick') |
| | | axes2.tick_params(axis='y', colors='black') |
| | | |
| | | def update_data(i): |
| | | print("更新数据:", i) |
| | | |
| | | return axes2, line, average_line_1m, average_line, axes |
| | | |
| | | def OnResize(self, e): |
| | | print("变化后的尺寸", e.Size) |
| | | |
| | | |
| | | class mainApp(wx.App): |
| | | |
| | | def __show_main_frame(self): |
| | | self.frame.Show() |
| | | |
| | | def __init_data(self): |
| | | try: |
| | | pass |
| | | except: |
| | | pass |
| | | |
| | | def OnInit(self): |
| | | self.SetAppName(APP_TITLE) |
| | | self.__init_data() |
| | | self.frame = TickCompareFrame() |
| | | self.__show_main_frame() |
| | | return True |
| | | |
| | | |
| | | def run(): |
| | | JueJinUtil.get_all_convertible_bonds_codes() |
| | | app = mainApp() |
| | | app.MainLoop() |
| | |
| | | return t1 |
| | | |
| | | |
| | | class TickCompareFrame(wx.Frame): |
| | | mark_lines = {} |
| | | |
| | | def __init__(self): |
| | | '''构造函数''' |
| | | wx.Frame.__init__(self, None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE, |
| | | size=(800, 1000)) |
| | | self.SetBackgroundColour(wx.Colour(0, 0, 0)) |
| | | |
| | | self.Center() |
| | | |
| | | # 拉取数据线程 |
| | | self.cost_price_threads = {} |
| | | |
| | | # 以下代码处理图标 |
| | | # if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe": |
| | | # exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None)) |
| | | # icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO) |
| | | # else: |
| | | # icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO) |
| | | # self.SetIcon(icon) |
| | | # 定义窗口关闭 |
| | | self.Bind(wx.EVT_CLOSE, self.OnExit) |
| | | self.Bind(wx.EVT_SIZE, self.OnResize) |
| | | self.panels = [] |
| | | self.scroll = None |
| | | self.col = 1 |
| | | self.ratio = 0.55 |
| | | self.__re_draw() |
| | | |
| | | self.timer = wx.Timer(self) # 创建定时器 |
| | | self.Bind(wx.EVT_TIMER, self.post_redraw, self.timer) # 绑定一个定时器事件 |
| | | self.last_size = (self.Size[0], self.Size[1]) |
| | | |
| | | # 初始化 |
| | | # self.scroll = wx.ScrolledWindow(self, -1, size=(800, 1000)) |
| | | self.boxsier = wx.BoxSizer(wx.VERTICAL) |
| | | boxSizer1 = wx.BoxSizer(wx.HORIZONTAL) |
| | | self.edit_code1 = wx.TextCtrl(self, size=(100, 30)) |
| | | self.edit_code2 = wx.TextCtrl(self, size=(100, 30)) |
| | | self.btn_load_data = wx.Button(self, label="加载数据", size=(100, 30)) |
| | | boxSizer1.Add(self.edit_code1) |
| | | boxSizer1.Add(self.edit_code2) |
| | | boxSizer1.Add(self.btn_load_data, 1, wx.LEFT|wx.TOP, 2) |
| | | |
| | | self.boxsier.Add(boxSizer1) |
| | | |
| | | # self.scroll.EnableScrolling(False, True) |
| | | |
| | | # self.boxsier.Add(wx.FlexGridSizer(rows, self.col, space, space)) |
| | | |
| | | # self.scroll.SetSizer(self.boxsier) |
| | | |
| | | # self.scroll.Layout() |
| | | # self.boxsier.Fit(self.scroll) |
| | | |
| | | # boxsier.Add(mainBoxsier, 1, wx.EXPAND | wx.ALL, 5) |
| | | # self.SetSizer(boxsier) |
| | | # mainBoxsier.Fit(self) |
| | | if setting.is_stay_on_top(): |
| | | self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.STAY_ON_TOP |
| | | |
| | | def __re_draw(self): |
| | | return |
| | | codes_name = juejin_core.GPCodeManager().get_codes_with_names() |
| | | rows = len(codes_name) |
| | | if rows % self.col == 0: |
| | | rows = rows / self.col |
| | | else: |
| | | rows = rows / self.col + 1 |
| | | space = 0 |
| | | if not self.scroll: |
| | | return |
| | | |
| | | if self.panels: |
| | | for p in self.panels: |
| | | p.Destroy() |
| | | self.boxsier.Clear() |
| | | |
| | | pannel_height = round((self.Size[0] - (self.col - 1) * space) / self.col * self.ratio) |
| | | |
| | | self.scroll.SetScrollbars(1, 1, 0, pannel_height * rows) |
| | | self.scroll.SetScrollRate(0, pannel_height) |
| | | global drawManager |
| | | axes_list = [] |
| | | self.panels = [] |
| | | for i in range(0, len(codes_name)): |
| | | # pos=(0, i * pannel_height) |
| | | pannel = wx.Panel(self.scroll, size=(-1, pannel_height)) |
| | | pannel.BackgroundColour = wx.Colour(0, 0, 0) |
| | | self.panels.append(pannel) |
| | | self.boxsier.Add(pannel) |
| | | code = codes_name[i][0] |
| | | axes = self.__create_canvas(pannel, code, "{}({})".format(codes_name[i][0], codes_name[i][1]), |
| | | codes_name[i][1], |
| | | codes_name[i][2]) |
| | | |
| | | if code not in self.cost_price_threads: |
| | | t1 = self.run_get_cost_price(codes_name[i][0]) |
| | | self.cost_price_threads[code] = t1 |
| | | axes_list.append(axes) |
| | | |
| | | self.scroll.Layout() |
| | | # self.boxsier.Fit(self.scroll) |
| | | # |
| | | # 初始化数据 |
| | | drawManager = DrawManager(axes_list, codes_name) |
| | | t1 = threading.Thread(target=lambda: drawManager.init_code_datas()) |
| | | # 后台运行 |
| | | t1.setDaemon(True) |
| | | t1.start() |
| | | |
| | | @classmethod |
| | | def set_mouse_data(cls, xdata, ydata, code, axes2): |
| | | try: |
| | | if code not in cls.mark_lines: |
| | | cls.mark_lines[code] = {} |
| | | if "mouse" not in cls.mark_lines[code]: |
| | | line_h = axes2.axhline(ydata, linestyle='-', color='white', lw=0.5, zorder=3) |
| | | line_v = axes2.axvline(xdata, linestyle='-', color='white', lw=0.5, zorder=3) |
| | | text_h = axes2.text(axes2.get_xlim()[1], ydata, r'', fontsize=10, color='white', |
| | | verticalalignment="center", bbox=dict(facecolor='white', alpha=0.9), zorder=3) |
| | | text_v = axes2.text(xdata, axes2.get_ylim()[0], r'', fontsize=10, color='red', |
| | | verticalalignment='top', horizontalalignment='center', |
| | | bbox=dict(facecolor='white', alpha=0.9), zorder=3) |
| | | |
| | | cls.mark_lines[code]["mouse"] = (line_h, line_v, text_h, text_v) |
| | | line = cls.mark_lines.get(code).get("mouse") |
| | | x = round(xdata) |
| | | y = round(ydata, 2) |
| | | |
| | | line[0].set_ydata(ydata) |
| | | line[1].set_xdata(xdata) |
| | | line[2].set_text(f"{y}%") |
| | | line[3].set_text(f"{tool.trade_time_add_second('09:30:00', x)}") |
| | | line[2].set_x(axes2.get_xlim()[1] * (1 + 0.005)) |
| | | line[2].set_y(y) |
| | | line[3].set_x(x) |
| | | line[3].set_y(axes2.get_ylim()[0] * (1 + 0.02)) |
| | | if y >= 0: |
| | | line[2].set_color('red') |
| | | else: |
| | | line[2].set_color('green') |
| | | axes2.figure.canvas.draw() |
| | | except Exception as e: |
| | | pass |
| | | |
| | | def __create_canvas(self, pannel, code, title, name, price, close_callback=None): |
| | | TickDataProcess.clear(code) |
| | | |
| | | def show_mouse_line(event): |
| | | # 删除之前的线 |
| | | self.set_mouse_data(event.xdata, event.ydata, code, axes) |
| | | |
| | | def clear_mouse_line(event): |
| | | print("clear_mouse_line") |
| | | if code in self.mark_lines: |
| | | if self.mark_lines.get(code): |
| | | line = self.mark_lines.get(code).get("mouse") |
| | | if line is not None: |
| | | for l in line: |
| | | l.remove() |
| | | self.mark_lines.get(code).pop("mouse") |
| | | axes.figure.canvas.draw() |
| | | |
| | | def close_canvas(event): |
| | | print("关闭", title) |
| | | close_callback(title) |
| | | |
| | | dpi = 100 |
| | | width_dpi = self.Size[0] / (dpi * self.col) |
| | | figure_score = Figure(figsize=(width_dpi, round(width_dpi * (self.ratio), 2)), dpi=dpi) |
| | | # 设置外边距 |
| | | right_padding_px = 85 |
| | | right = round((self.Size[0] - right_padding_px) / self.Size[0], 4) |
| | | figure_score.subplots_adjust(left=0.01, bottom=0.15, top=0.92, |
| | | right=right) |
| | | # 设置字体颜色 |
| | | plt.rcParams["text.color"] = "red" |
| | | plt.rcParams["axes.labelcolor"] = "red" |
| | | # 设置坐标轴数字颜色 |
| | | plt.rcParams["xtick.color"] = "white" |
| | | plt.rcParams["ytick.color"] = "white" |
| | | # 设置坐标轴颜色 |
| | | plt.rcParams["axes.edgecolor"] = "firebrick" |
| | | |
| | | # 解决中文乱码问题 |
| | | plt.rcParams["font.sans-serif"] = ["SimHei"] # 设置字体 |
| | | plt.rcParams["font.serif"] = ["SimHei"] |
| | | plt.rcParams["axes.unicode_minus"] = False # 该语句解决图像中的“-”负号的乱码问题 |
| | | |
| | | # 测试 |
| | | buttonaxe = plt.axes([0.94, 0.5, 0.1, 0.1]) |
| | | button1 = Button(buttonaxe, '关闭', color='white', hovercolor='yellow') |
| | | |
| | | axes = figure_score.add_subplot(1, 1, 1) |
| | | axes.autoscale(True) |
| | | |
| | | # axes_score.plot(t_score, s_score, 'ro', t_score, s_score, 'k') |
| | | axes.set_title(title) |
| | | axes.grid(False) |
| | | axes.set_xlabel(f'时间({name})') |
| | | axes.dist = 0 |
| | | |
| | | # axes.set_ylabel(u'价格') |
| | | # 获取平开价 |
| | | extra = 0 # (tool.get_limit_up_price(price)-decimal.Decimal(price))*decimal.Decimal(0.02) |
| | | |
| | | axes.patch.set_facecolor('black') |
| | | figure_score.patch.set_facecolor('black') |
| | | |
| | | # 设置横坐标9:25-15:00 |
| | | xs_str = ["09:25", "09:30", "10:30", "11:30", "14:00", "15:00"] |
| | | xs_int = [DrawManager.get_x_time_as_seconds(f"0000-00-00 {x}:00") for x in xs_str] |
| | | axes.set_xticks(xs_int[1:]) |
| | | axes.set_xticklabels(xs_str[1:]) |
| | | axes.set_xlim([xs_int[0], xs_int[-1]]) |
| | | |
| | | axes2 = axes.twinx() |
| | | # axes2.grid(color='firebrick', ls='-', lw=0.5) |
| | | axes2.grid(color='firebrick', ls='-', lw=0.5) |
| | | # 鼠标在画布移动 |
| | | # axes2.figure.canvas.mpl_connect('motion_notify_event', show_mouse_line) |
| | | # # 鼠标离开画布 |
| | | # axes2.figure.canvas.mpl_connect('axes_leave_event', clear_mouse_line) |
| | | |
| | | # 设置纵坐标轴 |
| | | limit_up_price = float(tool.get_limit_up_price(price)) |
| | | max_rate = round((limit_up_price - price) / price, 4) * 100 |
| | | print("涨停最大比例", max_rate) |
| | | # 设置纵坐标信息 |
| | | # max_rate = 2 |
| | | DrawManager.set_y_info(code, max_rate, axes, axes2, price) |
| | | |
| | | line = axes2.plot([], [], color='white', linewidth=1) |
| | | average_line = axes2.plot([], [], color='yellow', linewidth=1, linestyle='-') |
| | | average_line_1m = axes2.plot([], [], color='yellow', linewidth=1, linestyle='-') |
| | | # axes2.legend(loc='upper left') |
| | | cannvas = FigureCanvas(pannel, -1, figure_score) |
| | | axes2.text(1, 11.5, r'', fontsize=15, color='red') |
| | | axes2.text(-1, -11.5, r'', fontsize=15, color='red') |
| | | |
| | | axes2.spines['top'].set_visible(False) |
| | | axes.spines['top'].set_visible(False) |
| | | axes2.spines['bottom'].set_visible(True) |
| | | axes.spines['bottom'].set_visible(False) |
| | | |
| | | # 中轴线加粗 |
| | | hline = axes2.axhline(0, linestyle='-', color='firebrick', lw=2, zorder=1) |
| | | |
| | | # 设置坐标轴标记点为黑色 |
| | | axes.tick_params(axis='x', colors='firebrick') |
| | | axes.tick_params(axis='y', colors='black') |
| | | axes2.tick_params(axis='x', colors='firebrick') |
| | | axes2.tick_params(axis='y', colors='black') |
| | | |
| | | def update_data(i): |
| | | print("更新数据:", i) |
| | | |
| | | return axes2, line, average_line_1m, average_line, axes |
| | | |
| | | def __show_top(self, event): |
| | | if event.Selection: |
| | | setting.set_stay_on_top(1) |
| | | self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.STAY_ON_TOP |
| | | else: |
| | | setting.set_stay_on_top(0) |
| | | self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN |
| | | |
| | | def OnExit(self, e): |
| | | try: |
| | | setting.set_tick_window_info((self.Position[0], self.Position[1], self.Size[0], self.Size[1])) |
| | | except Exception as e: |
| | | print("") |
| | | self.Hide() |
| | | |
| | | def post_redraw(self, evt): |
| | | |
| | | if abs(self.last_size[0] - self.Size[0]) > 20: |
| | | print("--------post_redraw--------") |
| | | self.last_size = (self.Size[0], self.Size[1]) |
| | | self.__re_draw() |
| | | |
| | | def OnResize(self, e): |
| | | print("变化后的尺寸", e.Size) |
| | | # 留出滚动条,留出上边距 |
| | | if self.scroll: |
| | | self.scroll.Size = (e.Size[0] - 15, e.Size[1] - 60) |
| | | for p in self.panels: |
| | | p_height = round(e.Size[0] * (450 / 800)) |
| | | p.Size = (e.Size[0], p_height) |
| | | self.timer.Stop() |
| | | self.timer.StartOnce(1000) |
| | | |
| | | # 降低重绘频率 |
| | | # self.__re_draw() |
| | | |
| | | def set_codes_success(self): |
| | | print("设置代码成功回调") |
| | | p2.send("resub") |
| | | self.__re_draw() |
| | | self.timer.Stop() |
| | | self.timer.StartOnce(1000) |
| | | self.Size = wx.Size(self.Size[0], self.Size[1] + 10) |
| | | time.sleep(0.1) |
| | | self.Size = wx.Size(self.Size[0], self.Size[1] - 10) |
| | | |
| | | def run_get_cost_price(self, code): |
| | | def request(code): |
| | | while True: |
| | | try: |
| | | price = SocketApiUtil.get_cost_price(code) |
| | | pre_price = juejin_core.GPCodeManager().get_pre_prices(code) |
| | | rate = round((price - pre_price) * 100 / pre_price, 2) |
| | | DrawManager.set_cost_rate(code, rate) |
| | | # wx.CallAfter(lambda :) |
| | | except Exception as e: |
| | | DrawManager.set_cost_rate(code, None) |
| | | # wx.CallAfter(lambda: str(e)) |
| | | except: |
| | | pass |
| | | finally: |
| | | time.sleep(3) |
| | | |
| | | t1 = threading.Thread(target=lambda: request(code), daemon=True) |
| | | t1.start() |
| | | return t1 |
| | | |
| | | |
| | | # 绘图管理器 |
| | | class DrawManager: |
| | | X_RANGE_MINIUTES = 335 |
| | |
| | | def OnInit(self): |
| | | self.SetAppName(APP_TITLE) |
| | | self.__init_data() |
| | | self.frame = TickFrame() |
| | | self.frame = TickCompareFrame() |
| | | # self.floatFrame = FloatFrame() |
| | | global_datas["tickFrame"] = self.frame |
| | | # global_datas["floatFrame"] = self.floatFrame |
| | |
| | | # 策略中必须有init方法 |
| | | import datetime |
| | | import json |
| | | import threading |
| | | import time |
| | |
| | | def get_juejin_code_list_with_prefix(cls, codes): |
| | | list = [] |
| | | for d in codes: |
| | | if d[0:2] == '00': |
| | | if d.find(".") > 0: |
| | | list.append(d) |
| | | elif d[0:2] == '00': |
| | | list.append("SZSE.{}".format(d)) |
| | | elif d[0:2] == '60': |
| | | list.append("SHSE.{}".format(d)) |
| | |
| | | return data |
| | | |
| | | @classmethod |
| | | def get_history_tick_n(cls, code, count, fields=None): |
| | | def get_history_tick_n(cls, code, count, fields=None, frequency="1d"): |
| | | symbols = cls.get_juejin_code_list_with_prefix([code]) |
| | | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | # 前除权 |
| | | results = gmapi.history_n(symbol=symbols[0], frequency="1d", count=count, adjust=1, fields=fields) |
| | | results = gmapi.history_n(symbol=symbols[0], frequency=frequency, count=count, adjust=1, fields=fields) |
| | | return results |
| | | |
| | | @classmethod |
| | | def get_history_tick(cls, code, start_time, end_time, fields=None, frequency="1d"): |
| | | symbols = cls.get_juejin_code_list_with_prefix([code]) |
| | | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | # 前除权 |
| | | results = gmapi.history(symbol=symbols[0], frequency=frequency, start_time=start_time, end_time=end_time, |
| | | adjust=1, fields=fields) |
| | | return results |
| | | |
| | | @classmethod |
| | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | return gmapi.get_trading_dates("SHSE", start_date, end_date) |
| | | |
| | | @classmethod |
| | | def get_codes(cls, sec_type): |
| | | """ |
| | | 代码获取 |
| | | :param sec_type: 8:可转债 1:股票 |
| | | :return: |
| | | """ |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | return gmapi.get_instrumentinfos(exchanges="SHSE,SZSE", sec_types=[sec_type]) |
| | | |
| | | @classmethod |
| | | def get_underlying_code(cls, symbols): |
| | | """ |
| | | 获取可转债正股代码 |
| | | :param symbols: 如:[SZSE.128144] |
| | | :return: 正股代码,如:[SZSE.002734] |
| | | """ |
| | | account_id, s_id, token = JueJinApi.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | datas = gmapi.get_instruments(symbols=",".join(symbols), sec_types="8", |
| | | fields="symbol, sec_type, sec_id,sec_name, underlying_symbol") |
| | | fdatas = {} |
| | | for d in datas: |
| | | fdatas[d['symbol']] = d['underlying_symbol'] |
| | | return fdatas |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | # print(JueJinApi.get_gp_latest_info(["SZSE.128144"], "sec_id, underlying_symbol")) |
| | | |
| | | # account_id, s_id, token = JueJinApi.getJueJinAccountInfo() |
| | | # gmapi.set_token(token) |
| | | # data = gmapi.get_instruments(symbols=",".join(["SZSE.128144"]), sec_types="8", fields="symbol, sec_type, sec_id,sec_name, underlying_symbol") |
| | | # print(data) |
| | | |
| | | # 获取所有的可转债 |
| | | # results = JueJinApi.get_codes(8) |
| | | # count = 0 |
| | | # with open("datas/convertible_bonds_codes.txt", mode='w',encoding='utf-8') as f: |
| | | # symbols = [] |
| | | # for result in results: |
| | | # if int(tool.get_now_date_str("%Y%m%d")) < int(result['delisted_date'].strftime("%Y%m%d")): |
| | | # count += 1 |
| | | # symbols.append(result['symbol']) |
| | | # fdata = JueJinApi.get_underlying_code(symbols) |
| | | # for k in fdata: |
| | | # item = (k, fdata[k]) |
| | | # print(item) |
| | | # f.write(f"{item}\n") |
| | | |
| | | # print(count) |
| | | # 加载涨停代码 |
| | | with open("D:\\文件传输\\交易\\日志文件\\2024-04-26_limit_up.log", mode='r', encoding='utf-8') as f: |
| | | data = f.readline() |
| | | datas = eval(data) |
| | | limit_up_codes = "000421,000559,000560,000608,000657,000698,000705,000799,000949,000952,000980,001301,001366,001376,002037,002305,002331,002339,002367,002455,002616,002633,002748,002759,002790,002795,002827,002862,002895,002910,002946,002968,002972,300175,300407,300758,300778,300829,300905,301209,301226,301301,301393,600211,600223,600230,600326,600580,600686,600727,600743,600763,600789,600805,600844,600865,600866,600984,601233,601333,603079,603127,603219,603225,603231,603311,603580,603659,603711,603739,603778,603823,603928,603968,605055,605169,605298" |
| | | |
| | | with open("datas/convertible_bonds_codes.txt", mode='r', encoding='utf-8') as f: |
| | | lines = f.readlines() |
| | | for line in lines: |
| | | if line: |
| | | data = eval(line) |
| | | code = data[1][-6:] |
| | | if code in limit_up_codes: |
| | | print(data[0], data[1]) |
| | |
| | | </div> |
| | | </div> |
| | | <div id="l2_screen"> |
| | | |
| | | <div> <span>量:</span> <input id="min-volume" /> - <input id="max-volume" /> </div> |
| | | <table style="width: auto;"> |
| | | <tr> |
| | | <td>量:</td> |
| | | <td> <input id="min-volume" /> - <input id="max-volume" /></td> |
| | | </tr> |
| | | <tr> |
| | | <td>索引:</td> |
| | | <td><textarea id="watch_indexes" style="border: #BBB solid 1px;" placeholder="索引用逗号分隔"></textarea></td> |
| | | </tr> |
| | | |
| | | </table> |
| | | |
| | | <div> <button class="btn" @click="l2_screen_click">确定</button> </div> |
| | | |
| | |
| | | |
| | | #l2_screen input{ |
| | | border: solid 1px #BBB; |
| | | border-radius: 4px; |
| | | border-radius: 2px; |
| | | width: 50px; |
| | | padding: 2px 5px; |
| | | } |
| | | #l2_screen table{ |
| | | width: auto; |
| | | } |
| | | |
| | | #l2_screen textarea{ |
| | | padding: 2px 5px; |
| | | width: 300px; |
| | | height: 50px; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | #l2_screen .btn{ |
| | | margin-top: 10px; |
| | | margin-left: 315px; |
| | | } |
| | | |
| | |
| | | #date{ |
| | | width: 100px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .cb_list_top{ |
| | | display: flex; |
| | | overflow-wrap: break-word; |
| | | word-wrap: break-word; |
| | | white-space: normal; |
| | | width: 97.4%; |
| | | flex-wrap: wrap; |
| | | padding: 10px; |
| | | background-color: black; |
| | | color: white; |
| | | |
| | | } |
| | | |
| | | .cb_list_top > div{ |
| | | display: block; |
| | | width: 180px; |
| | | margin-bottom: 5px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .cb_list_top button{ |
| | | |
| | | border-radius: 5px; |
| | | font-size: 12px; |
| | | padding: 1px 4px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .cb_list{ |
| | | margin: 10px 10px; |
| | | width: 100%; |
| | | } |
| | | |
| | | .cb_list table{ |
| | | border: solid 1px #EEE; |
| | | |
| | | } |
| | | |
| | | .cb_list table tr{ |
| | | |
| | | } |
| | | |
| | | .cb_list table tr td{ |
| | | border: none; |
| | | padding: 2px; |
| | | } |
| | | |
| | | .cb_list button{ |
| | | border-radius: 5px; |
| | | font-size: 12px; |
| | | padding: 1px 4px; |
| | | cursor: pointer; |
| | | } |
| | |
| | | <script src="js/vconsole.min.js"></script> |
| | | <script src="js/chart.js"></script> |
| | | <script src="js/chartjs-plugin-datalabels.min.js"></script> |
| | | <script src="js/md5.min.js"></script> |
| | | <style> |
| | | |
| | | </style> |
| | |
| | | <tr> |
| | | <td><span class="bold">板块</span></td> |
| | | <td class="budinggundong"> |
| | | <div class="scroll-y" style="height: 93px;;"> |
| | | <div class="scroll-y" style="height: 93px;"> |
| | | <span v-for="(item,i) in kpl_code_info.plate" class="label-style" |
| | | :class="{'red':item[4]}">{{item[1]}}</span> |
| | | :class="{'red':item[4]!=null}">{{item[1]}}<span |
| | | v-if="item[4]!=null">({{item[4][1]}}&{{item[4][2]}})</span></span> |
| | | </div> |
| | | </td> |
| | | </tr> |
| | |
| | | |
| | | <!-- 右侧 --> |
| | | |
| | | <div style="float: right; width:72%;" v-if="choose_code_info"> |
| | | <!-- 右侧固定位 --> |
| | | <div> |
| | | <table |
| | | style="float: right; width:100%; background: #EEE;height: 130px; max-height: 130px;min-height: 130px; overflow: hidden;"> |
| | | <thead></thead> |
| | | <tbody> |
| | | <tr style="display: none;"> |
| | | <td style="width: 10%;"><span class="bold">强度</span></td> |
| | | <td colspan="3"> |
| | | <div class="scroll-x" style="width: 670px;"> |
| | | <div style="display: inline-block; margin-right: 16px;" |
| | | v-for="(item,index) in choose_code_info.plat_strength"><span |
| | | class="num-style">{{item[1]}}</span><br><span |
| | | class="num-style">{{item[2]}}</span> |
| | | </div> |
| | | </div> |
| | | </td> |
| | | </tr> |
| | | |
| | | |
| | | |
| | | <tr> |
| | | <td><span class="bold">今天</span></td> |
| | | <td><span v-if="choose_code_info.today"> |
| | | <span class="red">【{{choose_code_info.today[0]}}】</span>| <span |
| | | class="num-style">{{choose_code_info.today[2]}}</span> |
| | | |
| | | 二级: |
| | | <span class="num-style"> |
| | | {{choose_code_info.industry}} |
| | | </span> |
| | | |
| | | </td> |
| | | </tr> |
| | | |
| | | |
| | | |
| | | |
| | | <tr> |
| | | <td><span class="bold">历史</span></td> |
| | | <td> |
| | | |
| | | |
| | | <span v-for="(item1,i1) in choose_code_info.code_records"> |
| | | <span class="num-style red">【{{item1[0]}}】</span>| <span |
| | | class="num-style">{{item1[2]}}</span><span |
| | | class="num-style">({{item1[1]}})</span> |
| | | |
| | | </span> |
| | | </td> |
| | | |
| | | |
| | | </tr> |
| | | <tr> |
| | | <td><span class="bold">板块</span></td> |
| | | <td> |
| | | <div class="scroll-x" style="width: 670px;"> |
| | | <div v-for="(item,i) in choose_code_info.plate" class="item"> |
| | | <span class="num-style line">{{item[1]}}</span> |
| | | <span class="num-style line">{{item[2]}}%</span> |
| | | </div> |
| | | |
| | | </div> |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot></tfoot> |
| | | </table> |
| | | <div style="float: right; width:100%;background: #cecece;height: 10px;"></div> |
| | | </div> |
| | | <!-- 右侧滚动表格 --> |
| | | <div class="outer-container scroll-y" style="float: right;"> |
| | | |
| | | <div class="daixuan" v-for="(item,i) in choose_code_info.code_list_info" |
| | | @click="select_code_level_2($event,i)"> |
| | | <!-- 一条信息 --> |
| | | <table :class="{'active':choose_code.second==item.code_info[0]}"> |
| | | <thead></thead> |
| | | <tbody> |
| | | <div> |
| | | <tr> |
| | | <td style="width: 10%;"><span class="bold" |
| | | :class="{'purple':item.code_info[11]>8}">{{item.code_info[11]}}%</span> |
| | | </td> |
| | | <td colspan="3"> |
| | | |
| | | <div> |
| | | <span v-if="item.code_info[2]==1"><img |
| | | src="./images/limit_up.png"></span> |
| | | <span v-if="item.code_info[2]==2"><img |
| | | src="./images/stop_up.png"></span> |
| | | <span class="num-style bold" |
| | | :class="{'green': item.code_info[0].indexOf('00')!=0&&item.code_info[0].indexOf('60')!=0 }">{{item.code_info[1]}}</span><span |
| | | class="num-card-red" |
| | | v-if="item.code_info[3]">{{item.code_info[3]}}</span><span |
| | | class="num-card-bule" |
| | | v-if="item.code_info[4]">{{item.code_info[4]}}</span> |
| | | <span v-if="item.code_info[5]" |
| | | class="score-card-color yellow">{{item.code_info[5]}}</span><span |
| | | class="num-card-black" |
| | | v-if="item.code_info[13]">{{item.code_info[13]}}</span> |
| | | <span class="num-card-pink" |
| | | v-if="item.code_info[14]">{{item.code_info[14]}}</span> |
| | | |
| | | </div> |
| | | <img src="./images/delete.png" alt="" |
| | | style="float: right;margin-right: -2px;" |
| | | @click="del_code_level_2(i)"> |
| | | <div><span |
| | | v-if="item.code_info[6]&& item.code_info[6]!='00:00:00'">涨停时间:<span |
| | | class="num-style red">{{item.code_info[6]}} </span></span>代码:<span |
| | | class="num-style">{{item.code_info[0]}}</span> 现价:<span |
| | | class="num-style red">{{item.code_info[12]}}元</span> 自由市值:<span |
| | | class="num-style red">{{item.code_info[9]}}</span></div> |
| | | <div>主力净值:<span |
| | | class="num-style">{{item.code_info[15]}}</span> 300W:<span |
| | | class="num-style">{{item.code_info[16]}}</span> 第一季度机构增仓:<span |
| | | class="num-style">{{item.code_info[17]}}</span></div> |
| | | </td> |
| | | |
| | | </tr> |
| | | <tr |
| | | v-if="item.code_info[0].indexOf('00')==0||item.code_info[0].indexOf('60')==0"> |
| | | <td><span class="bold">今天</span></td> |
| | | <td> |
| | | <span v-if="item.today"> |
| | | <span class="red">【{{item.today[0]}}】</span>| <span |
| | | class="num-style">{{item.today[2]}}</span> |
| | | |
| | | </span> |
| | | |
| | | 二级: |
| | | <span class="num-style"> |
| | | {{item.industry}} |
| | | </span> |
| | | |
| | | </td> |
| | | |
| | | |
| | | </tr> |
| | | <tr |
| | | v-if="item.code_info[0].indexOf('00')==0||item.code_info[0].indexOf('60')==0"> |
| | | <td><span class="bold">历史</span></td> |
| | | <td style="max-width: 650px;"> |
| | | <div style="display: flex;flex-wrap: wrap;border-width: 1px;"> |
| | | <span v-for="(item1,i1) in item.code_records"> |
| | | <span class="num-style red">【{{item1[0][0]}}】</span>| |
| | | <span v-for="(item2,i2) in item1[2]"> |
| | | <span>{{item2[0]}}</span><span |
| | | v-if="i2!=item1[2].length -1">、</span> |
| | | </span> |
| | | |
| | | <span class="num-style">({{item1[1]}})</span> |
| | | |
| | | </span> |
| | | </div> |
| | | </td> |
| | | |
| | | |
| | | </tr> |
| | | <tr |
| | | v-if="item.code_info[0].indexOf('00')==0||item.code_info[0].indexOf('60')==0"> |
| | | <td><span class="bold">板块</span></td> |
| | | <td> |
| | | <div class="scroll-x" style="width: 650px;"> |
| | | <div v-for="(item1,i1) in item.plate" class="item"> |
| | | <span class="num-style line" |
| | | style="display: block;">{{item1[1]}}</span> |
| | | <span class="num-style line" |
| | | style="display: block;">{{item1[2]}}%</span> |
| | | </div> |
| | | |
| | | </div> |
| | | </td> |
| | | |
| | | |
| | | </tr> |
| | | </div> |
| | | </tbody> |
| | | <tfoot></tfoot> |
| | | </table> |
| | | <div style="float: right; width:72%;"> |
| | | <div class="cb_list_top"> |
| | | <div v-for="item in cb_list_top" v-on:click="select_cb(item)" :class="{'red': cb_selected_code == item[0][0]}"> |
| | | <img v-if="item[3]" style="margin-right:5px;" src="./images/stop_up.png"> |
| | | <span>{{item[0][1]}}</span> |
| | | <span>({{item[0][0]}})</span> |
| | | <button v-on:click="add_to_ths(item[0][0])">查看</button> |
| | | </div> |
| | | |
| | | </div> |
| | | |
| | | <div v-for="item in cb_list" class="cb_list" :class="{'red': cb_selected_code == item[0][0]}"> |
| | | <table> |
| | | <tr><td>正股名称:{{item[1][1]}}({{item[1][0]}}) <button v-on:click="add_to_ths(item[1][0])">查看</button></td><td >转债名称:<span class="green">{{item[0][1]}}({{item[0][0]}})</span> <button v-on:click="add_to_ths(item[0][0])">查看</button></td></tr> |
| | | <tr><td>涨停时间:{{item[2]}}</td><td>---</td></tr> |
| | | <tr><td>最新涨幅:{{item[1][2][1]}}%</td><td>最新涨幅:{{item[0][2][1]}}%</td></tr> |
| | | </table> |
| | | </div> |
| | | |
| | | |
| | | </div> |
| | | |
| | |
| | | <div v-for="(item,i) in want_codes" class="item" |
| | | style="display: flex;width: 335px;margin-bottom: 15px;" v-if="item[8]==1"> |
| | | |
| | | <div><img :style="{'visibility':item[3]==1?'visiable':'hidden'}" style="margin-right:5px;" |
| | | <div> |
| | | <input type="checkbox" :checked="item[9]==1" |
| | | v-on:click="add_or_remove_forbidden($event,item[0])" /> |
| | | <img :style="{'visibility':item[3]==1?'visiable':'hidden'}" style="margin-right:5px;" |
| | | src="./images/stop_up.png"><span |
| | | :class="{'red': item[5],'green': item[0].indexOf('00')!=0&&item[0].indexOf('60')!=0 }">{{item[1]}}({{item[0]}})-{{item[2]}}-{{item[6]}}-{{item[7]}} |
| | | </span><span v-if="item[3]==1">(炸)</span> <span class="red" v-if="item[4]">*</span> </div> |
| | | </span><span v-if="item[3]==1">(炸)</span> <span class="red" v-if="item[4]">*</span> |
| | | </div> |
| | | <img v-if="item[2]==1" class="delete" src="./images/delete.png" |
| | | @click="delete_from_want_codes(i)"> |
| | | </div> |
| | |
| | | <div v-for="(item,i) in want_codes" class="item" |
| | | style="display: flex;width: 335px;margin-bottom: 15px;" v-if="item[8]==0"> |
| | | |
| | | <div><img :style="{'visibility':item[3]==1?'visiable':'hidden'}" style="margin-right:5px;" |
| | | <div><input type="checkbox" :checked="item[9]==1" /><img |
| | | :style="{'visibility':item[3]==1?'visiable':'hidden'}" style="margin-right:5px;" |
| | | src="./images/stop_up.png"><span |
| | | :class="{'red': item[5]}">{{item[1]}}({{item[0]}})-{{item[2]}}-{{item[6]}}-{{item[7]}} |
| | | </span><span v-if="item[3]==1">(炸)</span> <span class="red" v-if="item[4]">*</span> </div> |
| | |
| | | kpl_open_limit_up_count_rank:[], |
| | | // 大单买卖数量 |
| | | big_buy_order_count:0, |
| | | big_sell_order_count:0 |
| | | big_sell_order_count:0, |
| | | // 过滤的索引 |
| | | filter_indexes:[] |
| | | |
| | | }, |
| | | watch: { |
| | |
| | | } |
| | | http_util.get_l2_h_cancel_datas(app.code, app.operate_index, function(res) { |
| | | res = JSON.parse(res); |
| | | console.log("H撤數據",res) |
| | | if (res.code == 0) { |
| | | app.h_cancel_indexes = res.data; |
| | | } |
| | |
| | | }, |
| | | need_show: function(item) { |
| | | |
| | | if(app.filter_indexes.length>0){ |
| | | if(app.filter_indexes.indexOf(item[2][0])>=0) |
| | | { |
| | | return true; |
| | | }else{ |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | if(app.real_order_indexes.includes( item[2][0])){ |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | if (app.hidden_canceled && (item[2][6].indexOf('买撤') >= 0 || (item[2][8] != null && |
| | | item[2][8].indexOf("-") > 0))) { |
| | |
| | | app.refresh_l2_data(); |
| | | } |
| | | }); |
| | | |
| | | app.get_l2_cant_buy_reasons(app.origin_code); |
| | | http_util.get_open_limit_up_count_rank(null,function(res){ |
| | | res = JSON.parse(res); |
| | |
| | | }else{ |
| | | app.l2_max_volume=null; |
| | | } |
| | | watch_indexes_str = $("#watch_indexes").val(); |
| | | if(watch_indexes_str!=null&&watch_indexes_str.length>0){ |
| | | var final_indexes=[]; |
| | | var indexes = watch_indexes_str.split(","); |
| | | indexes.forEach(function(e){ |
| | | final_indexes.push(parseInt(e)); |
| | | }); |
| | | app.filter_indexes = final_indexes; |
| | | console.log("选中索引:",final_indexes); |
| | | }else{ |
| | | app.filter_indexes =[]; |
| | | } |
| | | |
| | | }, |
| | | fordbidden_buy:function(code){ |
| | |
| | | |
| | | console.log("socket请求", data) |
| | | |
| | | |
| | | var sign = http_util.get_sign(data); |
| | | data['sign'] = sign; |
| | | console.log("参数:",data); |
| | | pyjs.socket_request(JSON.stringify(data), function(result) { |
| | | console.log(result); |
| | | http_util.socket_request(JSON.stringify(data), function(result) { |
| | | console.log("撤单结果",result) |
| | | result = JSON.parse(result); |
| | | if (result.code == 0) { |
| | | // pyjs.show_info(type_desc +"成功"); |
| | | layer.msg(type_desc + "成功") |
| | | if(result.code ==0 ){ |
| | | layer.msg(type_desc + "成功"); |
| | | } |
| | | callback(result); |
| | | }); |
| | | |
| | | }, |
| | | |
| | | get_want_codes: function(plate, callback) { |
| | |
| | | |
| | | console.log(params_str) |
| | | |
| | | md5Hash = crypto.createHash("md5").update(params_str).digest("hex"); |
| | | md5Hash = md5(params_str); |
| | | return md5Hash; |
| | | }, |
| | | cancel_order: function(code, success) { |
| | |
| | | var params={} |
| | | http_util.http_request("/get_kpl_market_feelings", params, callback); |
| | | }, |
| | | get_cb_list(callback){ |
| | | var params={} |
| | | http_util.http_request("/get_cb_list", params, callback); |
| | | }, |
| | | |
| | | |
| | | |
New file |
| | |
| | | !function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((u=d(d(t,n),d(e,u)))<<o|u>>>32-o,r)}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function c(n,t){var r,e,o,u;n[t>>5]|=128<<t%32,n[14+(t+64>>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h<n.length;h+=16)c=l(r=c,e=f,o=i,u=a,n[h],7,-680876936),a=l(a,c,f,i,n[h+1],12,-389564586),i=l(i,a,c,f,n[h+2],17,606105819),f=l(f,i,a,c,n[h+3],22,-1044525330),c=l(c,f,i,a,n[h+4],7,-176418897),a=l(a,c,f,i,n[h+5],12,1200080426),i=l(i,a,c,f,n[h+6],17,-1473231341),f=l(f,i,a,c,n[h+7],22,-45705983),c=l(c,f,i,a,n[h+8],7,1770035416),a=l(a,c,f,i,n[h+9],12,-1958414417),i=l(i,a,c,f,n[h+10],17,-42063),f=l(f,i,a,c,n[h+11],22,-1990404162),c=l(c,f,i,a,n[h+12],7,1804603682),a=l(a,c,f,i,n[h+13],12,-40341101),i=l(i,a,c,f,n[h+14],17,-1502002290),c=g(c,f=l(f,i,a,c,n[h+15],22,1236535329),i,a,n[h+1],5,-165796510),a=g(a,c,f,i,n[h+6],9,-1069501632),i=g(i,a,c,f,n[h+11],14,643717713),f=g(f,i,a,c,n[h],20,-373897302),c=g(c,f,i,a,n[h+5],5,-701558691),a=g(a,c,f,i,n[h+10],9,38016083),i=g(i,a,c,f,n[h+15],14,-660478335),f=g(f,i,a,c,n[h+4],20,-405537848),c=g(c,f,i,a,n[h+9],5,568446438),a=g(a,c,f,i,n[h+14],9,-1019803690),i=g(i,a,c,f,n[h+3],14,-187363961),f=g(f,i,a,c,n[h+8],20,1163531501),c=g(c,f,i,a,n[h+13],5,-1444681467),a=g(a,c,f,i,n[h+2],9,-51403784),i=g(i,a,c,f,n[h+7],14,1735328473),c=v(c,f=g(f,i,a,c,n[h+12],20,-1926607734),i,a,n[h+5],4,-378558),a=v(a,c,f,i,n[h+8],11,-2022574463),i=v(i,a,c,f,n[h+11],16,1839030562),f=v(f,i,a,c,n[h+14],23,-35309556),c=v(c,f,i,a,n[h+1],4,-1530992060),a=v(a,c,f,i,n[h+4],11,1272893353),i=v(i,a,c,f,n[h+7],16,-155497632),f=v(f,i,a,c,n[h+10],23,-1094730640),c=v(c,f,i,a,n[h+13],4,681279174),a=v(a,c,f,i,n[h],11,-358537222),i=v(i,a,c,f,n[h+3],16,-722521979),f=v(f,i,a,c,n[h+6],23,76029189),c=v(c,f,i,a,n[h+9],4,-640364487),a=v(a,c,f,i,n[h+12],11,-421815835),i=v(i,a,c,f,n[h+15],16,530742520),c=m(c,f=v(f,i,a,c,n[h+2],23,-995338651),i,a,n[h],6,-198630844),a=m(a,c,f,i,n[h+7],10,1126891415),i=m(i,a,c,f,n[h+14],15,-1416354905),f=m(f,i,a,c,n[h+5],21,-57434055),c=m(c,f,i,a,n[h+12],6,1700485571),a=m(a,c,f,i,n[h+3],10,-1894986606),i=m(i,a,c,f,n[h+10],15,-1051523),f=m(f,i,a,c,n[h+1],21,-2054922799),c=m(c,f,i,a,n[h+8],6,1873313359),a=m(a,c,f,i,n[h+15],10,-30611744),i=m(i,a,c,f,n[h+6],15,-1560198380),f=m(f,i,a,c,n[h+13],21,1309151649),c=m(c,f,i,a,n[h+4],6,-145523070),a=m(a,c,f,i,n[h+11],10,-1120210379),i=m(i,a,c,f,n[h+2],15,718787259),f=m(f,i,a,c,n[h+9],21,-343485551),c=d(c,r),f=d(f,e),i=d(i,o),a=d(a,u);return[c,f,i,a]}function i(n){for(var t="",r=32*n.length,e=0;e<r;e+=8)t+=String.fromCharCode(n[e>>5]>>>e%32&255);return t}function a(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e<t.length;e+=1)t[e]=0;for(var r=8*n.length,e=0;e<r;e+=8)t[e>>5]|=(255&n.charCodeAt(e/8))<<e%32;return t}function e(n){for(var t,r="0123456789abcdef",e="",o=0;o<n.length;o+=1)t=n.charCodeAt(o),e+=r.charAt(t>>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return i(c(a(n=r(n)),8*n.length))}function u(n,t){return function(n,t){var r,e=a(n),o=[],u=[];for(o[15]=u[15]=void 0,16<e.length&&(e=c(e,8*n.length)),r=0;r<16;r+=1)o[r]=909522486^e[r],u[r]=1549556828^e[r];return t=c(o.concat(a(t)),512+8*t.length),i(c(u.concat(t),640))}(r(n),r(t))}function t(n,t,r){return t?r?u(t,n):e(u(t,n)):r?o(n):e(o(n))}"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:n.md5=t}(this); |
| | | //# sourceMappingURL=md5.min.js.map |
| | |
| | | app.get_kpl_market_feelings(); |
| | | } |
| | | }, 3000, 3000); |
| | | |
| | | setInterval(function() { |
| | | if (is_trade_time()||true) { |
| | | app.get_cb_list(); |
| | | } |
| | | }, 3000, 3000); |
| | | |
| | | |
| | | |
| | |
| | | trade_data: { |
| | | order: 0 |
| | | }, |
| | | cb_list:[],// 可转债列表 |
| | | cb_list_top:[], |
| | | cb_selected_code:'', |
| | | // 代码的开盘啦涨停原因 |
| | | kpl_limit_up_reason: '', |
| | | default_score_data: { |
| | |
| | | app.trade_data = res.data.trade_data |
| | | } |
| | | res.data.kpl_code_info.plate.forEach(function(e) { |
| | | var s = false; |
| | | var s = null; |
| | | if (app.first_info.limit_up_reason_statistic) { |
| | | for (var i = 0; i < app.first_info |
| | | .limit_up_reason_statistic |
| | | .length; i++) { |
| | | if (app.first_info |
| | | .limit_up_reason_statistic[ |
| | | i][0] == e[1]) { |
| | | s = true; |
| | | var limit_up_info = app.first_info.limit_up_reason_statistic[i]; |
| | | if (limit_up_info[0] == e[1]) { |
| | | s = limit_up_info; |
| | | break; |
| | | } |
| | | } |
| | |
| | | console.log("板块请求结果:", res); |
| | | if (res.code == 0) { |
| | | res.data.plate.forEach(function(e) { |
| | | var s = false; |
| | | var s = null; |
| | | if (app.first_info.limit_up_reason_statistic) { |
| | | for (var i = 0; i < app.first_info |
| | | .limit_up_reason_statistic |
| | |
| | | if (app.first_info |
| | | .limit_up_reason_statistic[ |
| | | i][0] == e[1]) { |
| | | s = true; |
| | | s = app.first_info.limit_up_reason_statistic[i]; |
| | | break; |
| | | } |
| | | } |
| | |
| | | |
| | | } |
| | | }); |
| | | }, |
| | | add_or_remove_forbidden:function(event,code){ |
| | | |
| | | var el = event.currentTarget; |
| | | var checked = $(el).is(':checked'); |
| | | console.log(code, checked); |
| | | if(checked){ |
| | | http_util.do_action_for_code(code,'',0,function(res){ |
| | | |
| | | }); |
| | | }else{ |
| | | http_util.do_action_for_code(code,'',1,function(res){ |
| | | |
| | | }); |
| | | } |
| | | |
| | | }, |
| | | get_cb_list:function(){ |
| | | http_util.get_cb_list(function(res){ |
| | | res = JSON.parse(res); |
| | | if(res.code==0){ |
| | | app.cb_list = res.data; |
| | | var arr= new Array(); |
| | | arr = arr.concat(res.data); |
| | | app.cb_list_top = arr; |
| | | app.set_selected_cb_top(); |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | set_selected_cb_top:function(){ |
| | | var temp_list=app.cb_list; |
| | | for(var i=0;i<temp_list.length;i++){ |
| | | if(temp_list[i][0][0] == app.cb_selected_code){ |
| | | var data = temp_list[i]; |
| | | temp_list.splice(i, 1); |
| | | temp_list.unshift(data); |
| | | app.cb_list = temp_list; |
| | | break; |
| | | } |
| | | } |
| | | }, |
| | | |
| | | select_cb:function(data){ |
| | | app.cb_selected_code = data[0][0]; |
| | | this.set_selected_cb_top(); |
| | | |
| | | |
| | | }, |
| | | add_to_ths:function(code){ |
| | | pyjs.add_code_to_ths(code); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | |
| | | app.get_jingxuan_data(app.jingxuan_data_type); |
| | | app.get_limit_up_list(app.code, false); |
| | | app.get_kpl_market_feelings(); |
| | | app.get_cb_list(); |
| | | } |
| | | |
| | | $(".market .child-title").click(function() { |
| | |
| | | |
| | | def __socket_request(self, text, callback_info): |
| | | try: |
| | | print("socket請求:", text) |
| | | result = network_util.socket_request(text) |
| | | print("请求结果:", result) |
| | | self.signal_request.emit(callback_info[0], callback_info[1], result) |
| | |
| | | import time |
| | | from urllib.parse import parse_qs, urlparse |
| | | |
| | | from convertible_bonds.main import JueJinUtil |
| | | from juejin_core import JueJinApi |
| | | from kpl import kpl_util, kpl_api |
| | | from kpl.kpl_data_manager import KPLLimitUpDataManager |
| | |
| | | |
| | | elif url.startswith("/get_kpl_market_feelings"): |
| | | return cls.__get_kpl_market_feelings() |
| | | elif url.startswith("/get_cb_list"): |
| | | # 获取可转债的列表 |
| | | return cls.get_cb_list() |
| | | |
| | | return None, False |
| | | |
| | |
| | | return json.dumps( |
| | | {"code": 0, "data": fdata}), True |
| | | |
| | | __cb_codes_list = None # 所有可转债数据 |
| | | __pre_price_dict = {} # 昨日收盘价 |
| | | |
| | | # 获取可转债的列表 |
| | | @classmethod |
| | | def get_cb_list(cls): |
| | | # 获取所有可转债列表 |
| | | if not cls.__cb_codes_list: |
| | | cls.__cb_codes_list = JueJinUtil.get_all_convertible_bonds_codes() |
| | | # 获取昨日收盘价 |
| | | symbols = [x[0][0] for x in cls.__cb_codes_list] |
| | | symbols.extend([x[1] for x in cls.__cb_codes_list]) |
| | | # 获取现价 |
| | | results = JueJinApi.get_gp_latest_info(symbols, fields='symbol,pre_close') |
| | | cls.__pre_price_dict = {x['symbol']: x['pre_close'] for x in results} |
| | | |
| | | # 获取涨停列表 |
| | | records = KPLLimitUpDataManager().get_limit_up_history_datas() |
| | | currents = KPLLimitUpDataManager().get_limit_up_current_datas() |
| | | current_codes = [d[0] for d in currents] |
| | | record_codes = [d[0] for d in records] |
| | | record_map = {} |
| | | for r in records: |
| | | record_map[r[0]] = r |
| | | # 格式[([转债代码,转债名称, (现价,涨幅)],[正股代码,正股名称,(现价,涨幅)],正股涨停时间,是否炸板)] |
| | | datas = [] |
| | | for b in cls.__cb_codes_list: |
| | | code = b[1].split(".")[1] |
| | | if code in record_codes: |
| | | if record_map[code][4] != '首板': |
| | | continue |
| | | datas.append( |
| | | [[b[0][0], b[0][1], None], [b[1], record_map[code][1], None], tool.time_format(record_map[code][2]), |
| | | code not in current_codes]) |
| | | # 获取所有的涨幅 |
| | | symbols = [] |
| | | for d in datas: |
| | | symbols.append(d[0][0]) |
| | | symbols.append(d[1][0]) |
| | | # 获取当前 |
| | | current_infos = JueJinApi.get_gp_current_info(symbols, fields='symbol,price') |
| | | rate_dict = {x['symbol']: (x['price'], round( |
| | | (x['price'] - cls.__pre_price_dict[x['symbol']]) * 100 / cls.__pre_price_dict[x['symbol']], 2)) for x in |
| | | current_infos} |
| | | for d in datas: |
| | | d[0][2] = rate_dict[d[0][0]] |
| | | d[1][2] = rate_dict[d[1][0]] |
| | | d[0][0] = d[0][0].split('.')[1] |
| | | d[1][0] = d[1][0].split('.')[1] |
| | | datas.sort(key=lambda x: int(x[2].replace(":","")), reverse=True) |
| | | |
| | | # 获取今日正股涨停的可转债列表 |
| | | return json.dumps( |
| | | {"code": 0, "data": datas}), True |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | codes = ["002523", "603095"] |
| | | datas = LocalKanPanNetworkDelegate.get_kpl_market_feelings(codes) |
| | | |
| | | datas = LocalKanPanNetworkDelegate.get_cb_list() |
| | | print(datas) |
| | |
| | | 601766 |
| | | 600866 |
| | | 600984 |
| | | 000705 |
| | | 000980 |
| | |
| | | [config] |
| | | stay_on_top = 1 |
| | | window_info = [[-1711, 194, 1280, 800], [1473, 621, 320, 195]] |
| | | xgb_window_info = [-71, 121, 1046, 885] |
| | | xgb_window_info = [-2354, 86, 1920, 1017] |
| | | window_watch_float_info = [146, 419, 435, 220] |
| | | window_tick_info = [-1799, 324, 1223, 665] |
| | | kp_second_window_info = [130, 295, 730, 974] |
| | | window_tick_info = [280, 81, 800, 1000] |
| | | kp_second_window_info = [-1907, -8, 1920, 1017] |
| | | code_attribute_window_info = [-650, 315, 291, 278] |
| | | client = hxh |
| | | float_frame_auto_focus = 1 |
| | |
| | | |
| | | |
| | | # 获取涨停价 |
| | | def get_limit_up_price(price): |
| | | price = decimal.Decimal(str(price)) * decimal.Decimal("1.1") |
| | | def get_limit_up_price(price, max_rate=0.1): |
| | | price = decimal.Decimal(str(price)) * decimal.Decimal(f"{round(1 + max_rate, 1)}") |
| | | price = price.quantize(decimal.Decimal("0.00"), decimal.ROUND_HALF_UP) |
| | | return price |
| | | |
| | |
| | | |
| | | |
| | | def get_now_date_str(format="%Y-%m-%d"): |
| | | # TODO 测试 |
| | | return datetime.datetime.now().strftime(format) |
| | | |
| | | |