| | |
| | | import array |
| | | import ctypes |
| | | import json |
| | | import queue |
| | | import random |
| | | import socket |
| | | import struct |
| | | import sys |
| | |
| | | import cv2 |
| | | import win32con |
| | | import win32gui |
| | | from matplotlib.animation import FuncAnimation |
| | | |
| | | import constant |
| | | import juejin_data_export |
| | |
| | | import tool |
| | | import requests |
| | | |
| | | from sell_processor import TickDataProcess |
| | | |
| | | APP_TITLE = "卖票看板" |
| | | APP_ICON = "" |
| | | SOCKET_PORT = 9001 |
| | | SOCKET_PORT = 11008 |
| | | HTTP_PORT = 9004 |
| | | |
| | | |
| | |
| | | # 代码 |
| | | label = wx.StaticText(self, label="目标代码:") |
| | | boxsier.Add(label, 0, wx.LEFT | wx.RIGHT, 5) |
| | | self.edit_codes = wx.TextCtrl(self, size=(150, 150), style=wx.TE_MULTILINE) |
| | | |
| | | # 自动填充按钮 |
| | | self.btn_position = wx.Button(self, label='填充持仓代码') |
| | | self.btn_position.Bind(wx.EVT_BUTTON, self.__fill_position_codes) |
| | | boxsier.Add(self.btn_position, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) |
| | | |
| | | self.edit_codes = wx.TextCtrl(self, size=(150, 120), style=wx.TE_MULTILINE) |
| | | boxsier.Add(self.edit_codes, 0, wx.LEFT | wx.RIGHT, 5) |
| | | |
| | | # 确定按钮 |
| | | ID_SURE = wx.NewId() |
| | | ID_SURE = random.randint(1000, 1200) |
| | | self.btn_sure = wx.Button(self, label='确定', id=ID_SURE) |
| | | self.btn_sure.Bind(wx.EVT_BUTTON, self.__sure_btn) |
| | | boxsier.Add(self.btn_sure, 0, wx.LEFT | wx.TOP, 5 | 5) |
| | |
| | | if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 |
| | | self.Close() |
| | | toastone.Destroy() |
| | | |
| | | @classmethod |
| | | def get_position_codes(cls): |
| | | def request_position_codes(): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = (constant.SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | try: |
| | | data = socket_util.encryp_client_params_sign( |
| | | {"type": "common", "data": {"ctype": "get_position_codes"}}) |
| | | client.send(socket_util.load_header(json.dumps(data).encode("utf-8"))) |
| | | result_str, header_str = socket_util.recv_data(client) |
| | | return result_str |
| | | finally: |
| | | client.close() |
| | | result_str = request_position_codes() |
| | | result = json.loads(result_str) |
| | | if result["code"] == 0: |
| | | return result["data"] |
| | | else: |
| | | raise Exception(result["msg"]) |
| | | |
| | | # 填充持仓代码 |
| | | def __fill_position_codes(self, event): |
| | | def request_position_codes(): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = (constant.SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | try: |
| | | data = socket_util.encryp_client_params_sign( |
| | | {"type": "common", "data": {"ctype": "get_position_codes"}}) |
| | | client.send(socket_util.load_header(json.dumps(data).encode("utf-8"))) |
| | | result_str, header_str = socket_util.recv_data(client) |
| | | return result_str |
| | | finally: |
| | | client.close() |
| | | try: |
| | | codes = self.get_position_codes() |
| | | if codes: |
| | | self.edit_codes.SetValue("\n".join(codes)) |
| | | else: |
| | | raise Exception("无持仓") |
| | | except Exception as e: |
| | | show_warning(str(e), None) |
| | | |
| | | |
| | | class FobiddenCodesFrame(wx.Frame): |
| | |
| | | |
| | | # 格式为:(上边距,宽度,高度) |
| | | rect_ = setting.get_ths_auto_code_rect() |
| | | scale = 1.5 |
| | | # 测试 |
| | | scale = 1 if constant.IS_TEST else 1.5 |
| | | if len(rect_) > 3: |
| | | scale = rect_[3] |
| | | width = int((rect[2] - rect[0]) * scale) |
| | |
| | | def __request(cls, data_json): |
| | | socket_util.encryp_client_params_sign(data_json) |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = (constant.SERVER_HOST, 10009) # server地址和端口号(最好是10000以后) |
| | | ip_port = (constant.SERVER_HOST, 11009) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | client.send(socket_util.load_header(json.dumps(data_json).encode("utf-8"))) |
| | | result_str, header = socket_util.recv_data(client) |
| | |
| | | |
| | | |
| | | class TickFrame(wx.Frame): |
| | | mark_lines = {} |
| | | |
| | | def __init__(self): |
| | | '''构造函数''' |
| | | wx.Frame.__init__(self, None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE, |
| | |
| | | self.Bind(wx.EVT_SIZE, self.OnResize) |
| | | self.panels = [] |
| | | self.scroll = None |
| | | self.mark_lines = {} |
| | | self.col = 1 |
| | | self.ratio = 0.63 |
| | | 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.Layout() |
| | | # self.boxsier.Fit(self.scroll) |
| | |
| | | pannel.BackgroundColour = wx.Colour(0, 0, 0) |
| | | self.panels.append(pannel) |
| | | self.boxsier.Add(pannel) |
| | | code = codes_name[i][0] |
| | | 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 |
| | |
| | | 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): |
| | | # 删除之前的线 |
| | | if title in self.mark_lines: |
| | | if self.mark_lines.get(title): |
| | | line = self.mark_lines.get(title).get("mouse") |
| | | if line is not None: |
| | | line.remove() |
| | | self.mark_lines.get(title).pop("mouse") |
| | | else: |
| | | self.mark_lines[title] = {} |
| | | try: |
| | | line = axes2.axhline(event.ydata, linestyle='-', color='white', lw=0.5) |
| | | self.mark_lines[title]["mouse"] = line |
| | | axes2.figure.canvas.draw() |
| | | except: |
| | | pass |
| | | self.set_mouse_data(event.xdata, event.ydata, code, axes) |
| | | |
| | | def clear_mouse_line(event): |
| | | print("clear_mouse_line") |
| | | if title in self.mark_lines: |
| | | if self.mark_lines.get(title): |
| | | line = self.mark_lines.get(title).get("mouse") |
| | | 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: |
| | | line.remove() |
| | | self.mark_lines.get(title).pop("mouse") |
| | | axes2.figure.canvas.draw() |
| | | for l in line: |
| | | l.remove() |
| | | self.mark_lines.get(code).pop("mouse") |
| | | axes.figure.canvas.draw() |
| | | |
| | | def close_canvas(event): |
| | | print("关闭", title) |
| | |
| | | # 获取平开价 |
| | | extra = 0 # (tool.get_limit_up_price(price)-decimal.Decimal(price))*decimal.Decimal(0.02) |
| | | |
| | | axes.set_ylim(tool.get_limit_down_price(price) - extra, tool.get_limit_up_price(price) + extra) |
| | | 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) |
| | | # 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)) |
| | |
| | | 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'现价:0.0 涨幅:0.00% \n留:0%', fontsize=10, color='white') |
| | | axes2.text(-1, -11.5, r'现价:0.0 涨幅:0.00% \n留:0%', fontsize=10, color='white') |
| | | axes2.text(1, 11.5, r'现价:0.0 涨幅:0.00% \n留:0%', fontsize=15, color='red') |
| | | axes2.text(-1, -11.5, r'现价:0.0 涨幅:0.00% \n留:0%', fontsize=15, color='red') |
| | | |
| | | axes2.spines['top'].set_visible(False) |
| | | axes.spines['top'].set_visible(False) |
| | |
| | | axes.spines['bottom'].set_visible(False) |
| | | |
| | | # 中轴线加粗 |
| | | hline = axes2.axhline(0, linestyle='-', color='firebrick', lw=2) |
| | | hline = axes2.axhline(0, linestyle='-', color='firebrick', lw=2, zorder=1) |
| | | |
| | | # 设置坐标轴标记点为黑色 |
| | | axes.tick_params(axis='x', colors='black') |
| | | axes.tick_params(axis='x', colors='firebrick') |
| | | axes.tick_params(axis='y', colors='black') |
| | | axes2.tick_params(axis='x', colors='black') |
| | | axes2.tick_params(axis='x', colors='firebrick') |
| | | axes2.tick_params(axis='y', colors='black') |
| | | |
| | | return (axes2, line, average_line_1m, average_line, axes) |
| | | def update_data(i): |
| | | print("更新数据:", i) |
| | | |
| | | return axes2, line, average_line_1m, average_line, axes |
| | | |
| | | def __show_top(self, event): |
| | | if event.Selection: |
| | |
| | | finally: |
| | | time.sleep(3) |
| | | |
| | | t1 = threading.Thread(target=lambda: request(code), daemon=True) |
| | | t1 = threading.Thread(target=lambda: request(code), daemon=True) |
| | | t1.start() |
| | | return t1 |
| | | |
| | | |
| | | # 绘图管理器 |
| | | class DrawManager: |
| | | X_RANGE_MINIUTES = 60 |
| | | X_DATA_MINIUTES = 56 |
| | | 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 add_sell_point(cls, code, time_str, rate): |
| | | if code not in cls.sell_points_dict: |
| | | cls.sell_points_dict[code] = queue.Queue() |
| | | # 暂时注释掉 |
| | | # cls.sell_points_dict[code].put_nowait((cls.get_x_time_as_seconds(time_str), rate)) |
| | | |
| | | @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): |
| | |
| | | for data in results: |
| | | datas.append(juejin_core.parse_tick(data)) |
| | | # 保存数据 |
| | | last_time = time_range[0] |
| | | last_time = None |
| | | for data in datas: |
| | | # 09:25:00之前的数据不保存 |
| | | created_at = data["created_at"].strftime("%Y-%m-%d %H:%M:%S") |
| | | time_ = created_at[-8:] |
| | | if tool.trade_time_sub(time_, "09:25:00") < 0: |
| | | time_s = int(time_.replace(":", "")) |
| | | if time_s < int("092500") or time_s > int("150000"): |
| | | continue |
| | | if tool.trade_time_sub(time_, "15:00:00") > 0: |
| | | continue |
| | | if tool.trade_time_sub(time_, "11:30:00") > 0 and tool.trade_time_sub(time_, "13:00:00") < 0: |
| | | if int("113000") < time_s < int("130000"): |
| | | continue |
| | | |
| | | # 不是今天的数据不保存 |
| | | if day != created_at[:10]: |
| | | continue |
| | | # 每隔15s保存一次 |
| | | if last_time and tool.trade_time_sub(created_at[-8:], last_time) >= 15: |
| | | if last_time is None or tool.trade_time_sub(time_, last_time) >= 15: |
| | | last_time = created_at[-8:] |
| | | codeDataManager.save_data(data) |
| | | |
| | | def init_code_datas(self): |
| | | |
| | | global code_datas |
| | | global max_min_prices |
| | | codeDataManager = code_data_manager.CodeDataManager() |
| | |
| | | max_min_prices[data[0]] = (data[1], data[2]) |
| | | |
| | | for code in codes: |
| | | # 清除Y轴最大振幅 |
| | | if code in self.last_max_rate_dict: |
| | | self.last_max_rate_dict.pop(code) |
| | | # 加载历史数据 |
| | | code_datas[code] = [] |
| | | old_datas = codeDataManager.get_datas(code) |
| | |
| | | min_time = "11:30:00" |
| | | |
| | | min_time = tool.trade_time_add_second(min_time, 0 - DrawManager.X_DATA_MINIUTES * 60) |
| | | # 如果最小时间小于9:25则取9:25 |
| | | if int(min_time.replace(":", "")) < int("092500"): |
| | | min_time = "09:25:00" |
| | | |
| | | ranges = codeDataManager.get_lack_datas_time_range(old_datas, min_time) |
| | | # TODO 测试注释 |
| | | # if len(ranges) > 0: |
| | | # self.__load_lack_datas(code, ranges) |
| | | # old_datas = codeDataManager.get_datas(code) |
| | | old_datas = [] |
| | | |
| | | latest_time = min_time |
| | | if old_datas: |
| | | latest_time = old_datas[-1]['created_at'][-8:] |
| | | |
| | | now_time_str = tool.get_now_time_str() |
| | | if tool.trade_time_sub(now_time_str, "15:00:00") > 0: |
| | | now_time_str = "15:00:00" |
| | | |
| | | if tool.trade_time_sub(now_time_str, latest_time) > 15: |
| | | # 加载到当前时间 |
| | | if ranges: |
| | | ranges.append((ranges[-1][1], tool.get_now_time_str())) |
| | | else: |
| | | ranges.append((latest_time, tool.get_now_time_str())) |
| | | |
| | | if len(ranges) > 0: |
| | | self.__load_lack_datas(code, ranges) |
| | | old_datas = codeDataManager.get_datas(code) |
| | | # old_datas = [] |
| | | if old_datas: |
| | | code_datas[code].extend(old_datas) |
| | | # self.update(code, code_datas[code]) |
| | |
| | | |
| | | @classmethod |
| | | def __format_max_rate(cls, max_rate): |
| | | PERCENT_RATE = 1 |
| | | line_count = 0 |
| | | if max_rate % 0.6 < 0.0001: |
| | | line_count = int(round(max_rate // 0.6)) |
| | | if max_rate % PERCENT_RATE < 0.0001: |
| | | line_count = int(round(max_rate // PERCENT_RATE)) |
| | | else: |
| | | line_count = int(round(max_rate // 0.6)) + 1 |
| | | return line_count * 0.6, 0.6 |
| | | 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): |
| | |
| | | yticks_labels.append("") |
| | | axes2.set_ylabel(u'') |
| | | # 设置纵轴的值的范围 |
| | | axes2.set_ylim(0 - max_rate * (1), max_rate * (1)) |
| | | axes.set_ylim((100 - max_rate) * price / 100, (100 + max_rate) * price / 100) |
| | | 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.set_yticks(yticks) |
| | | axes.set_yticklabels(yticks_labels) |
| | | # axes.axhline(0, color='firebrick', linewidth=2) |
| | | |
| | | # 设置纵坐标数值颜色 |
| | | for i in range(0, line_count): |
| | | axes.get_yticklabels()[i].set_color("green") |
| | | # 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") |
| | | # 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") |
| | | # axes.get_yticklabels()[i].set_color("red") |
| | | axes2.get_yticklabels()[i].set_color("red") |
| | | |
| | | @classmethod |
| | |
| | | |
| | | # 更新数据 |
| | | def __update_data(self, code, axes, datas, pre_price, y_max_rate=10.5, cost_rate=None): |
| | | def get_time_as_seconds(created_at): |
| | | time_ = created_at[-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 |
| | | |
| | | def seconds_2_time_str(seconds): |
| | | seconds += 9 * 3600 + 60 * 30 |
| | | if seconds > 11 * 3600 + 60 * 30: |
| | | seconds += 90 * 60 |
| | | h = seconds // 3600 |
| | | m = seconds % 3600 // 60 |
| | | s = seconds % 60 |
| | | return "{0:0>2}:{1:0>2}:{2:0>2}".format(h, m, s) |
| | | def on_pick(event): |
| | | ind = event.ind[0] |
| | | offset = event.artist.get_offsets()[ind] |
| | | x = offset[0] |
| | | y = offset[1] |
| | | TickFrame.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: |
| | |
| | | ys_average_rate_1m = [] |
| | | ys_average_rate = [] |
| | | for data in datas: |
| | | xs.append(get_time_as_seconds(data["created_at"])) |
| | | 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) |
| | |
| | | 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(get_time_as_seconds(datas[0]["created_at"]), get_time_as_seconds(end_x)) |
| | | # 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)) |
| | | |
| | | # if len(xs) < 2 or xs[-1] - xs[0] < 30 * 60: |
| | | # axes[0].set_xlim(xs[0], xs[0] + 30 * 60) |
| | | # else: |
| | | # axes[0].set_xlim(xs[0], xs[-1]) |
| | | xms = axes[0].get_xlim() |
| | | yms = axes[0].get_ylim() |
| | | 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) |
| | | # 暂时不设置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("{}% \n留:{}".format(round(datas[-1]["rate"] * 100, 2), '无持仓' if self.cost_rate_dict.get( |
| | | code) is None else f"{self.cost_rate_dict.get(code)}%")) |
| | | texts[1].set_text("{}".format(datas[-1]["created_at"].split(" ")[1])) |
| | | texts[0].set_x(xms[1] - 80) |
| | | texts[0].set_y(yms[1] + 0.5) |
| | | 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] - 1.5) |
| | | texts[1].set_y(yms[0] - yms[1] / 9) |
| | | |
| | | # 删除之前 |
| | | if code in self.lines: |
| | |
| | | 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:] |
| | | # datas = datas[0 - self.X_DATA_MINIUTES * 20:] |
| | | # 修正量数据 |
| | | last_info = None |
| | | for i in range(1, len(datas)): |
| | |
| | | self.frame.scrollTo(index) |
| | | break |
| | | except Exception as e: |
| | | # logging.exception(e) |
| | | # print(str(e)) |
| | | pass |
| | | time.sleep(0.005) |
| | |
| | | def __show_main_frame(self): |
| | | self.frame.Show() |
| | | |
| | | def __init_data(self): |
| | | try: |
| | | codes = CodesSettingFrame.get_position_codes() |
| | | if codes: |
| | | juejin_core.GPCodeManager().set_codes(codes) |
| | | except: |
| | | pass |
| | | |
| | | def OnInit(self): |
| | | self.SetAppName(APP_TITLE) |
| | | self.__init_data() |
| | | self.frame = TickFrame() |
| | | self.floatFrame = FloatFrame() |
| | | # self.floatFrame = FloatFrame() |
| | | global_datas["tickFrame"] = self.frame |
| | | global_datas["floatFrame"] = self.floatFrame |
| | | # # 测试 |
| | | # global_datas["floatFrame"].Show() |
| | | # global_datas["floatFrame"] = self.floatFrame |
| | | |
| | | t1 = threading.Thread(target=lambda: self.__refresh()) |
| | | # 后台运行 |
| | | t1.setDaemon(True) |
| | | t1.start() |
| | | self.__show_main_frame() |
| | | |
| | | return True |
| | | |
| | |
| | | last_time = code_datas[code][-1]["created_at"].split(" ")[1] |
| | | else: |
| | | last_time = code_datas[code][-1]["created_at"].strftime("%H:%M:%S") |
| | | if tool.trade_time_sub(create_time, "09:30:00") < 0: |
| | | TickDataProcess.init_origin_price(code, data['price'], data['rate'] * 100) |
| | | else: |
| | | if TickDataProcess.process_tick_data(code, create_time, data['price'], data['rate'] * 100): |
| | | drawManager.add_sell_point(code, create_time, data['rate'] * 100) |
| | | # 如果相差15s就添加进去 |
| | | if last_time is None or tool.trade_time_sub(create_time, last_time) >= 15: |
| | | code_datas[code].append(data) |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | # app = mainApp() |
| | | # app.MainLoop() |
| | | # ocr_ths_code() |
| | | SocketApiUtil.get_cost_price("002207") |
| | | app = mainApp() |
| | | app.MainLoop() |