New file |
| | |
| | | import torch |
| | | import torch.nn as nn |
| | | |
| | | print(torch.__version__) |
| | | print(torch.cuda.is_available()) |
| | | |
| | | |
| | | # 创建网络 |
| | | class CNN(torch.nn.Module): |
| | | def __init__(self): |
| | | super(CNN, self).__init__() |
| | | self.conv = nn.Sequential( |
| | | # [BATCH_SIZE, 1, 28, 28] |
| | | # (通道大小,特征图数量,卷积核大小,步长,边缘填充像素) |
| | | nn.Conv2d(1, 32, 5, 1, 2), |
| | | nn.ReLU(), |
| | | nn.MaxPool2d(2), |
| | | # [BATCH_SIZE, 32, 14, 14] |
| | | nn.Conv2d(32, 64, 5, 1, 2), |
| | | # [BATCH_SIZE, 64, 14, 14] |
| | | nn.ReLU(), |
| | | nn.MaxPool2d(2) |
| | | # [BATCH_SIZE, 64, 7, 7] |
| | | ) |
| | | self.fc = nn.Linear(64 * 7 * 7, 10) |
| | | |
| | | def forward(self, x): |
| | | x = self.conv(x) |
| | | x = x.view(x.size(0), -1) |
| | | y = self.fc(x) |
| | | return y |
| | | |
| | | |
| | | # 评估函数 |
| | | def accuracy(predictions, labels): |
| | | pred = torch.max(predictions.data, 1)[1] |
| | | rights = pred.eq(labels.data.view_as(pred)).sum() |
| | | return rights, len(labels) |
| | | |
| | | |
| | | def __train(): |
| | | net = CNN() |
| | | # 损失函数 |
| | | criterion = nn.CrossEntropyLoss() |
| | | #优化器 |
| | | optimizer = torch.optim.Adam(net.parameters(),lr=0.001) |
| | | num_epochs= 10 |
| | | # 开始循环训练 |
| | | for epoch in range(num_epochs): |
| | | pass |
New file |
| | |
| | | import os |
| | | import time |
| | | |
| | | from PIL import Image |
| | | import torch |
| | | from torchvision import transforms |
| | | import cnn |
| | | import matplotlib.pyplot as plt |
| | | |
| | | |
| | | # 分隔图片 |
| | | def __split_img_for_cnn(img): |
| | | # 切割图片 |
| | | pass |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | path = 'C:/Users/Administrator/Desktop/ocr/codes/' |
| | | imgs = [] |
| | | labels = [] |
| | | for name in sorted(os.listdir(path)): |
| | | if name.find(".png") < 0: |
| | | continue |
| | | img = Image.open(path + name).convert('L') |
| | | img = transforms.ToTensor()(img) |
| | | imgs.append(img) |
| | | labels.append(int(name[0])) |
| | | imgs = torch.stack(imgs, 0) |
| | | # %% 加载模型 |
| | | model = cnn.CNN() |
| | | model.load_state_dict(torch.load('model.pt', map_location=torch.device('cpu'))) |
| | | model.eval() |
| | | for i in range(0, 10): |
| | | start_time = time.time() |
| | | with torch.no_grad(): |
| | | output = model(imgs) |
| | | # %% 打印结果 |
| | | pred = output.argmax(1) |
| | | true = torch.LongTensor(labels) |
| | | print(pred) |
| | | print(true) |
| | | print("识别时间:", (time.time() - start_time) * 1000) |
| | | |
| | | # %% 结果显示 |
| | | # plt.figure(figsize=(10, 4)) |
| | | # for i in range(len(imgs)): |
| | | # plt.subplot(2, 5, i + 1) |
| | | # plt.title(f'pred {pred[i]} | true {true[i]}') |
| | | # plt.axis('off') |
| | | # plt.imshow(imgs[i].squeeze(0), cmap='gray') |
| | | # # plt.savefig('test.png') |
| | | # plt.show() |
New file |
| | |
| | | import torch |
| | | import torch.nn as nn |
| | | import torchvision.datasets as dataset |
| | | import torchvision.transforms as transforms |
| | | import torch.utils.data as data_utils |
| | | import matplotlib.pyplot as plt |
| | | |
| | | print(torch.__version__) |
| | | print(torch.cuda.is_available()) |
| | | |
| | | # 获取数据集 |
| | | train_data = dataset.MNIST(root="D:\\ml", |
| | | train=True, |
| | | transform=transforms.ToTensor(), |
| | | download=True |
| | | ) |
| | | test_data = dataset.MNIST(root="D:\\ml", |
| | | train=False, |
| | | transform=transforms.ToTensor(), |
| | | download=False |
| | | ) |
| | | train_loader = data_utils.DataLoader(dataset=train_data, batch_size=100, shuffle=True) |
| | | test_loader = data_utils.DataLoader(dataset=test_data, batch_size=100, shuffle=True) |
| | | |
| | | |
| | | |
| | | cnn = CNN() |
| | | # cnn = cnn.cuda() |
| | | |
| | | # 损失函数 |
| | | los = torch.nn.CrossEntropyLoss() |
| | | |
| | | # 优化函数 |
| | | optime = torch.optim.Adam(cnn.parameters(), lr=0.01) |
| | | |
| | | train_targets = train_data.targets |
| | | plt.figure(figsize=(9, 9)) |
| | | for i in range(9): |
| | | plt.subplot(3, 3, i + 1) |
| | | plt.title(train_targets[i].numpy()) |
| | | plt.axis('off') |
| | | plt.imshow(train_data.data[i], cmap='gray') |
| | | plt.show() |
| | | |
| | | # 训练模型 |
| | | for epo in range(10): |
| | | for i, (images, lab) in enumerate(train_loader): |
| | | # images = images.cuda() |
| | | # lab = lab.cuda() |
| | | out = cnn(images) |
| | | loss = los(out, lab) |
| | | optime.zero_grad() |
| | | loss.backward() |
| | | optime.step() |
| | | print("epo:{},i:{},loss:{}".format(epo + 1, i, loss)) |
| | | |
| | | # 测试模型 |
| | | loss_test = 0 |
| | | accuracy = 0 |
| | | with torch.no_grad(): |
| | | for j, (images_test, lab_test) in enumerate(test_loader): |
| | | # images_test = images_test.cuda() |
| | | # lab_test = lab_test.cuda() |
| | | out1 = cnn(images_test) |
| | | loss_test += los(out1, lab_test) |
| | | loss_test = loss_test / (len(test_data) // 100) |
| | | _, p = out1.max(1) |
| | | accuracy += (p == lab_test).sum().item() |
| | | accuracy = accuracy / len(test_data) |
| | | print("loss_test:{},accuracy:{}".format(loss_test, accuracy)) |
| | |
| | | datas = sorted(datas, key=lambda tup: int(tup["created_at"].split(" ")[1].replace(":", ""))) |
| | | return datas |
| | | |
| | | def get_lack_datas_time_range(self, datas): |
| | | def get_lack_datas_time_range(self, datas, min_time=None): |
| | | def is_trade_time(time_): |
| | | if int("092500") <= int(time_.replace(":", "")) <= int("113000") or int("130000") <= int( |
| | | last_time.replace(":", "")) <= int("150000"): |
| | | time_.replace(":", "")) <= int("150000"): |
| | | return True |
| | | return False |
| | | |
| | | ranges = [] |
| | | # 只获取18分钟内的数据 |
| | | |
| | | 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, "13:00:00") < 0 and tool.trade_time_sub(now_time_str, "11:30:00") > 0 : |
| | | if tool.trade_time_sub(now_time_str, "13:00:00") < 0 and tool.trade_time_sub(now_time_str, "11:30:00") > 0: |
| | | now_time_str = "11:30:00" |
| | | |
| | | # 还没到时间 |
| | | if tool.trade_time_sub(now_time_str, "09:25:00") < 0: |
| | | return ranges |
| | | |
| | | last_time = tool.trade_time_add_second(now_time_str, 0 - 18 * 60) |
| | | if tool.trade_time_sub(last_time, "09:25:00") < 0: |
| | | last_time = "09:25:00" |
| | | last_time = "09:25:01" if min_time is None else min_time |
| | | # tool.trade_time_add_second(now_time_str, 0 - 18 * 60) |
| | | # if tool.trade_time_sub(last_time, "09:25:00") < 0: |
| | | # last_time = "09:25:00" |
| | | |
| | | if len(datas) == 0: |
| | | ranges.append((last_time, now_time_str)) |
New file |
| | |
| | | import cv2 |
| | | |
| | | import opencv_util |
| | | import win32_util |
| | | import ocr_util |
| | | |
| | | |
| | | def save_code_img(): |
| | | img = win32_util.window_capture(0x00D118FC, (40, 150, 90, 165)) |
| | | gray_img = opencv_util.gray_img(img) |
| | | code = ocr_util.recognize_code(gray_img) |
| | | # 保存文件 |
| | | cv2.imwrite(f"datas/test3/{code}.png", gray_img) |
| | | print(code) |
| | | |
| | | |
| | | def save_l2_select_img(): |
| | | x = 1500 + 67 |
| | | y = 400 + 4 |
| | | img = win32_util.window_capture(0x00010BA2, (x, y, x + 45, y + 16)) |
| | | gray_img = opencv_util.gray_img(img) |
| | | code = ocr_util.recognize_num(gray_img) |
| | | # 保存文件 |
| | | cv2.imwrite(f"datas/test4/{code}.png", gray_img) |
| | | print(code) |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | save_l2_select_img() |
New file |
| | |
| | | from jinja2 import Environment, FileSystemLoader |
| | | |
| | | |
| | | def render(params): |
| | | env = Environment(loader=FileSystemLoader('D:/nginx-1.13.6/html/kp')) |
| | | css = env.get_template('index.css') |
| | | params["css"] = css.render() |
| | | template = env.get_template('index.html') |
| | | html_content = template.render(params) |
| | | return html_content |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | datas = { |
| | | "base_url": "http://192.168.3.122/kp/", |
| | | "code_name": "天域生态 002255", |
| | | "score_data": {"volume": {"score": 20, "now": "12", "high": {"num": "56", "date": "2023-04-13"}}, |
| | | "bidding": {"score": 10, "money": "4563"}, |
| | | "deal_big_money": {"score": 10, "money": 0, "base_money": 456.5, |
| | | "start": {"time": "09:00:00", "num": 1456}, |
| | | "end": {"time": "09:00:00", "num": 1456}}, |
| | | "k_form": {"score": 10, "datas": ["破前高", "超跌补涨", "涨幅过高"]}, |
| | | "code_nature": {"score": 10, "data_desc": "涨停次数2次"}, |
| | | "hot_block": {"score": 10, "block_name": "影视", "limit_up_count": 10, "open_limit_up_count": 2}, |
| | | "limit_up_time": {"score": 10, "time": "09:56:00"}, |
| | | "zyltgb": {"score": 10, "value": "12.5"}, |
| | | "limit_up_price": {"score": 10, "price": "6.35"}, |
| | | "total_score": "210" |
| | | }, |
| | | "trade_data": {"star": {"desc": "被动买入", "count": 0}, |
| | | "safe_count": {"base": 12, "now": 2}, |
| | | "m": {"base": 1200, "now": 1000}, |
| | | "big_num": {"base": 10, "now": 2}, |
| | | "trade_progress": {"time": "09:12:12", "num": 1111, "money": "12.56"}, |
| | | "buy_single": {"time": "09:12:12", "num": 1111, "money": "12.56"}, |
| | | "buy_exec": {"time": "09:12:12", "num": 1111, "money": "12.56"} |
| | | }, |
| | | "xgb_code_infos": [{"date": "今天", "blocks": [ |
| | | {"name": "影视", "limit_up_count": 2, "index": 1, "price": "12.00", "rate": "+10.00%"}, |
| | | {"name": "文旅", "limit_up_count": 3, "index": 2, "price": "12.00", "rate": "+10.00%"}, |
| | | ]}], |
| | | "initiative_buy_codes": [ |
| | | {"name": "测试1", "code": "000123", "score": 125, "limit_up": True, "open_limit_up": True}, |
| | | {"name": "测试2", "code": "000123", "score": 125, "limit_up": False, "open_limit_up": True}, |
| | | {"name": "测试2", "code": "000123", "score": 125, "limit_up": False, "open_limit_up": True}, |
| | | {"name": "测试2", "code": "000123", "score": 125, "limit_up": False, "open_limit_up": False} |
| | | ], |
| | | "passive_buy_codes": [{"name": "测试1", "code": "000123", "score": 125}, |
| | | {"name": "测试2", "code": "000123", "score": 125}, |
| | | {"name": "测试2", "code": "000123", "score": 125}, |
| | | {"name": "测试2", "code": "000123", "score": 125} |
| | | ], |
| | | "trade_record": {"open_limit_up": "10:00:03", "records": [ |
| | | {"type": 1, "index": 1, "time": "11:00:00", "score": 12}, |
| | | {"type": 0, "time": "11:26:00", "desc": "H撤撤单"} |
| | | ]}, |
| | | "xgb_infos": [{"block": {"name": "测试1", "rate": "+12.00%", "limit_up_count": 10}, |
| | | "codes": [ |
| | | {"limit_up": True, "name": "测试代码", "code": "000654"}, |
| | | {"limit_up": True, "name": "测试代码", "code": "000654"}, |
| | | {"limit_up": True, "name": "测试代码", "code": "000654"}, |
| | | {"limit_up": False, "name": "测试代码", "code": "000654"}, |
| | | ]}] |
| | | } |
| | | |
| | | result = (render(datas)) |
| | | with open("D:/nginx-1.13.6/html/kp/index_test.html", "w", encoding="utf-8") as f: |
| | | f.write(result) |
New file |
| | |
| | | # 悬浮框 |
| | | import json |
| | | import logging |
| | | import os |
| | | import sys |
| | | import threading |
| | | import time |
| | | |
| | | import requests |
| | | import wx |
| | | |
| | | import tool |
| | | import kpl_api |
| | | |
| | | |
| | | def show_warning(content, click): |
| | | 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() |
| | | |
| | | |
| | | def show_info(content, click): |
| | | toastone = wx.MessageDialog(None, content, "提示", wx.YES_DEFAULT | wx.ICON_INFORMATION) |
| | | if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 |
| | | click() |
| | | toastone.Destroy() |
| | | |
| | | |
| | | class MyLogHandler(logging.Handler): |
| | | |
| | | def __init__(self, obj): |
| | | logging.Handler.__init__(self) |
| | | self.setLevel(logging.DEBUG) |
| | | self.Object = obj |
| | | |
| | | def emit(self, record): |
| | | if record.levelno: |
| | | if len(self.Object.GetValue()) > 1024: |
| | | self.Object.SetValue('') |
| | | |
| | | tstr = time.strftime('%Y-%m-%d_%H:%M:%S') |
| | | self.Object.AppendText("[%s][%s] %s\n" % (tstr, record.levelname, record.getMessage())) |
| | | |
| | | |
| | | class KPLDataCaptureFrame(wx.Frame): |
| | | |
| | | def __create_item(self, name, checked=True, trade_time=True, circulate=True): |
| | | btn = wx.Button(self, label=f"{'开启' if circulate else ''}{name}", size=(120, 28)) |
| | | check = wx.CheckBox(self, size=(-1, -1)) |
| | | if checked: |
| | | check.SetValue(True) |
| | | else: |
| | | check.SetValue(False) |
| | | label = wx.StaticText(self, label=f"{'是否交易时间采集' if trade_time else ''}") |
| | | bs1 = wx.BoxSizer(wx.HORIZONTAL) |
| | | bs1.Add(label) |
| | | bs1.Add(check, 0, wx.LEFT, 10) |
| | | bs2 = wx.BoxSizer(wx.VERTICAL) |
| | | bs2.Add(bs1) |
| | | bs2.Add(btn) |
| | | if not trade_time: |
| | | check.Hide() |
| | | return bs2, btn, check |
| | | |
| | | # 初始化采集线程 |
| | | def __init_capture_threads(self): |
| | | def create_thread(target): |
| | | t1 = threading.Thread(target=target) |
| | | t1.setDaemon(True) |
| | | t1.start() |
| | | |
| | | def create_circulate_task(target): |
| | | while True: |
| | | try: |
| | | target() |
| | | except Exception as e: |
| | | print(str(e)) |
| | | time.sleep(3) |
| | | |
| | | create_thread(lambda: create_circulate_task(self.__exec_limit_up)) |
| | | time.sleep(0.5) |
| | | create_thread(lambda: create_circulate_task(self.__exec_open_limit_up)) |
| | | time.sleep(0.5) |
| | | create_thread(lambda: create_circulate_task(self.__exec_limit_down)) |
| | | time.sleep(0.5) |
| | | create_thread(lambda: create_circulate_task(self.__exec_ever_limit_down)) |
| | | time.sleep(0.5) |
| | | create_thread(lambda: create_circulate_task(self.__exec_fengkou)) |
| | | time.sleep(0.5) |
| | | create_thread(lambda: create_circulate_task(self.__exec_fengkou_best)) |
| | | time.sleep(0.5) |
| | | create_thread(lambda: create_circulate_task(self.__exec_fengxiang)) |
| | | time.sleep(0.5) |
| | | create_thread(lambda: create_circulate_task(self.__exec_industry_rank)) |
| | | |
| | | def __init__(self): |
| | | self.__init_data() |
| | | wx.Frame.__init__(self, None, -1, "开盘啦数据采集客户端", |
| | | style=wx.CAPTION ^ wx.MINIMIZE_BOX ^ wx.CLOSE_BOX ^ wx.STAY_ON_TOP, |
| | | size=(800, 400)) |
| | | self.SetBackgroundColour(wx.Colour(224, 224, 224)) |
| | | self.Bind(wx.EVT_CLOSE, self.OnExit) |
| | | boxsier = wx.FlexGridSizer(5, 2, 10, 20) |
| | | self.item_bidding = self.__create_item("竞价采集", trade_time=False, circulate=False) |
| | | boxsier.Add(self.item_bidding[0], 0, wx.TOP, 5) |
| | | |
| | | self.items = [] |
| | | names = ["涨停采集", "炸板采集", "跌停采集", "曾跌停采集", "市场风口采集", "最强风口采集", "风向标采集", "行业涨幅"] |
| | | for name in names: |
| | | self.items.append(self.__create_item(name)) |
| | | boxsier.Add(self.items[-1][0], 0, wx.TOP, 5) |
| | | |
| | | # 绑定事件 |
| | | self.item_bidding[1].Bind(wx.EVT_BUTTON, self.__capture_bidding) |
| | | |
| | | for i in range(0, len(names)): |
| | | self.items[i][1].Bind(wx.EVT_BUTTON, lambda e, x=i: self.__capture_btn_click(x, e)) |
| | | self.items[i][2].Bind(wx.EVT_CHECKBOX, lambda e, x=i: self.__capture_btn_check(x, e)) |
| | | |
| | | root_boxsier = wx.BoxSizer(wx.HORIZONTAL) |
| | | left_boxsier = wx.BoxSizer(wx.VERTICAL) |
| | | left_boxsier.Add(boxsier) |
| | | whole_boxsier = wx.BoxSizer(wx.HORIZONTAL) |
| | | |
| | | self.start_all_btn = wx.Button(self, label="开启全部任务", size=(120, 28)) |
| | | self.start_all_btn.SetForegroundColour("#008040") |
| | | self.start_all_btn.Bind(wx.EVT_BUTTON, self.__start_all_task) |
| | | |
| | | self.stop_all_btn = wx.Button(self, label="关闭全部任务", size=(120, 28)) |
| | | self.stop_all_btn.SetForegroundColour("#FF0000") |
| | | self.stop_all_btn.Bind(wx.EVT_BUTTON, self.__stop_all_task) |
| | | |
| | | whole_boxsier.Add(self.stop_all_btn) |
| | | whole_boxsier.Add(self.start_all_btn, 1, wx.LEFT, 25) |
| | | left_boxsier.Add(whole_boxsier, 1, wx.TOP, 30) |
| | | root_boxsier.Add(left_boxsier, 1, wx.LEFT, 10) |
| | | self.text_log = wx.TextCtrl(parent=self, size=(500, self.Size[1]), style=wx.TE_MULTILINE) |
| | | self.text_log.SetEditable(False) |
| | | self.text_log.SetBackgroundColour("#EEE") |
| | | self.text_log.SetForegroundColour("#333") |
| | | |
| | | handler = MyLogHandler(self.text_log) |
| | | self.logger = logging.getLogger(__name__) |
| | | self.logger.addHandler(handler) |
| | | self.logger.setLevel(logging.DEBUG) |
| | | |
| | | root_boxsier.Add(self.text_log, 1, wx.LEFT, 10) |
| | | self.SetSizer(root_boxsier) |
| | | |
| | | self.timer = wx.Timer(self) # 创建定时器 |
| | | # self.Bind(wx.EVT_TIMER, self.clear_msg, self.timer) |
| | | |
| | | self.logger.info("初始化成功") |
| | | |
| | | self.__init_capture_threads() |
| | | |
| | | def __init_data(self): |
| | | self.capture_status = {} |
| | | self.keys = ["limit_up", "open_limit_up", "limit_down", "ever_limit_down", "feng_kou", "best_feng_kou", |
| | | "feng_xiang", "industry_rank"] |
| | | for key in self.keys: |
| | | self.capture_status[key] = [False, True] |
| | | |
| | | def __set_btn_text(self, controls): |
| | | text = controls[1].GetLabelText() |
| | | if text.find("开启") == 0: |
| | | text = text.replace("开启", "关闭") |
| | | else: |
| | | text = text.replace("关闭", "开启") |
| | | controls[1].SetLabelText(text) |
| | | |
| | | def __capture_bidding(self, event): |
| | | results = kpl_api.daBanList(kpl_api.DABAN_TYPE_BIDDING) |
| | | result = json.loads(results) |
| | | self.logger.info(f"获取到竞价数据:{len(result['list'])}") |
| | | self.__upload_data("biddings", result) |
| | | # show_info("采集成功", None) |
| | | |
| | | def __capture_btn_click(self, key_index, event): |
| | | self.__set_btn_text(self.items[key_index]) |
| | | self.capture_status[self.keys[key_index]][0] = not self.capture_status[self.keys[key_index]][0] |
| | | |
| | | def __capture_btn_check(self, key_index, event): |
| | | self.capture_status[self.keys[key_index]][1] = not self.capture_status[self.keys[key_index]][1] |
| | | |
| | | def __can_capture(self, key_index): |
| | | if not self.capture_status[self.keys[key_index]][0]: |
| | | return False |
| | | if self.capture_status[self.keys[key_index]][1] and not tool.is_trade_time(): |
| | | return False |
| | | return True |
| | | |
| | | def __exec_limit_up(self): |
| | | if not self.__can_capture(0): |
| | | return |
| | | results = kpl_api.daBanList(kpl_api.DABAN_TYPE_LIMIT_UP) |
| | | result = json.loads(results) |
| | | self.logger.info(f"涨停代码数量:{len(result['list'])}") |
| | | self.__upload_data(self.keys[0], result) |
| | | |
| | | def __exec_open_limit_up(self): |
| | | if not self.__can_capture(1): |
| | | return |
| | | results = kpl_api.daBanList(kpl_api.DABAN_TYPE_OPEN_LIMIT_UP) |
| | | result = json.loads(results) |
| | | self.logger.info(f"炸板代码数量:{len(result['list'])}") |
| | | self.__upload_data(self.keys[1], result) |
| | | |
| | | def __exec_limit_down(self): |
| | | if not self.__can_capture(2): |
| | | return |
| | | results = kpl_api.daBanList(kpl_api.DABAN_TYPE_LIMIT_DOWN) |
| | | result = json.loads(results) |
| | | self.logger.info(f"跌停代码数量:{len(result['list'])}") |
| | | self.__upload_data(self.keys[2], result) |
| | | |
| | | def __exec_ever_limit_down(self): |
| | | if not self.__can_capture(3): |
| | | return |
| | | results = kpl_api.daBanList(kpl_api.DABAN_TYPE_EVER_LIMIT_DOWN) |
| | | result = json.loads(results) |
| | | self.logger.info(f"曾经跌停代码数量:{len(result['list'])}") |
| | | self.__upload_data(self.keys[3], result) |
| | | |
| | | def __exec_fengkou(self): |
| | | if not self.__can_capture(4): |
| | | return |
| | | results = kpl_api.getFengKouList(tool.get_now_date_str()) |
| | | result = json.loads(results) |
| | | self.logger.info(f"市场风口代码数量:{len(result['List'])}") |
| | | self.__upload_data(self.keys[4], result) |
| | | |
| | | def __exec_fengkou_best(self): |
| | | if not self.__can_capture(5): |
| | | return |
| | | if not os.path.exists("D:/kpl/GetFengKListBest_0_0.log"): |
| | | return |
| | | with open("D:/kpl/GetFengKListBest_0_0.log", mode='r', encoding="utf-16") as f: |
| | | lines = f.readlines() |
| | | if lines: |
| | | data = json.loads(lines[0]) |
| | | self.logger.info(f"最强风口代码数量:{data['Count']}") |
| | | self.__upload_data(self.keys[5], data) |
| | | |
| | | def __exec_fengxiang(self): |
| | | if not self.__can_capture(6): |
| | | return |
| | | self.logger.info(f"开始风向标采集") |
| | | try: |
| | | results = kpl_api.getFengXiangBiao() |
| | | result = json.loads(results) |
| | | self.logger.info(f"风向标代码数量:{len(result['list'])}") |
| | | self.__upload_data(self.keys[6], result) |
| | | except Exception as e: |
| | | self.logger.error(str(e)) |
| | | |
| | | def __exec_industry_rank(self): |
| | | if not self.__can_capture(7): |
| | | return |
| | | results = kpl_api.getIndustryRealRankingInfo() |
| | | result = json.loads(results) |
| | | self.logger.info(f"行业涨幅排行代码数量:{len(result['list'])}") |
| | | self.__upload_data(self.keys[7], result) |
| | | |
| | | # 开始所有的任务 |
| | | def __start_all_task(self, event): |
| | | for i in range(0, len(self.items)): |
| | | # 是否已经开启 |
| | | if not self.capture_status[self.keys[i]][0]: |
| | | self.__capture_btn_click(i, None) |
| | | |
| | | # 开始所有的任务 |
| | | |
| | | def __stop_all_task(self, event): |
| | | for i in range(0, len(self.items)): |
| | | # 是否已经开启 |
| | | if self.capture_status[self.keys[i]][0]: |
| | | self.__capture_btn_click(i, None) |
| | | |
| | | def __upload_data(self, type, datas): |
| | | root_data = { |
| | | "type": type, |
| | | "data": datas |
| | | } |
| | | requests.post("http://192.168.3.252:9004/upload_kpl_data", json.dumps(root_data)) |
| | | |
| | | def OnExit(self, e): |
| | | sys.exit(0) |
| | | |
| | | |
| | | class mainApp(wx.App): |
| | | |
| | | def OnInit(self): |
| | | self.SetAppName("开盘啦") |
| | | # 传递代码设置成功的回调 |
| | | self.kpl = KPLDataCaptureFrame() |
| | | self.kpl.Show() |
| | | return True |
| | | |
| | | |
| | | # cd D:\workspace\GP\trade_desk |
| | | # D:\workspace\GP\trade_desk\dist\env\pk_env\Scripts\pyinstaller.exe kpl/gui.spec |
| | | # |
| | | |
| | | if __name__ == "__main__": |
| | | app = mainApp(redirect=True, filename="logs/output.log") |
| | | app.MainLoop() |
New file |
| | |
| | | # -*- mode: python ; coding: utf-8 -*- |
| | | |
| | | |
| | | block_cipher = None |
| | | |
| | | |
| | | a = Analysis( |
| | | ['gui.py'], |
| | | pathex=[], |
| | | binaries=[], |
| | | datas=[('../venv/Lib/site-packages/dateutil','dateutil')], |
| | | hiddenimports=[], |
| | | hookspath=[], |
| | | hooksconfig={}, |
| | | runtime_hooks=[], |
| | | excludes=[], |
| | | win_no_prefer_redirects=False, |
| | | win_private_assemblies=False, |
| | | cipher=block_cipher, |
| | | noarchive=False, |
| | | ) |
| | | pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) |
| | | |
| | | exe = EXE( |
| | | pyz, |
| | | a.scripts, |
| | | [], |
| | | exclude_binaries=True, |
| | | name='开盘啦', |
| | | debug=False, |
| | | bootloader_ignore_signals=False, |
| | | strip=False, |
| | | upx=True, |
| | | console=False, |
| | | disable_windowed_traceback=False, |
| | | argv_emulation=False, |
| | | target_arch=None, |
| | | codesign_identity=None, |
| | | entitlements_file=None |
| | | ) |
| | | coll = COLLECT( |
| | | exe, |
| | | a.binaries, |
| | | a.zipfiles, |
| | | a.datas, |
| | | strip=False, |
| | | upx=True, |
| | | upx_exclude=[], |
| | | name='开盘啦', |
| | | ) |
New file |
| | |
| | | import datetime |
| | | import logging |
| | | import time |
| | | |
| | | import pandas as pd |
| | | import requests |
| | | import json |
| | | import requests |
| | | |
| | | import tool |
| | | |
| | | # 竞价 |
| | | DABAN_TYPE_BIDDING = 8 |
| | | # 涨停 |
| | | DABAN_TYPE_LIMIT_UP = 1 |
| | | # 炸板 |
| | | DABAN_TYPE_OPEN_LIMIT_UP = 2 |
| | | # 跌停 |
| | | DABAN_TYPE_LIMIT_DOWN = 3 |
| | | # 曾跌停 |
| | | DABAN_TYPE_EVER_LIMIT_DOWN = 5 |
| | | |
| | | |
| | | def __base_request(url, data): |
| | | headers = { |
| | | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", |
| | | "User-Agent": "Dalvik / 2.1.0(Linux;U;Android 6.0.1;MuMu Build/V417IR)" |
| | | } |
| | | # proxies={'https': '192.168.3.251:9002'} |
| | | # 禁止代理,不然会走本地代理 |
| | | response = requests.post(url, data=data, headers=headers, proxies={"http": None, "https": None}) |
| | | return response |
| | | |
| | | |
| | | def daBanList(pidType): |
| | | data = "Order=1&a=DaBanList&st=100&c=HomeDingPan&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23" \ |
| | | f"&VerSion=5.8.0.2&Index=0&Is_st=1&PidType={pidType}&apiv=w32&Type=4&FilterMotherboard=0&Filter=0&FilterTIB=0" \ |
| | | "&FilterGem=0 " |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | |
| | | def getFengKouList(day): |
| | | data = f"c=StockFengKData&a=GetFengKList&Index=0&st=500&Order=17&Day={day}&Time=&DeviceID=a38adabd-99ef-3116" \ |
| | | "-8bb9-6d893c846e23 " |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php?apiv=w32&PhoneOSNew=1&VerSion=5.8.0.2", |
| | | data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | |
| | | def getFengXiangBiao(): |
| | | 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=801225&" |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", |
| | | data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | |
| | | def getWeiTuo_W14(code, index): |
| | | data = f"a=GetWeiTuo_W14&st=200&c=StockL2Data&PhoneOSNew=1&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Token=0&Index={index}&Tur=30&apiv=w32&Type=3&Vol=500&StockID={code}&VType=1&UserID=0&VOrder=0&" |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", |
| | | data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | |
| | | # 获取行业涨幅 |
| | | def getIndustryRealRankingInfo(): |
| | | data = f"Order=1&a=RealRankingInfo&st=20&apiv=w32&Type=2&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 getStockIDPlate(code): |
| | | data = f"a=GetStockIDPlate_New&apiv=w32&c=StockL2Data&StockID={code}&PhoneOSNew=1&UserID=0&DeviceID=a38adabd-99ef-3116-8bb9-6d893c846e23&VerSion=5.8.0.2&Token=0&" |
| | | response = __base_request("https://apphq.longhuvip.com/w1/api/index.php", |
| | | data=data) |
| | | if response.status_code != 200: |
| | | raise Exception("请求出错") |
| | | return response.text |
| | | |
| | | def test_l2(): |
| | | code = "600981" |
| | | count = 0 |
| | | while True: |
| | | result = getWeiTuo_W14(code, count) |
| | | result = json.loads(result) |
| | | new_count = result["Count"] |
| | | list_ = result["List"] |
| | | if new_count != count: |
| | | print(tool.get_now_time_str(), len(list_), result) |
| | | count = new_count |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | result = (daBanList(3)) |
| | | result = json.loads(result) |
| | | print(len(result["list"])) |
| | | tool.get_now_time_str() |
| | | for d in result["list"]: |
| | | print(d) |
| | | print("行业涨幅", getStockIDPlate("000333")) |
New file |
| | |
| | | import datetime |
| | | import decimal |
| | | from threading import Thread |
| | | |
| | | |
| | | def async_call(fn): |
| | | def wrapper(*args, **kwargs): |
| | | Thread(target=fn, args=args, kwargs=kwargs).start() |
| | | |
| | | return wrapper |
| | | |
| | | |
| | | # 获取涨停价 |
| | | def get_limit_up_price(price): |
| | | price = decimal.Decimal(str(price)) * decimal.Decimal("1.1") |
| | | price = price.quantize(decimal.Decimal("0.00"), decimal.ROUND_HALF_UP) |
| | | return price |
| | | |
| | | |
| | | # 获取跌停价 |
| | | def get_limit_down_price(price): |
| | | return decimal.Decimal(str(price)) * decimal.Decimal("0.9").quantize(decimal.Decimal("0.00"), decimal.ROUND_HALF_UP) |
| | | |
| | | |
| | | def get_time_as_second(time_str): |
| | | ts = time_str.split(":") |
| | | return int(ts[0]) * 3600 + int(ts[1]) * 60 + int(ts[2]) |
| | | |
| | | |
| | | def trade_time_sub(time_str_1, time_str_2): |
| | | split_time = get_time_as_second("11:30:00") |
| | | time_1 = get_time_as_second(time_str_1) |
| | | time_2 = get_time_as_second(time_str_2) |
| | | if time_1 > split_time >= time_2: |
| | | time_2 += 90 * 60 |
| | | else: |
| | | if time_1 < split_time <= time_2: |
| | | time_2 -= 90 * 60 |
| | | |
| | | return time_1 - time_2 |
| | | |
| | | |
| | | # 将秒数格式化为时间 |
| | | def time_seconds_format(seconds): |
| | | h = seconds // 3600 |
| | | m = seconds % 3600 // 60 |
| | | s = seconds % 60 |
| | | return "{0:0>2}:{1:0>2}:{2:0>2}".format(h, m, s) |
| | | |
| | | |
| | | # 交易时间加几s |
| | | def trade_time_add_second(time_str, second): |
| | | ts = time_str.split(":") |
| | | s_ = int(ts[0]) * 3600 + int(ts[1]) * 60 + int(ts[2]) |
| | | s = s_ + second |
| | | # 结果在11:30到1点之间 |
| | | if 13 * 3600 > s >= 11 * 3600 + 30 * 60: |
| | | if second > 0: |
| | | s += 90 * 60 |
| | | else: |
| | | s -= 90 * 60 |
| | | return time_seconds_format(s) |
| | | |
| | | |
| | | def is_trade_time(time_str=None): |
| | | if time_str is None: |
| | | time_str = get_now_time_str() |
| | | if (int("092500") <= int(time_str.replace(":", "")) <= int("113000")) or ( |
| | | int("130000") <= int(time_str.replace(":", "")) <= int("150000")): |
| | | return True |
| | | return False |
| | | |
| | | |
| | | def get_now_time_str(): |
| | | return datetime.datetime.now().strftime("%H:%M:%S") |
| | | # return "10:20:00" |
| | | |
| | | |
| | | def get_now_date_str(): |
| | | return datetime.datetime.now().strftime("%Y-%m-%d") |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | print(trade_time_sub("13:00:00", "11:30:00")) |
| | | print(trade_time_sub("13:00:00", "11:29:00")) |
| | | print(trade_time_sub("11:29:00", "13:00:00")) |
New file |
| | |
| | | import logging |
| | | import os |
| | | |
| | | |
| | | def get_logger(log_filename, level=logging.INFO, when='D', back_count=0): |
| | | """ |
| | | :brief 日志记录 |
| | | :param log_filename: 日志名称 |
| | | :param level: 日志等级 |
| | | :param when: 间隔时间: |
| | | S:秒 |
| | | M:分 |
| | | H:小时 |
| | | D:天 |
| | | W:每星期(interval==0时代表星期一) |
| | | midnight: 每天凌晨 |
| | | :param back_count: 备份文件的个数,若超过该值,就会自动删除 |
| | | :return: logger |
| | | """ |
| | | # 创建一个日志器。提供了应用程序接口 |
| | | logger = logging.getLogger(log_filename) |
| | | # 设置日志输出的最低等级,低于当前等级则会被忽略 |
| | | logger.setLevel(level) |
| | | |
| | | # 创建格式器 |
| | | formatter = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s') |
| | | # 创建处理器:ch为控制台处理器,fh为文件处理器 |
| | | ch = logging.StreamHandler() |
| | | ch.setLevel(level) |
| | | # 输出到文件 |
| | | fh = logging.FileHandler( |
| | | filename=log_filename, |
| | | encoding='utf-8') |
| | | fh.setLevel(level) |
| | | # 设置日志输出格式 |
| | | fh.setFormatter(formatter) |
| | | ch.setFormatter(formatter) |
| | | # 将处理器,添加至日志器中 |
| | | logger.addHandler(fh) |
| | | logger.addHandler(ch) |
| | | |
| | | return logger |
| | | |
| | | |
| | | debug_logger = get_logger("logs/debug.log",logging.DEBUG) |
| | | debug_logger.setLevel(logging.DEBUG) |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | debug_logger.info("test234") |
| | |
| | | import time |
| | | from multiprocessing import freeze_support |
| | | |
| | | import cv2 |
| | | import torch |
| | | import win32con |
| | | import win32gui |
| | | from matplotlib.lines import Line2D |
| | | |
| | | import ocr_util |
| | | import opencv_util |
| | |
| | | from matplotlib.widgets import Button |
| | | |
| | | import wx |
| | | import wx.html |
| | | import wx.html2 as webview |
| | | from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas |
| | | from matplotlib.figure import Figure |
| | | |
| | | import code_data_manager |
| | | import juejin_core |
| | | import tool |
| | | import dateutil |
| | | import requests |
| | | |
| | | APP_TITLE = "卖票看板" |
| | | APP_ICON = "" |
| | | SERVER_HOST = "192.168.3.252" |
| | | SOCKET_PORT = 9001 |
| | | HTTP_PORT = 9004 |
| | | |
| | | |
| | | def show_warning(content, click): |
| | |
| | | |
| | | def __request(self, codes): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = ("192.168.3.252", 9001) # server地址和端口号(最好是10000以后) |
| | | ip_port = (SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | data = {"type": 201, "data": {"codes": codes}} |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | |
| | | toastone.Destroy() |
| | | |
| | | |
| | | last_ocr_code = ["000000"] |
| | | |
| | | import log |
| | | |
| | | def ocr_ths_code(): |
| | | hwnd = ths_util.get_ths_main_content_hwnd() |
| | | if not hwnd: |
| | |
| | | # hwnd_width = (rect[2] - rect[0]) * 15 // 10 |
| | | rect_ = setting.get_ths_auto_code_rect() |
| | | img = win32_util.window_capture(hwnd, (0, rect_[0], rect_[1], rect_[0] + rect_[2])) |
| | | code = ocr_util.recognize_code(opencv_util.clip_ths_code_area(img)) |
| | | clip_img, details = opencv_util.clip_ths_code_area(img) |
| | | start_time = time.time() |
| | | code = ocr_util.recognize_code(clip_img) |
| | | use_time =round( (time.time()-start_time)*1000) |
| | | if code is None: |
| | | code = ocr_util.recognize_code(img) |
| | | if code != last_ocr_code[0]: |
| | | print("保存图片", code) |
| | | log.debug_logger.info(f"代码识别结果:{code} 识别时间:{use_time}ms") |
| | | last_ocr_code[0] = code |
| | | cv2.imwrite(f"datas/test/{code}.png", opencv_util.gray_img(img)) |
| | | |
| | | return code |
| | | |
| | | |
| | | # 悬浮框 |
| | | class FloatFrame(wx.Frame): |
| | | def __init__(self, position): |
| | | def __init__(self): |
| | | wx.Frame.__init__(self, None, -1, "悬浮盯盘", style=wx.CAPTION ^ wx.MINIMIZE_BOX ^ wx.CLOSE_BOX ^ wx.STAY_ON_TOP, |
| | | size=(320, 195)) |
| | | self.SetBackgroundColour(wx.Colour(224, 224, 224)) |
| | | self.SetTransparent(230) |
| | | if position: |
| | | self.SetPosition(wx.Point(position[0], position[1])) |
| | | self.Bind(wx.EVT_CLOSE, self.OnExit) |
| | | # 读取配置信息 |
| | | window_info = setting.get_float_watch_window_info() |
| | | if window_info: |
| | | self.SetPosition(wx.Point(window_info[0], window_info[1])) |
| | | self.Size = wx.Size(window_info[2], window_info[3]) |
| | | boxsier = wx.FlexGridSizer(5, 2, 2, 5) |
| | | bs1 = wx.BoxSizer(wx.HORIZONTAL) |
| | | self.btn_remove_black = wx.Button(self, label="移除黑名单", size=(70, 30)) |
| | |
| | | boxsier.Add(self.edit_code) |
| | | |
| | | self.notify_text = wx.StaticText(self, label="", size=(80, -1)) |
| | | boxsier.Add(self.notify_text) |
| | | boxsier.Add(self.notify_text, 0, wx.LEFT, -45) |
| | | |
| | | # 代码 |
| | | bs1 = wx.BoxSizer(wx.HORIZONTAL) |
| | |
| | | try: |
| | | code = self.__get_code() |
| | | print("加入白名单", code) |
| | | self.__request([code], 202) |
| | | self.show_info(f"{code}加入白名单成功") |
| | | result = self.__request([code], 202) |
| | | result = json.loads(result) |
| | | if result["code"] == 0: |
| | | self.show_info(f"{code}加入白名单成功") |
| | | else: |
| | | self.show_warning(f"加入失败:{result['msg']}") |
| | | self.edit_code.SetValue("") |
| | | except Exception as e: |
| | | self.show_warning(str(e)) |
| | |
| | | self.check_auto_refresh.SetValue(True) |
| | | else: |
| | | self.check_auto_refresh.SetValue(False) |
| | | self.__init_trade_state() |
| | | |
| | | def __init_trade_state(self): |
| | | # 获取交易状态 |
| | | try: |
| | | result = self.__request_buy_state() |
| | | result = json.loads(result) |
| | | if result["code"] == 0: |
| | | if result["data"]["can_buy"]: |
| | | self.btn_open_buy.SetLabelText("开启交易*") |
| | | self.btn_close_buy.SetLabelText("关闭交易") |
| | | else: |
| | | self.btn_open_buy.SetLabelText("开启交易") |
| | | self.btn_close_buy.SetLabelText("关闭交易*") |
| | | except: |
| | | pass |
| | | |
| | | def __auto_click_check(self, event): |
| | | if event.Selection: |
| | |
| | | |
| | | def __request(self, codes, type): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = ("192.168.3.252", 9001) # server地址和端口号(最好是10000以后) |
| | | ip_port = (SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | data = {"type": type, "data": {"codes": codes}} |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | | result = client.recv(1024) |
| | | client.close() |
| | | return result.decode("gbk") |
| | | |
| | | def __request_list(self, type): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = ("192.168.3.252", 9001) # server地址和端口号(最好是10000以后) |
| | | ip_port = (SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | data = {"type": type, "data": {}} |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | |
| | | |
| | | def __request_buy(self, is_open): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = ("192.168.3.252", 9001) # server地址和端口号(最好是10000以后) |
| | | ip_port = (SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | data = {"type": 501, "data": {"open": is_open}} |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | | # 读取内容 |
| | | result = client.recv(10240) |
| | | client.close() |
| | | return result.decode("gbk") |
| | | |
| | | # 获取买入状态 |
| | | def __request_buy_state(self): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = (SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | data = {"type": 502, "data": {}} |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | | # 读取内容 |
| | | result = client.recv(1024) |
| | | client.close() |
| | | return result.decode("gbk") |
| | | |
| | |
| | | result = self.__request_buy(True) |
| | | msg = json.loads(result)["msg"] |
| | | show_info(msg, None) |
| | | self.__init_trade_state() |
| | | except Exception as e: |
| | | show_warning(str(e), None) |
| | | |
| | |
| | | result = self.__request_buy(False) |
| | | msg = json.loads(result)["msg"] |
| | | show_info(msg, None) |
| | | self.__init_trade_state() |
| | | except Exception as e: |
| | | show_warning(str(e), None) |
| | | |
| | | show_sure("是否关闭交易", close_buy) |
| | | |
| | | def OnExit(self, e): |
| | | try: |
| | | setting.set_float_watch_window_info((self.Position[0], self.Position[1], self.Size[0], self.Size[1])) |
| | | except Exception as e: |
| | | print("") |
| | | self.Hide() |
| | | |
| | | |
| | | # 代码数据 |
| | | class CodeDataFrame(wx.Frame): |
| | | def __init__(self, set_codes_success_callback): |
| | | def __init__(self, set_codes_success_callback, show_float_callback, show_main_callback): |
| | | # style=wx.CAPTION | |
| | | wx.Frame.__init__(self, None, -1, "数据", |
| | | style=wx.CAPTION | wx.STAY_ON_TOP | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.CLOSE_BOX | wx.RESIZE_BORDER, |
| | |
| | | self.SetBackgroundColour(wx.Colour(224, 224, 224)) |
| | | # self.SetTransparent(230) |
| | | boxsier = wx.BoxSizer(wx.VERTICAL) |
| | | self.data_text = wx.html.HtmlWindow(self, size=wx.Size(self.Size[0], self.Size[ |
| | | 1])) |
| | | self.data_text.SetBackgroundColour(wx.Colour(224, 224, 224)) |
| | | # ---配置浏览器---- |
| | | webview.WebView.MSWSetEmulationLevel() |
| | | backend = None |
| | | backends = [ |
| | | (webview.WebViewBackendEdge, 'WebViewBackendEdge'), |
| | | (webview.WebViewBackendIE, 'WebViewBackendIE'), |
| | | (webview.WebViewBackendWebKit, 'WebViewBackendWebKit'), |
| | | (webview.WebViewBackendDefault, 'WebViewBackendDefault'), |
| | | ] |
| | | for id, name in backends: |
| | | available = webview.WebView.IsBackendAvailable(id) |
| | | if available and backend is None: |
| | | backend = id |
| | | |
| | | self.wv = webview.WebView.New(self, size=wx.Size(self.Size[0], self.Size[ |
| | | 1]), backend=backend) |
| | | self.wv.SetZoomType(wx.html2.WEBVIEW_ZOOM_TYPE_TEXT) |
| | | self.Bind(webview.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv) |
| | | self.Bind(webview.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv) |
| | | |
| | | # 执行定时更新 |
| | | self.timer = wx.Timer(self) # 创建定时器 |
| | | self.Bind(wx.EVT_TIMER, self.__update_kpl, self.timer) |
| | | self.timer.Start(3000) |
| | | self.count = 0 |
| | | |
| | | self.wv.SetBackgroundColour(wx.Colour(224, 224, 224)) |
| | | if "gtk2" in wx.PlatformInfo: |
| | | self.data_text.SetStandardFonts() |
| | | boxsier.Add(self.data_text) |
| | | self.wv.SetStandardFonts() |
| | | boxsier.Add(self.wv, 1, wx.EXPAND) |
| | | self.latest_code = '' |
| | | self.SetSizer(boxsier) |
| | | window_info = setting.get_xgb_window_info() |
| | |
| | | self.Size = wx.Size(window_info[2], window_info[3]) |
| | | self.Bind(wx.EVT_CLOSE, self.OnExit) |
| | | self.Bind(wx.EVT_SIZE, self.OnResize) |
| | | self.data_text.SetPage("") |
| | | self.wv.SetPage("", "") |
| | | self.__menu() |
| | | self.show_float_callback = show_float_callback |
| | | self.show_main_callback = show_main_callback |
| | | |
| | | def OnWebViewNavigating(self, evt): |
| | | # this event happens prior to trying to get a resource |
| | | if evt.GetURL().find("cancel_order://") >= 0: |
| | | code__ = evt.GetURL().split("cancel_order://")[1] |
| | | # if wx.MessageBox("是否要撤单?", |
| | | # style=wx.YES_NO | wx.ICON_QUESTION) == wx.YES: |
| | | self.__cancel_order(code__) |
| | | evt.Veto() |
| | | |
| | | def OnWebViewLoaded(self, evt): |
| | | # pass |
| | | # 加载开盘啦数据 |
| | | self.__update_kpl(None) |
| | | |
| | | # 更新开盘啦数据 |
| | | def __update_kpl(self, evt): |
| | | response = requests.get(f"http://{SERVER_HOST}:{HTTP_PORT}/get_kpl_data") |
| | | if response.status_code == 200: |
| | | print(response.text) |
| | | with open("res/kpl.js", mode="r", encoding="utf-8") as f: |
| | | lines = f.readlines() |
| | | script = "\n".join(lines) |
| | | script = script.replace("{}", response.text) |
| | | self.wv.RunScript(script) |
| | | |
| | | def __cancel_order(self, code): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = (SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | try: |
| | | client.connect(ip_port) |
| | | data = {"type": 80, "data": {"code": code}} |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | | result = client.recv(1024) |
| | | result = result.decode("utf-8") |
| | | result = json.loads(result) |
| | | if result["code"] == 0: |
| | | # show_info("撤单处理成功", None) |
| | | # 刷新数据 |
| | | self.__init_data(self.latest_code) |
| | | else: |
| | | show_warning(result["msg"], None) |
| | | |
| | | client.close() |
| | | except Exception as e: |
| | | show_warning(str(e), None) |
| | | |
| | | def OnWebViewError(self, evt): |
| | | # The full document has loaded |
| | | print("网页出错") |
| | | |
| | | def handleMessage(self, event): |
| | | print("数据回调") |
| | | |
| | | def set_data(self, code, data): |
| | | self.data_text.SetPage(data) |
| | | self.wv.SetPage(data, "") |
| | | |
| | | # 设置代码 |
| | | def set_code(self, code): |
| | |
| | | |
| | | def __request(self, code, type=71): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = ("192.168.3.252", 9001) # server地址和端口号(最好是10000以后) |
| | | ip_port = (SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | data = {"type": type, "data": {"code": code}} |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | |
| | | |
| | | def OnResize(self, e): |
| | | print("变化后的尺寸", e.Size) |
| | | self.data_text.Size = e.Size |
| | | self.wv.Size = e.Size |
| | | |
| | | def __menu(self): |
| | | self.mainmenu = wx.MenuBar() |
| | |
| | | setting_.AppendSeparator() |
| | | setting_.Append(103, '&代码管理', 'Open a new document') |
| | | setting_.Append(102, '&下载涨停代码', 'Open a new document') |
| | | setting_.AppendSeparator() |
| | | setting_.Append(104, '&GPU检测', 'Open a new document') |
| | | |
| | | self.mainmenu.Append(setting_, '&设置') |
| | | |
| | | auto_help = wx.Menu() |
| | | auto_help.Append(202, '&同花顺设置', '') |
| | | self.mainmenu.Append(auto_help, '&自动化') |
| | | |
| | | view = wx.Menu() |
| | | view.Append(301, '&打开悬浮盯盘', '') |
| | | view.Append(302, '&打开分时看盘', '') |
| | | self.mainmenu.Append(view, '&视图') |
| | | |
| | | # 设置事件 |
| | | self.Bind(wx.EVT_MENU, self.__set_juejin_params, id=101) |
| | | self.Bind(wx.EVT_MENU, self.__download_codes, id=102) |
| | | self.Bind(wx.EVT_MENU, self.__manage_code, id=103) |
| | | self.Bind(wx.EVT_MENU, self.__gpu_is_avaiable, id=104) |
| | | self.Bind(wx.EVT_MENU, self.__manage_ths_pos, id=202) |
| | | self.Bind(wx.EVT_MENU, self.__show_float_callback, id=301) |
| | | self.Bind(wx.EVT_MENU, self.__show_main_callback, id=302) |
| | | |
| | | self.SetMenuBar(self.mainmenu) |
| | | |
| | | def __gpu_is_avaiable(self,event): |
| | | if torch.cuda.is_available(): |
| | | show_info("GPU可用", None) |
| | | else: |
| | | show_warning("GPU不可用", None) |
| | | |
| | | def __set_juejin_params(self, event): |
| | | ps = self.GetPosition() |
| | |
| | | size = self.GetSize() |
| | | THSPositionSettingFrame((ps[0] + size[0] / 2, ps[1] + size[1] / 2)).Show() |
| | | |
| | | def __show_float_callback(self, event): |
| | | self.show_float_callback() |
| | | |
| | | class MainFrame(wx.Frame): |
| | | def __show_main_callback(self, event): |
| | | self.show_main_callback() |
| | | |
| | | |
| | | class TickFrame(wx.Frame): |
| | | def __init__(self): |
| | | '''构造函数''' |
| | | wx.Frame.__init__(self, None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE, |
| | |
| | | # ^ wx.RESIZE_BORDER ^ wx.STAY_ON_TOP |
| | | # 默认style是下列项的组合:wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN |
| | | self.SetBackgroundColour(wx.Colour(0, 0, 0)) |
| | | self.Center() |
| | | win_info = setting.get_tick_window_info() |
| | | if win_info: |
| | | self.SetPosition(wx.Point(win_info[0], win_info[1])) |
| | | self.Size = wx.Size(win_info[2], win_info[3]) |
| | | else: |
| | | self.Center() |
| | | |
| | | # 以下代码处理图标 |
| | | # if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe": |
| | |
| | | self.scroll = None |
| | | self.mark_lines = {} |
| | | self.col = 1 |
| | | self.ratio = 0.76 |
| | | self.ratio = 0.63 |
| | | self.__re_draw() |
| | | |
| | | self.timer = wx.Timer(self) # 创建定时器 |
| | |
| | | # boxsier.Add(mainBoxsier, 1, wx.EXPAND | wx.ALL, 5) |
| | | # self.SetSizer(boxsier) |
| | | # mainBoxsier.Fit(self) |
| | | |
| | | window_info = setting.get_window_info() |
| | | float_pos = None |
| | | if window_info: |
| | | float_pos = window_info[1] |
| | | self.SetPosition(wx.Point(window_info[0][0], window_info[0][1])) |
| | | self.Size = wx.Size(window_info[0][2], window_info[0][3]) |
| | | self.floatFrame = FloatFrame(float_pos) |
| | | self.floatFrame.Show() |
| | | 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 |
| | | |
| | |
| | | print("关闭", title) |
| | | close_callback(title) |
| | | |
| | | width_dpi = self.Size[0] / (100 * self.col) |
| | | figure_score = Figure(figsize=(width_dpi, round(width_dpi * (self.ratio), 2))) |
| | | 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) |
| | |
| | | max_rate = round((limit_up_price - price) / price, 4) * 100 |
| | | print("涨停最大比例", max_rate) |
| | | yticks2 = [] |
| | | for i in range(0, 21): |
| | | if i >= 10: |
| | | yticks2.append(0 - round(max_rate * (10 - i) / 10, 4)) |
| | | for i in range(0, 41): |
| | | if i >= 20: |
| | | yticks2.append(0 - round(max_rate * (20 - i) / 20, 4)) |
| | | else: |
| | | yticks2.append(round(max_rate * (i - 10) / 10, 4)) |
| | | yticks2.append(round(max_rate * (i - 20) / 20, 4)) |
| | | yticks2_labels = [] |
| | | yticks = [] |
| | | yticks_labels = [] |
| | |
| | | if i % 2 == 0: |
| | | yticks_labels.append("") |
| | | # yticks_labels.append(round(yticks[i], 2)) |
| | | if i == 10: |
| | | if i == 20: |
| | | axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=2) |
| | | else: |
| | | axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=1.2) |
| | |
| | | axes.set_yticks(yticks) |
| | | axes.set_yticklabels(yticks_labels) |
| | | # 设置纵坐标数值颜色 |
| | | for i in range(0, 9): |
| | | for i in range(0, 19): |
| | | axes.get_yticklabels()[i].set_color("green") |
| | | axes2.get_yticklabels()[i].set_color("green") |
| | | for i in range(10, 10): |
| | | for i in range(20, 20): |
| | | axes.get_yticklabels()[i].set_color("white") |
| | | axes2.get_yticklabels()[i].set_color("white") |
| | | for i in range(11, 21): |
| | | for i in range(21, 41): |
| | | axes.get_yticklabels()[i].set_color("red") |
| | | axes2.get_yticklabels()[i].set_color("red") |
| | | line = axes2.plot([], [], color='white', linewidth=1) |
| | | average_line = axes2.plot([], [], color='yellow', linewidth=1) |
| | | average_line = axes2.plot([], [], color='green', 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'现价: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') |
| | |
| | | axes.spines['top'].set_visible(False) |
| | | axes2.spines['bottom'].set_visible(False) |
| | | axes.spines['bottom'].set_visible(False) |
| | | return (axes2, line, average_line) |
| | | return (axes2, line, average_line_1m, average_line) |
| | | |
| | | def __show_top(self, event): |
| | | if event.Selection: |
| | |
| | | |
| | | def OnExit(self, e): |
| | | try: |
| | | self.floatFrame.Close(True) |
| | | setting.set_window_info((self.Position[0], self.Position[1], self.Size[0], self.Size[1]), ( |
| | | self.floatFrame.Position[0], self.floatFrame.Position[1], self.floatFrame.Size[0], |
| | | self.floatFrame.Size[1])) |
| | | setting.set_tick_window_info((self.Position[0], self.Position[1], self.Size[0], self.Size[1])) |
| | | except Exception as e: |
| | | print("") |
| | | jueJinProcess.terminate() |
| | | sys.exit(0) |
| | | self.Hide() |
| | | |
| | | def post_redraw(self, evt): |
| | | |
| | |
| | | |
| | | # 绘图管理器 |
| | | class DrawManager: |
| | | X_RANGE_MINIUTES = 60 |
| | | X_DATA_MINIUTES = 56 |
| | | |
| | | def __load_lack_datas(self, code, time_ranges): |
| | | codeDataManager = code_data_manager.CodeDataManager() |
| | |
| | | code_datas[code] = [] |
| | | old_datas = codeDataManager.get_datas(code) |
| | | # 获取缺失的数据 |
| | | ranges = codeDataManager.get_lack_datas_time_range(old_datas) |
| | | min_time = tool.get_now_time_str() |
| | | if int(min_time.replace(":", "")) > int("150000"): |
| | | min_time = "15:00:00" |
| | | elif int("113000") < int(min_time.replace(":", "")) < int("130000"): |
| | | min_time = "11:30:00" |
| | | |
| | | min_time = tool.trade_time_add_second(min_time, 0 - DrawManager.X_DATA_MINIUTES * 60) |
| | | |
| | | ranges = codeDataManager.get_lack_datas_time_range(old_datas, min_time) |
| | | if len(ranges) > 0: |
| | | self.__load_lack_datas(code, ranges) |
| | | old_datas = codeDataManager.get_datas(code) |
| | |
| | | # 删除9:30以前的数据 |
| | | for i in range(0, len(datas)): |
| | | time_ = datas[i]["created_at"][-8:] |
| | | if int(time_.replace(":", "")) >= int("093000"): |
| | | if int(time_.replace(":", "")) >= int("092600"): |
| | | datas = datas[i:] |
| | | break |
| | | # 取最近12分钟的数据 |
| | | # 取最近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_) >= 14 * 60: |
| | | 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(get_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:], 15 * 60) |
| | | 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)) |
| | | |
| | | # if len(xs) < 2 or xs[-1] - xs[0] < 30 * 60: |
| | |
| | | axes[0].set_xticklabels(xticklabels) |
| | | |
| | | axes[1][0].set_data(xs, ys_rate) |
| | | axes[2][0].set_data(xs, ys_average_rate) |
| | | 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留格局:0%".format(round(datas[-1]["rate"] * 100, 2))) |
| | | texts[1].set_text("{}".format(datas[-1]["created_at"].split(" ")[1])) |
| | |
| | | min_rate = rate |
| | | |
| | | # 展示最近的600个 |
| | | datas = datas[-450:] |
| | | datas = datas[0 - self.X_DATA_MINIUTES * 20:] |
| | | # 修正量数据 |
| | | last_info = None |
| | | for i in range(1, len(datas)): |
| | |
| | | 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'] = last_info['average_rate'] |
| | | 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: |
| | |
| | | last_time = round(time.time()) |
| | | for index in range(0, len(codes)): |
| | | if codes[index] == code: |
| | | self.Frame.scrollTo(index) |
| | | self.frame.scrollTo(index) |
| | | break |
| | | except Exception as e: |
| | | # print(str(e)) |
| | | pass |
| | | time.sleep(0.005) |
| | | |
| | | def __show_float_frame(self): |
| | | self.floatFrame.Show() |
| | | |
| | | def __show_main_frame(self): |
| | | self.frame.Show() |
| | | |
| | | def OnInit(self): |
| | | self.SetAppName(APP_TITLE) |
| | | self.frame = MainFrame() |
| | | self.frame.Show() |
| | | self.frame = TickFrame() |
| | | self.floatFrame = FloatFrame() |
| | | # 传递代码设置成功的回调 |
| | | self.xgb = CodeDataFrame(self.frame.set_codes_success) |
| | | self.xgb = CodeDataFrame(self.frame.set_codes_success, self.__show_float_frame, self.__show_main_frame) |
| | | self.xgb.Show() |
| | | t1 = threading.Thread(target=lambda: self.__refresh()) |
| | | # 后台运行 |
| | |
| | | |
| | | |
| | | if __name__ == "__main__1": |
| | | code = ocr_util.recognize_code("C:\\Users\\Administrator\\Desktop\\test.png.bmp") |
| | | print(code) |
| | | print(webview.WebView.IsBackendAvailable(webview.WebViewBackendEdge)) |
| | | |
| | | # 打包命令 |
| | | # cd D:\workspace\GP\trade_desk |
| | |
| | | strip=False, |
| | | upx=True, |
| | | upx_exclude=[], |
| | | name='分时', |
| | | name='分时1', |
| | | ) |
| | |
| | | # 数字识别 |
| | | def recognize_code(img): |
| | | results = num_reader.readtext(img, detail=0, mag_ratio=1.5) |
| | | print("识别结果", results) |
| | | # print("识别结果", results) |
| | | if results: |
| | | result = results[0].strip() |
| | | code = result[-6:] |
| | | if code.isnumeric(): |
| | | return code |
| | | for result in results: |
| | | result = result.strip() |
| | | if len(result) >= 6: |
| | | code = result[-6:] |
| | | if code.isnumeric(): |
| | | return code |
| | | return None |
| | | |
| | | |
| | | # 数字识别 |
| | | def recognize_num(img): |
| | | results = reader.readtext(img, detail=0, mag_ratio=2) |
| | | print("识别结果", results) |
| | | results = num_reader.readtext(img, detail=0, mag_ratio=1.5) |
| | | # print("识别结果", results) |
| | | if results: |
| | | result = results[0].strip() |
| | | if result.isnumeric(): |
| | |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | start_time = time.time() |
| | | img = "C:\\Users\\Administrator\\Desktop\\ocr\\codes\\000021_23850.png" |
| | | results = num_reader.readtext(img, detail=1, mag_ratio=2) |
| | | print(results) |
| | | |
| | | # results = kpl_util.recognize_datas("C:\\Users\\Administrator\\Desktop\\test.png") |
| | | # print(results) |
| | |
| | | # 二值化图像 |
| | | import os |
| | | import random |
| | | |
| | | import cv2 |
| | | import matplotlib.pyplot as plt |
| | | import numpy |
| | | |
| | | SHOW_PLT = False |
| | | |
| | | |
| | | def gray_img(img): |
| | | if img.ndim == 2: |
| | | return img |
| | | result = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
| | | return result |
| | | |
| | | |
| | | def is_col_empty(img, col, thresh_hold=0): |
| | | for r in img: |
| | | if r[col] > thresh_hold: |
| | | def is_col_empty(img, col, start_row, end_row, thresh_hold=0): |
| | | for r in range(start_row, end_row + 1): |
| | | if img[r][col] > thresh_hold: |
| | | return False |
| | | return True |
| | | |
| | | |
| | | def is_col_full(img, col, thresh_hold_start=64, thresh_hold_end=255): |
| | | def is_col_full(img, col, start_row, end_row, thresh_hold_start=64, thresh_hold_end=255, thresh_empty_count=1): |
| | | rows, cols = img.shape |
| | | for r in img: |
| | | if r[col] < thresh_hold_start or r[col] > thresh_hold_end: |
| | | empty_count = 0 |
| | | for r in range(start_row, end_row + 1): |
| | | if img[r][col] < thresh_hold_start or img[r][col] > thresh_hold_end: |
| | | empty_count += 1 |
| | | if empty_count > thresh_empty_count: |
| | | return False |
| | | return True |
| | | |
| | | |
| | | # 行是否是满的 |
| | | def is_row_full(img, row, start_col, end_col, thresh_hold_start=64, thresh_hold_end=255): |
| | | rows, cols = img.shape |
| | | for c in range(start_col, end_col + 1): |
| | | if img[row][c] < thresh_hold_start or img[row][c] > thresh_hold_end: |
| | | return False |
| | | return True |
| | | |
| | | |
| | | def format_num_img(img): |
| | | # 先调整为方形 |
| | | rows, cols = img.shape |
| | | img_new = numpy.zeros((max(rows, cols), max(rows, cols)), numpy.uint8) |
| | | img_new.fill(0) |
| | | start_col = (max(rows, cols) - cols) // 2 |
| | | if rows > cols: |
| | | for r in range(rows): |
| | | for c in range(cols): |
| | | img_new[r][c + start_col] = img[r][c] |
| | | else: |
| | | pass |
| | | # 设置为28X28像素 |
| | | return cv2.resize(img_new, (28, 28), interpolation=cv2.INTER_AREA) |
| | | |
| | | |
| | | # 分隔数字 |
| | | def split_nums_img(img): |
| | | # 获取代码的最大色值 |
| | | rows, cols = img.shape |
| | | max_color = 0 |
| | | for r in range(0, rows): |
| | | for c in range(0, cols): |
| | | if img[r][c] > max_color: |
| | | max_color = img[r][c] |
| | | |
| | | start_index = -1 |
| | | end_index = -1 |
| | | codes_pos = [] |
| | | for col in range(0, cols): |
| | | if not is_col_empty(img, col, 0, rows - 1, max_color * 2 // 3): |
| | | if start_index < 0: |
| | | start_index = col |
| | | end_index = col |
| | | else: |
| | | if end_index >= 0 and start_index >= 0: |
| | | codes_pos.append((start_index, end_index + 1)) |
| | | end_index = -1 |
| | | start_index = -1 |
| | | img_detail = [] |
| | | for i in range(len(codes_pos)): |
| | | temp_img = img[0:rows - 1, codes_pos[i][0]:codes_pos[i][1]] |
| | | temp_img = format_num_img(temp_img) |
| | | img_detail.append(temp_img) |
| | | return img_detail |
| | | |
| | | |
| | | # 分离同花顺的代码 |
| | | def clip_ths_code_area(img): |
| | | img = gray_img(img) |
| | | rows, cols = img.shape |
| | | end_col = cols - 1 |
| | | for col in range(0, cols, 1): |
| | | if is_col_full(img, col, 38, 38): |
| | | |
| | | # 行分隔 |
| | | full_row = -1 |
| | | start_row = -1 |
| | | end_row = -1 |
| | | for r in range(0, rows, 1): |
| | | if is_row_full(img, r, 0, cols // 2, 38, 38): |
| | | # print("找到分隔:", col) |
| | | end_col = col - 1 |
| | | full_row = r |
| | | if start_row >= 0 and r - start_row > 10: |
| | | end_row = r - 1 |
| | | break |
| | | |
| | | else: |
| | | if full_row > -1: |
| | | full_row = -1 |
| | | if start_row < 0: |
| | | start_row = r |
| | | if end_row < 0: |
| | | end_row = rows - 1 |
| | | |
| | | if start_row < 0: |
| | | raise Exception("没找到上分割线") |
| | | |
| | | end_col = cols - 1 |
| | | for c in range(cols - 1, -1, -1): |
| | | if is_col_full(img, c, start_row, end_row, 38, 38, 2): |
| | | # print("找到分隔:", col) |
| | | end_col = c - 1 |
| | | break |
| | | # 往前找数字分隔 |
| | | content_start = -1 |
| | | empty_start = -1 |
| | | empty_end = -1 |
| | | start_index = 0 |
| | | end_index = end_col |
| | | start_index = -1 |
| | | end_index = -1 |
| | | codes_pos = [] |
| | | # 获取代码的最大色值 |
| | | max_color = 0 |
| | | for r in range(start_row, end_row + 1): |
| | | for c in range(end_col, end_col // 2, -1): |
| | | if img[r][c] > max_color: |
| | | max_color = img[r][c] |
| | | |
| | | for col in range(end_col, 0, -1): |
| | | if not is_col_empty(img, col): |
| | | if content_start < 0: |
| | | content_start = col |
| | | empty_start = -1 |
| | | empty_end = -1 |
| | | if not is_col_empty(img, col, start_row, end_row, max_color * 2 // 3): |
| | | if start_index < 0: |
| | | start_index = col |
| | | end_index = col |
| | | else: |
| | | if empty_start < 0: |
| | | empty_start = col |
| | | empty_end = col |
| | | else: |
| | | empty_end = col |
| | | if empty_start - empty_end > 2 and content_start > 0: |
| | | start_index = col + (empty_start - empty_end + 1) |
| | | end_index = content_start |
| | | # print("代码范围:", start_index, end_index) |
| | | break |
| | | clip_img = img[0:rows, start_index:end_index] |
| | | if end_index >= 0 and start_index >= 0: |
| | | codes_pos.append((end_index - 1, start_index + 1)) |
| | | end_index = -1 |
| | | start_index = -1 |
| | | codes_pos = codes_pos[:6] |
| | | codes_pos.sort(key=lambda x: x[0]) |
| | | |
| | | if SHOW_PLT: |
| | | plt.figure(figsize=(10, 4)) |
| | | img_detail = [] |
| | | for i in range(len(codes_pos)): |
| | | if SHOW_PLT: |
| | | plt.subplot(2, 5, i + 1) |
| | | plt.title(f'pred {i}') |
| | | plt.axis('off') |
| | | temp_img = img[start_row:end_row, codes_pos[i][0]:codes_pos[i][1]] |
| | | temp_img = format_num_img(temp_img) |
| | | img_detail.append(temp_img) |
| | | if SHOW_PLT: |
| | | plt.imshow(temp_img, cmap='gray') |
| | | if SHOW_PLT: |
| | | plt.show() |
| | | |
| | | clip_img = img[start_row:end_row, codes_pos[0][0]:codes_pos[-1][1]] |
| | | # cv2.imwrite("test1.png", clip_img) |
| | | return clip_img |
| | | return clip_img, img_detail |
| | | |
| | | # print(clip_img.shape) |
| | | # ret1, p1 = cv2.threshold(src=clip_img, thresh=100, maxval=255, type=cv2.THRESH_BINARY) |
| | | # cv2.imwrite("D:/workspace/GP/trade_desk/test3.png", p1) |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | img = gray_img(cv2.imread("C:\\Users\\Administrator\\Desktop\\test.png")) |
| | | cv2.imwrite("C:\\Users\\Administrator\\Desktop\\test_gray.png", img) |
| | | def __test4(): |
| | | files = os.listdir("datas/test4/") |
| | | for file in files: |
| | | code = file[:-4] |
| | | img = cv2.imread(f"datas/test4/{file}", cv2.IMREAD_GRAYSCALE) |
| | | img_details = split_nums_img(img) |
| | | for d in range(0, len(img_details)): |
| | | cv2.imwrite(f"C:/Users/Administrator/Desktop/ocr/codes/{code}_{random.randint(0, 100000)}.png", |
| | | img_details[d]) |
| | | plt.figure(figsize=(10, 4)) |
| | | for i in range(0, len(img_details)): |
| | | plt.subplot(2, 5, i + 1) |
| | | plt.title(f'pred {i}') |
| | | plt.axis('off') |
| | | plt.imshow(img_details[i], cmap='gray') |
| | | plt.show() |
| | | |
| | | |
| | | def __test3(): |
| | | files = os.listdir("datas/test3/") |
| | | for file in files: |
| | | code = file[:-4] |
| | | img = cv2.imread(f"datas/test3/{file}", cv2.IMREAD_GRAYSCALE) |
| | | rows, cols = img.shape |
| | | for r in range(rows): |
| | | for c in range(cols): |
| | | img[r][c] = 255 - img[r][c] |
| | | |
| | | img_details = split_nums_img(img) |
| | | for d in range(0, len(img_details)): |
| | | cv2.imwrite(f"C:/Users/Administrator/Desktop/ocr/codes/{code}_{random.randint(0, 100000)}.png", |
| | | img_details[d]) |
| | | plt.figure(figsize=(10, 4)) |
| | | for i in range(0, len(img_details)): |
| | | plt.subplot(2, 5, i + 1) |
| | | plt.title(f'pred {i}') |
| | | plt.axis('off') |
| | | plt.imshow(img_details[i], cmap='gray') |
| | | plt.show() |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | __test4() |
| | | |
| | | if __name__ == "__main__1": |
| | | # |
| | | files = os.listdir("datas/test/") |
| | | for file in files: |
| | | code = file[:6] |
| | | img = cv2.imread(f"datas/test/{file}", cv2.IMREAD_GRAYSCALE) |
| | | img, img_details = clip_ths_code_area(img) |
| | | for d in range(0, len(img_details)): |
| | | cv2.imwrite(f"C:/Users/Administrator/Desktop/ocr/codes/{code}_{random.randint(0, 100000)}.png", |
| | | img_details[d]) |
| | | if SHOW_PLT: |
| | | plt.figure(figsize=(1, 1)) |
| | | plt.subplot(1, 1, 1) |
| | | plt.title(f"test") |
| | | plt.axis('off') |
| | | plt.imshow(img) |
| | | plt.show() |
| | | pass |
| | | # img = gray_img(cv2.imread("C:\\Users\\Administrator\\Desktop\\ocr\\code_test.png")) |
| | | # h = img.shape[0] |
| | | # w = img.shape[1] |
| | | # img = cv2.resize(img, (int(w * 2), int(h * 2)), interpolation=cv2.INTER_AREA) |
| | | # cv2.imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\code_test_gray.png", img) |
New file |
| | |
| | | function money_desc(money) { |
| | | if (Math.abs(money) > 100000000) { |
| | | return (money / 100000000.0).toFixed(2) + "亿"; |
| | | } else if (Math.abs(money) > 10000000){ |
| | | return (money / 10000).toFixed(0) + "万"; |
| | | }else if (Math.abs(money) > 1000000){ |
| | | return (money / 10000).toFixed(1) + "万"; |
| | | }else{ |
| | | return (money / 10000).toFixed(2) + "万"; |
| | | } |
| | | }; |
| | | |
| | | function fill_best_feng_kou(best_feng_kou) { |
| | | var html = ""; |
| | | //最强风口 |
| | | for (var i = 0; i < best_feng_kou.length; i++) { |
| | | var item = best_feng_kou[i]; |
| | | var tr = "<tr>"; |
| | | if (item[0].indexOf("00")==0||item[0].indexOf("60")==0) |
| | | { |
| | | tr += "<td>" + item[1] + " <br>" + item[0] + " </td>"; |
| | | }else{ |
| | | tr += "<td><span class='color-not-buy'>" + item[1] + "</span> <br>" + item[0] + " </td>"; |
| | | } |
| | | tr += "<td>" + item[2] + "</td>"; |
| | | if (item[3] >= 9) { |
| | | tr += "<td class='purple'>" + item[3] + "%</td>"; |
| | | } else { |
| | | tr += "<td >" + item[3] + "%</td>"; |
| | | } |
| | | //取板块中的前2个板块 |
| | | var blocks = item[5].split("、"); |
| | | if (blocks.length > 2) { |
| | | blocks = blocks.slice(0, 2); |
| | | } |
| | | var hot_blocks = item[4].split("、"); |
| | | tr += "<td class='bule'>"; |
| | | for (var n = 0; n < blocks.length; n++) { |
| | | var hot = 0; |
| | | for (var j = 0; j < hot_blocks.length; j++) { |
| | | if (hot_blocks[j] == blocks[n]) { |
| | | hot = 1; |
| | | break; |
| | | } |
| | | } |
| | | if (hot) { |
| | | tr += "<span class='red'>" + blocks[n] + "</span>"; |
| | | } else { |
| | | tr += blocks[n]; |
| | | } |
| | | if (n != blocks.length - 1) { |
| | | tr += "<br>"; |
| | | } |
| | | } |
| | | tr += "</td>"; |
| | | tr += "</tr>"; |
| | | html += tr; |
| | | } |
| | | try{ |
| | | table = document.getElementById('kpl-best_feng_kou'); |
| | | if(table!=undefined&&table!=null) |
| | | { |
| | | table.getElementsByTagName("tbody")[0].innerHTML = html; |
| | | } |
| | | }catch(e){ |
| | | }; |
| | | }; |
| | | |
| | | function fill_feng_kou(feng_kou) { |
| | | var html = ""; |
| | | for (var i = 0; i < feng_kou.length; i++) { |
| | | var item = feng_kou[i]; |
| | | var tr = "<tr>"; |
| | | if (item[0].indexOf("00")==0||item[0].indexOf("60")==0) |
| | | { |
| | | tr += "<td>" + item[1] + " <br>" + item[0] + " </td>"; |
| | | }else{ |
| | | tr += "<td><span class='color-not-buy'>" + item[1] + "</span> <br>" + item[0] + " </td>"; |
| | | } |
| | | |
| | | |
| | | tr += "<td>" + money_desc(item[3]) + "</td>"; |
| | | if (parseFloat(item[2]) >= 9) { |
| | | tr += "<td class='purple'>" + item[2] + "%</td>"; |
| | | } else { |
| | | tr += "<td >" + item[2] + "%</td>"; |
| | | } |
| | | //取板块中的前2个板块 |
| | | var blocks = item[4].split(","); |
| | | if (blocks.length > 2) { |
| | | blocks = blocks.slice(0, 2); |
| | | } |
| | | tr += "<td class='bule'>"; |
| | | for (var n = 0; n < blocks.length; n++) { |
| | | tr += blocks[n]; |
| | | if (n != blocks.length - 1) { |
| | | tr += "<br>"; |
| | | } |
| | | } |
| | | tr += "</td>"; |
| | | tr += "</tr>"; |
| | | html += tr; |
| | | } |
| | | table = document.getElementById('kpl-feng_kou'); |
| | | if(table!=undefined&&table!=null) |
| | | { |
| | | table.getElementsByTagName("tbody")[0].innerHTML = html; |
| | | } |
| | | |
| | | }; |
| | | |
| | | function fill_feng_xiang(feng_xiang) { |
| | | var html = ""; |
| | | for (var i = 0; i < feng_xiang.length; i++) { |
| | | var item = feng_xiang[i]; |
| | | var tr = "<tr>"; |
| | | if (item[0].indexOf("00")==0||item[0].indexOf("60")==0) |
| | | { |
| | | tr += "<td>" + item[1] + " <br>" + item[0] + " </td>"; |
| | | }else{ |
| | | tr += "<td><span class='color-not-buy'>" + item[1] + "</span> <br>" + item[0] + " </td>"; |
| | | } |
| | | if (parseFloat(item[3]) >= 9) { |
| | | tr += "<td class='purple'>" + item[3] + "%</td>"; |
| | | } else { |
| | | tr += "<td >" + item[3] + "%</td>"; |
| | | } |
| | | //取板块中的前2个板块 |
| | | var blocks = item[4].split("、"); |
| | | if (blocks.length > 2) { |
| | | blocks = blocks.slice(0, 2); |
| | | } |
| | | tr += "<td class='bule'>"; |
| | | for (var n = 0; n < blocks.length; n++) { |
| | | tr += blocks[n]; |
| | | if (n != blocks.length - 1) { |
| | | tr += "<br>"; |
| | | } |
| | | } |
| | | tr += "</td>"; |
| | | tr += "<td >" + money_desc(item[5]) + "</td>"; |
| | | tr += "<td >" + money_desc(item[6]) + "</td>"; |
| | | tr += "</tr>"; |
| | | html += tr; |
| | | } |
| | | table = document.getElementById('kpl-feng_xiang'); |
| | | if(table!=undefined&&table!=null) |
| | | { |
| | | table.getElementsByTagName("tbody")[0].innerHTML = html; |
| | | } |
| | | |
| | | }; |
| | | |
| | | function fill_industry_rank(industry_rank) { |
| | | var html = ""; |
| | | for (var i = 0; i < industry_rank.length; i++) { |
| | | var item = industry_rank[i]; |
| | | var tr = "<tr>"; |
| | | tr += "<td>" + item[1] + " <br>" + item[0] + " </td>"; |
| | | tr += "<td >" + money_desc(item[2]) + "</td>"; |
| | | if (parseFloat(item[3]) >= 9) { |
| | | tr += "<td class='purple'>" + item[3] + "%</td>"; |
| | | } else { |
| | | tr += "<td >" + item[3] + "%</td>"; |
| | | } |
| | | |
| | | |
| | | |
| | | tr += "</tr>"; |
| | | html += tr; |
| | | } |
| | | table = document.getElementById('kpl-industry_rank'); |
| | | if(table!=undefined&&table!=null) |
| | | { |
| | | table.getElementsByTagName("tbody")[0].innerHTML = html; |
| | | } |
| | | |
| | | }; |
| | | |
| | | |
| | | |
| | | var data = JSON.parse('{}'); |
| | | if (data.code == 0) { |
| | | fill_best_feng_kou( data.data.best_feng_kou); |
| | | fill_feng_kou( data.data.feng_kou); |
| | | fill_feng_xiang(data.data.feng_xiang); |
| | | fill_industry_rank(data.data.industry_rank); |
| | | }; |
| | |
| | | [config] |
| | | stay_on_top = 1 |
| | | window_info = [[-1268, 136, 800, 502], [1386, 638, 320, 195]] |
| | | window_info = [[-1711, 194, 1280, 800], [1473, 621, 320, 195]] |
| | | xgb_window_info = [-8, -8, 1936, 1056] |
| | | window_watch_float_info = [961, 489, 320, 195] |
| | | window_tick_info = [-1310, 226, 986, 645] |
| | | |
| | | [juejin] |
| | | strategy_id = 95a982ce-fc2d-11ec-8ff3-0a0027000010 |
| | |
| | | ths_click_time_space = 2000 |
| | | ths_trade_auto_refresh = 0 |
| | | ths_refresh_time_space = 1500 |
| | | ths_code_rect = [30,200,20] |
| | | ths_code_rect = [25,200,30] |
| | | |
New file |
| | |
| | | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| | | "http://www.w3.org/TR/html4/loose.dtd"> |
| | | <html> |
| | | <head> |
| | | <title>{{title}}</title> |
| | | </head> |
| | | <body> |
| | | <ul> |
| | | {% for k in list1 %} |
| | | {% if k.index % 2 == 0 %}<li>{{k.index}}</li>{% endif %} |
| | | {%endfor%} |
| | | </ul> |
| | | |
| | | </body> |
| | | </html> |
| | |
| | | return None |
| | | |
| | | |
| | | # 记录上次的窗口位置与大小 |
| | | def set_window_info(mainWindow, floatWindow): |
| | | # 设置分时看盘 |
| | | def set_tick_window_info(win_info): |
| | | cp = __read_setting() |
| | | cp.set("config", "window_info", json.dumps((mainWindow, floatWindow))) |
| | | cp.set("config", "window_tick_info", json.dumps(win_info)) |
| | | __write_setting(cp) |
| | | |
| | | |
| | | def get_window_info(): |
| | | def get_tick_window_info(): |
| | | cp = __read_setting() |
| | | val = __get_setting(cp, "config", "window_info") |
| | | val = __get_setting(cp, "config", "window_tick_info") |
| | | if val is None: |
| | | return None |
| | | else: |
| | | val = json.loads(val) |
| | | return val |
| | | |
| | | |
| | | # 设置悬浮盯盘 |
| | | def set_float_watch_window_info(win_info): |
| | | cp = __read_setting() |
| | | cp.set("config", "window_watch_float_info", json.dumps(win_info)) |
| | | __write_setting(cp) |
| | | |
| | | |
| | | def get_float_watch_window_info(): |
| | | cp = __read_setting() |
| | | val = __get_setting(cp, "config", "window_watch_float_info") |
| | | if val is None: |
| | | return None |
| | | else: |
New file |
| | |
| | | |
| | | import json |
| | | import random |
| | | |
| | | import xlwt |
| | | |
| | | # k_form=(15个交易日是否涨幅24.9%,是否破前高,是否超跌,是否接近前高,是否N) |
| | | # code_nature = (是否有涨停,是否有溢价) |
| | | # hot_block(板块中涨停票个数(包含自己),板块炸板票个数) |
| | | # zyltgb自由流通市值是否大于250亿 |
| | | # limit_price 涨停价是否大于100块 |
| | | # limit_up_time 是否10点之前涨停 |
| | | def getscore(bidding_money, big_money, volume, k_form, code_nature, hot_block, zyltgb, limit_price, limit_up_time): |
| | | score = 0 |
| | | score_list = [] |
| | | # 开盘前竞价 |
| | | if bidding_money: |
| | | score += 200 |
| | | score_list.append(200) |
| | | else: |
| | | score_list.append(0) |
| | | # 大单成交 |
| | | if big_money: |
| | | score += 150 |
| | | score_list.append(150) |
| | | else: |
| | | score_list.append(0) |
| | | # 量 |
| | | volume_score = [0, 200, 250, 200, 150, 100, -500, -1000] |
| | | score += volume_score[volume] |
| | | score_list.append(volume_score[volume]) |
| | | |
| | | # 15个交易日是否涨幅24.9% |
| | | if k_form[0]: |
| | | score += -1000 |
| | | score_list.append(-1000) |
| | | else: |
| | | score_list.append(0) |
| | | # 是否破前高 |
| | | if k_form[1]: |
| | | score += 150 |
| | | score_list.append(150) |
| | | else: |
| | | score_list.append(0) |
| | | # 是否超跌 |
| | | if k_form[2]: |
| | | score += 170 |
| | | score_list.append(170) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | # 是否接近前高 |
| | | if k_form[3]: |
| | | score += -1000 |
| | | score_list.append(-1000) |
| | | else: |
| | | score_list.append(0) |
| | | # 是否N |
| | | if k_form[4]: |
| | | score += 160 |
| | | score_list.append(160) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if not code_nature[0]: |
| | | score += 50 |
| | | score_list.append(50) |
| | | else: |
| | | score_list.append(0) |
| | | if code_nature[1]: |
| | | score += 100 |
| | | score_list.append(100) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if hot_block[0] >= 2: |
| | | score += 200 |
| | | score_list.append(200) |
| | | else: |
| | | score += 150 |
| | | score_list.append(150) |
| | | if hot_block[1] > 0: |
| | | score += 50 |
| | | score_list.append(50) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if zyltgb: |
| | | score += -500 |
| | | score_list.append(-500) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if limit_price: |
| | | score += -1000 |
| | | score_list.append(-1000) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if limit_up_time: |
| | | score += 150 |
| | | score_list.append(150) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | return score, score_list |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | bidding_money = [True, False] |
| | | bidding_money_desc = ["Y", "N"] |
| | | big_money = [True, False] |
| | | big_money_desc = ["Y", "N"] |
| | | volume = [0, 1, 2, 3, 4, 5, 6, 7] |
| | | volume_desc = ["换手量<49.9%。", "64.9%>换手量≥49.9%。", "79.9%>换手量≥64.9%。", "94.9%>换手量≥79.9%。", "109.9%>换手量≥94.9%。", |
| | | "124.9%>换手量≥109.9%。", "139.9%>换手量≥124.9%。", "换手量≥139.9%。"] |
| | | k_form = [] |
| | | k_form_str = [] |
| | | for i in range(0, 5): |
| | | k_form.append([True, False]) |
| | | k_form_str.append(["Y", "N"]) |
| | | |
| | | code_nature = [] |
| | | code_nature_str = [] |
| | | for i in range(0, 2): |
| | | code_nature.append([True, False]) |
| | | code_nature_str.append(["Y", "N"]) |
| | | |
| | | hot_block = [] |
| | | hot_block.append([1, 2]) |
| | | hot_block.append([0, 1]) |
| | | |
| | | zyltgb = [True, False] |
| | | limit_price = [True, False] |
| | | limit_up_time = [True, False] |
| | | |
| | | total_count = 0 |
| | | |
| | | params = {} |
| | | for i0 in range(0, len(bidding_money)): |
| | | for i1 in range(0, len(big_money)): |
| | | for i2 in range(0, len(volume)): |
| | | for i3 in range(0, len(k_form)): |
| | | ks = [] |
| | | for i in range(0, len(k_form)): |
| | | ks.append(0) |
| | | for n in range(0, 2): |
| | | ks[0] = k_form[0][n] |
| | | for n1 in range(0, 2): |
| | | ks[1] = k_form[1][n1] |
| | | for n2 in range(0, 2): |
| | | ks[2] = k_form[2][n2] |
| | | for n3 in range(0, 2): |
| | | ks[3] = k_form[3][n3] |
| | | for n4 in range(0, 2): |
| | | ks[4] = k_form[4][n4] |
| | | cns = [] |
| | | for i in range(0, len(code_nature)): |
| | | cns.append(0) |
| | | for j in range(0, 2): |
| | | cns[0] = code_nature[0][j] |
| | | for j1 in range(0, 2): |
| | | cns[1] = code_nature[1][j1] |
| | | hbs = [] |
| | | for i in range(0, len(hot_block)): |
| | | hbs.append(0) |
| | | for h in range(0, 2): |
| | | hbs[0] = hot_block[0][h] |
| | | for h1 in range(0, 2): |
| | | hbs[1] = hot_block[1][h1] |
| | | for i10 in range(0, len(zyltgb)): |
| | | for i11 in range(0, len(limit_price)): |
| | | for i12 in range(0, len(limit_up_time)): |
| | | param = (bidding_money[i0], big_money[i1], |
| | | volume[i2], ks, cns, hbs, |
| | | zyltgb[i10], limit_price[i11], |
| | | limit_up_time[i12]) |
| | | |
| | | score, score_list = getscore(bidding_money[i0], |
| | | big_money[i1], |
| | | volume[i2], ks, cns, |
| | | hbs, |
| | | zyltgb[i10], |
| | | limit_price[i11], |
| | | limit_up_time[i12]) |
| | | params[json.dumps(param)] = (score, score_list) |
| | | |
| | | titles = ["竞价强度", "资金力度", "换手量能", ["K线-涨幅24.9%", "K线-是否破前高", "K线-是否超跌", "K线-是否接近前高", "K线-是否N"], |
| | | ["股性-无涨停", "股性-有溢价"], |
| | | ["板块-涨停票数", "板块-炸板票数"], "股价>100", "自由流通市值>250亿", "10点前涨停", "得分"] |
| | | |
| | | # 写入excel |
| | | datas = [] |
| | | for key in params: |
| | | param = json.loads(key) |
| | | score = params[key] |
| | | # 15个交易日是否涨幅24.9 %, 是否破前高,是否超跌,是否接近前高,是否N |
| | | if param[3][1:2] == [True, True]: |
| | | continue |
| | | if param[3][1] == True and param[3][3] == True: |
| | | continue |
| | | if param[4][0] == True and param[4][1] == True: |
| | | continue |
| | | datas.append((param, score)) |
| | | |
| | | print("数量", len(datas)) |
| | | |
| | | random.shuffle(datas) |
| | | datas = datas[:1000] |
| | | |
| | | if True: |
| | | print("总数", len(datas)) |
| | | |
| | | file_name = "D:/test__.xls" |
| | | wb = xlwt.Workbook() |
| | | ws = wb.add_sheet('sheet1') |
| | | ws.write(0, 0, '序号') |
| | | index = 1 |
| | | for title in titles: |
| | | if type(title) != str: |
| | | for t in title: |
| | | ws.write(0, index, t) |
| | | index += 1 |
| | | else: |
| | | ws.write(0, index, title) |
| | | index += 1 |
| | | |
| | | index = 0 |
| | | for data in datas: |
| | | index += 1 |
| | | col = 1 |
| | | ws.write(index, 0, index) |
| | | for d in data[0]: |
| | | col_data = "" |
| | | if type(d) == list: |
| | | for dd in d: |
| | | if type(dd) == bool: |
| | | col_data = "Y" if dd else "N" |
| | | else: |
| | | col_data = str(dd) |
| | | |
| | | ws.write(index, col, f"{col_data}({data[1][1][col - 1]})") |
| | | col += 1 |
| | | else: |
| | | if type(d) == bool: |
| | | col_data = "Y" if d else "N" |
| | | else: |
| | | if col == 3: |
| | | col_data = volume_desc[d] |
| | | else: |
| | | col_data = str(d) |
| | | |
| | | print(col) |
| | | ws.write(index, col, f"{col_data}({data[1][1][col - 1]})") |
| | | col += 1 |
| | | |
| | | ws.write(index, col, data[1][0]) |
| | | wb.save(file_name) |
| | |
| | | return time_seconds_format(s) |
| | | |
| | | |
| | | def is_trade_time(time_str=None): |
| | | if time_str is None: |
| | | time_str = get_now_time_str() |
| | | if (int("092500") <= int(time_str.replace(":", "")) <= int("113000")) or ( |
| | | int("130000") <= int(time_str.replace(":", "")) <= int("150000")): |
| | | return True |
| | | return False |
| | | |
| | | |
| | | def get_now_time_str(): |
| | | return datetime.datetime.now().strftime("%H:%M:%S") |
| | | # return "10:20:00" |
| | | |
| | | |
| | | def get_now_date_str(): |
| | |
| | | str_ = getText(temp) |
| | | if str_.find(title) > -1: |
| | | hwnds.append(temp) |
| | | print(str_) |
| | | temp = win32gui.FindWindowEx(hwnd, temp, None, None) |
| | | if not temp: |
| | | break |
| | |
| | | |
| | | signedIntsArray = saveBitMap.GetBitmapBits(True) |
| | | |
| | | |
| | | |
| | | # 内存释放 |
| | | win32gui.DeleteObject(saveBitMap.GetHandle()) |
| | | saveDC.DeleteDC() |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | print(search_window("副屏1")) |
| | | visual_click(0x00152876, (110, 90)) |
| | | # print(search_window("副屏1")) |
| | | # visual_click(0x00152876, (110, 90)) |
| | | x = 1500 +67 |
| | | y = 400 + 4 |
| | | window_capture(0x00010BA2,(x,y,x +45,y+16)) |
| | | # pass |