class TableSheet: def __init__(self, records, headers, window): self.records = records self.sdem = Sheet(window, width=1000, height=500, align="w", header_align="center", row_index_align="center", show=True, column_width=180, row_index_width=50, data_reference=records, headers=headers) self.sdem.enable_bindings( ("single", "drag_select", "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize")) self.sdem.edit_bindings(True) self.sdem.pack()
class AnalyzeStockScreen(Frame): def __init__(self, master=None, session=None): super().__init__(master) self.master = master self.session = session self.analyze_controller = FAnalyzeStockController(session) self.pack(padx=20, pady=20) self.create_widgets() def create_widgets(self): # Khởi tạo tab phân tích chứng khoán ## Phần nhập ngày bắt đầu self.start_date_frame = Frame(self) self.start_date_frame.pack(fill=X) self.start_date_label = Label(self.start_date_frame, text="Start date", width=10) self.start_date_label.pack(side=LEFT, padx=5, pady=5) self.start_date_input = Entry(self.start_date_frame) self.start_date_input.pack(fill=X, padx=5, expand=True) ## Phần nhập ngày kết thúc self.end_date_frame = Frame(self) self.end_date_frame.pack(fill=X) self.end_date_label = Label(self.end_date_frame, text="End date", width=10) self.end_date_label.pack(side=LEFT, padx=5, pady=5) self.end_date_input = Entry(self.end_date_frame) self.end_date_input.pack(fill=X, padx=5, expand=True) ## Phần nút bấm self.stock_submit_frame = Frame(self) self.stock_submit_frame.pack(fill=X, padx=10) ## Phần button phân tích self.stock_submit = Button(self.stock_submit_frame) self.stock_submit["text"] = "Tính" self.stock_submit["command"] = lambda: self.start_calc() self.stock_submit.pack(side=RIGHT) # Phầns button export excel self.export_excel_button = Button(self.stock_submit_frame, state=DISABLED) self.export_excel_button["text"] = "Export file" self.export_excel_button["command"] = lambda: self.export_file_excel() self.export_excel_button.pack(side=RIGHT, padx=20) ## Phần bản tính self.tabel_frame = Frame(self) self.tabel_frame.pack(fill=X, pady=10) self.sheet = Sheet(self.tabel_frame) self.sheet.pack(fill=X) self.header = ("Mã", "Giá đóng nhỏ nhất", "Giá đóng lớn nhất") self.sheet.headers(self.header) ### Cấu hình cho tkinter sheet self.sheet.enable_bindings( ("single_select", "row_select", "column_width_resize", "arrowkeys", "right_click_popup_menu", "rc_select", "rc_insert_row", "rc_delete_row", "copy", "cut", "paste", "delete", "undo", "edit_cell")) def start_calc(self): ## Disable trang export file button self.export_excel_button["state"] = DISABLED datetime_format = "%d/%m/%Y" startDate = datetime.strptime(self.start_date_input.get().strip(), datetime_format) endDate = datetime.strptime(self.end_date_input.get(), datetime_format) self.analyzeStocks = self.analyze_controller.get_analyze_stocks_data( startDate, endDate) ## Tạo data cho tkinter sheet self.data_sheet = [] for anaStock in self.analyzeStocks: self.data_sheet.append([ anaStock.code, anaStock.closedPriceMin, anaStock.closedPriceMax ]) ## Thêm vào tkinter sheet self.sheet.set_sheet_data(self.data_sheet) self.export_excel_button["state"] = NORMAL def export_file_excel(self): ## Tạo bảnh tính excel với tên file là file_excel_<Thời gian tính theo giây> workbook = xlsxwriter.Workbook('file_excel_{}.xlsx'.format( time.time())) worksheet = workbook.add_worksheet() ## Tạo kiểu kiểu chữ bold = workbook.add_format({'bold': True}) ## Phần header cho trang tính excel worksheet.write('A1', 'Mã', bold) worksheet.write('B1', 'Giá đóng nhỏ nhất', bold) worksheet.write('C1', 'Giá đóng lớn nhất', bold) ## Thêm dòng vào bảng tính row = 1 for record in self.analyzeStocks: worksheet.write(row, 0, record.code) worksheet.write(row, 1, record.closedPriceMin) worksheet.write(row, 2, record.closedPriceMax) row += 1 ## Lưu file và đóng bảng tính workbook.close()
class PageScreener(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller self.flag = 0 self.FLAG_THRD_SCREEN_DATA = 1 # 处理数据队列 self.queData = Queue() # 数据缓存,用于重复使用, self.listData = [] topFrame = tk.Frame(self) self.btnMainPage = tk.Button(topFrame, text="主页面", command=self.on_btn_main_page).pack( side=tk.LEFT, padx=4) # 日期选择 # Calendar((x, y), 'ur').selection() 获取日期,x,y为点坐标 date_start_gain = lambda: [ self.date_start.set(date) for date in [CalendarCustom(None, 'ul').selection()] if date ] self.btnStart = tk.Button(topFrame, text='选股日期:', command=date_start_gain) self.btnStart.pack(side=tk.LEFT, padx=4) # ret = self.btnStart.winfo_geometry() self.date_start = tk.StringVar() ttk.Entry(topFrame, textvariable=self.date_start).pack(side=tk.LEFT) today = get_last_valid_trade_date() dt = datetime.datetime.strptime(today, '%Y%m%d') today = dt.strftime('%Y-%m-%d') self.date_start.set(today) tk.Label(topFrame, text="选股类型:").pack(side=tk.LEFT) self.screenTypeStr = tk.StringVar() cmbScreenType = ttk.Combobox(topFrame, width=15, textvariable=self.screenTypeStr, state='readonly') # Adding combobox drop down list cmbScreenType['values'] = ('平台突破', '均线附近') cmbScreenType.current(1) cmbScreenType.pack(side=tk.LEFT, padx=4) # cmbScreenType.bind("<<ComboboxSelected>>", self.on_cmb_screen_select) # 选股周期数 self.screenIntervalCountStr = tk.StringVar(value='25') # state=tk.DISABLED 默认禁止输入 self.screenIntervalCount = ttk.Entry( topFrame, width=10, textvariable=self.screenIntervalCountStr) self.screenIntervalCount.pack(side=tk.LEFT, padx=4) # 选股周期类型 self.screenIntervalTypeStr = tk.StringVar() cmbScreenInterval = ttk.Combobox( topFrame, width=8, textvariable=self.screenIntervalTypeStr, state='readonly') # Adding combobox drop down list cmbScreenInterval['values'] = ('日', '周', '月') cmbScreenInterval.current(0) cmbScreenInterval.pack(side=tk.LEFT, padx=4) # cmbScreenInterval.bind("<<ComboboxSelected>>", self.on_cmb_screen_interval_select) self.chkST = tk.IntVar() tk.Checkbutton(topFrame, text="包括ST", variable=self.chkST).pack(side=tk.LEFT, padx=4) self.chkTech = tk.IntVar() tk.Checkbutton(topFrame, text="包括科创板", variable=self.chkTech).pack(side=tk.LEFT, padx=4) self.btnStart = tk.Button(topFrame, text="选股", command=self.on_btn_start) self.btnStart.pack(side=tk.LEFT, padx=4) topFrame.pack(side=tk.TOP, fill=tk.BOTH) self.tipsStr = tk.StringVar() tk.Label(topFrame, textvariable=self.tipsStr, font=("simsun", 12)).pack(side=tk.LEFT) self.tipsStr.set('状态:准备...') # Progress bar widget self.progress = Progressbar(topFrame, orient=tk.HORIZONTAL, length=100, mode='determinate') # self.progress.pack(side=tk.LEFT, padx=4) # self.progress.pack_forget() # 列表框 self.frameReport = tk.Frame(self) self.sheet = Sheet(self.frameReport) self.sheet.enable_bindings(( # "single_select", # "single_select" or "toggle_select" # "drag_select", # enables shift click selection as well # "column_drag_and_drop", # "row_drag_and_drop", # "column_select", "row_select", "column_width_resize", "double_click_column_resize", # "row_width_resize", # "column_height_resize", # "arrowkeys", # "row_height_resize", # "double_click_row_resize", # "right_click_popup_menu", # "rc_select", # "rc_insert_column", # "rc_delete_column", # "rc_insert_row", # "rc_delete_row", # "hide_columns", # "copy", # "cut", # "paste", # "delete", # "undo", # "edit_cell" )) self.sheet.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.frameReport.pack(side=tk.TOP, fill=tk.BOTH, expand=1, pady=4) self.sheet.headers(['编码', '名称', '板块', '收盘价', '涨幅']) self.sheet.refresh() def on_btn_main_page(self): self.controller.show_frame('PageMain') pass def on_btn_start(self): if self.FLAG_THRD_SCREEN_DATA == self.flag & self.FLAG_THRD_SCREEN_DATA: return self.flag |= self.FLAG_THRD_SCREEN_DATA self.progress.pack(side=tk.LEFT, padx=4) # 获取数据线程,取一个放入队列,由另一个线程处理 # 周期参数 iInterval = int(self.screenIntervalCountStr.get()) # TODO 测试代码, iInterval = 43 type = 'd' if self.screenIntervalTypeStr.get() == '周': type = 'w' elif self.screenIntervalTypeStr.get() == '月': type = 'm' start_date = self.date_start.get().replace('-', '') # 多获取 10 组数据 thrd = threading.Thread(target=dbService.get_data_thread, args=( iInterval + 30, type, self.chkST.get(), self.chkTech.get(), self.queData, start_date, )) thrd.setDaemon(True) # 守护线程 thrd.start() cnt = self.sheet.get_total_rows() for i in range(cnt): self.sheet.delete_row(i) self.sheet.refresh() if self.screenTypeStr.get() == '平台突破': thrd = threading.Thread(target=self.screen_platform, args=(self.queData, )) thrd.setDaemon(True) # 守护线程 thrd.start() elif self.screenTypeStr.get() == '均线附近': thrd = threading.Thread(target=self.screen_ma_around, args=(self.queData, )) thrd.setDaemon(True) # 守护线程 thrd.start() pass def screen_platform(self, in_q): """ 平台突破 找出N天内创新高的股票, :return: """ self.btnStart['state'] = 'disabled' self.tipsStr.set('状态:正在读取数据,请耐心等待...') # 准备数据 iInterval = int(self.screenIntervalCountStr.get()) type = 'd' if self.screenIntervalTypeStr.get() == '周': type = 'w' elif self.screenIntervalTypeStr.get() == '月': type = 'm' self.progress['value'] = 5 # root.update_idletasks() # 避免中间缺数据 * 2 count = iInterval + 5 datas = dbService.get_data(count, type, self.chkST.get(), self.chkTech.get()) screenCount = 0 self.tipsStr.set('状态:正在选股,请耐心等待...') per_interval = len(datas) / 95 step_count = 0 progress_step = 5 pickup_list = [] for it in datas: step_count += 1 if step_count >= per_interval: step_count = 0 progress_step += 1 self.progress['value'] = progress_step # root.update_idletasks() result = platform_break_through(it, iInterval) if result: screenCount += 1 print(result) pickup_list.append(result) pickup_sorted = sorted(pickup_list, key=itemgetter(3), reverse=True) for it in pickup_sorted: self.sheet.insert_row(values=it) self.sheet.refresh() self.progress['value'] = 100 # root.update_idletasks() self.tipsStr.set('状态:共选出 {:d} 只股票'.format(screenCount)) self.flag &= (~self.FLAG_THRD_SCREEN_DATA) self.btnStart['state'] = 'normal' self.progress.pack_forget() print("screen_platform exit ==========") pass def screen_ma_around(self, in_q): """ 参数 120,2 表示 120 日均线,2%附近 ma120*0.98 < 收盘价 < ma120*1.2 :return: """ self.btnStart['state'] = 'disabled' screenCount = 0 self.tipsStr.set('状态:正在处理,请耐心等待...') # 准备数据 param = [(self.screenIntervalCountStr.get())] per_interval = get_code_count() / 95 step_count = 0 progress_step = 5 pickup_list = [] while True: try: it = in_q.get_nowait() except queue.Empty as e1: continue if it is None: break step_count += 1 if step_count >= per_interval: step_count = 0 progress_step += 1 self.progress['value'] = progress_step result = ma25_around(it, param) if result: screenCount += 1 print(result) self.sheet.insert_row(values=result) # self.sheet.refresh() # pickup_list.append(result) # pickup_sorted = sorted(pickup_list, key=itemgetter(3), reverse=True) # # for it in pickup_sorted: # self.sheet.insert_row(values=it) self.progress['value'] = 100 # root.update_idletasks() self.tipsStr.set('状态:共选出 {:d} 只股票'.format(screenCount)) self.flag &= (~self.FLAG_THRD_SCREEN_DATA) self.btnStart['state'] = 'normal' self.progress.pack_forget() self.progress['value'] = 0 print("screen_ma_around exit ==========") pass def tree_solution_selected(self, selected): print('tree_solution_selected items:', selected) pass
class PageDiary(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller topFrame = tk.Frame(self) self.btnMainPage = tk.Button(topFrame, text="主页面", command=self.on_btn_main_page).pack( side=tk.LEFT, padx=4) # 日期选择 # Calendar((x, y), 'ur').selection() 获取日期,x,y为点坐标 date_start_gain = lambda: [ self.str_date.set(date) for date in [CalendarCustom(None, 'ur').selection()] if date ] tk.Button(topFrame, text='日期:', command=date_start_gain).pack(side=tk.LEFT, padx=4) self.str_date = tk.StringVar() ttk.Entry(topFrame, textvariable=self.str_date, width=12).pack(side=tk.LEFT) today = datetime.date.today() self.str_date.set(today) tk.Label(topFrame, text="代码:").pack(side=tk.LEFT) self.strCode = tk.StringVar(value='') ttk.Entry(topFrame, width=10, textvariable=self.strCode).pack(side=tk.LEFT, padx=4) tk.Label(topFrame, text="名称:").pack(side=tk.LEFT) self.strName = tk.StringVar(value='') ttk.Entry(topFrame, width=10, textvariable=self.strName).pack(side=tk.LEFT, padx=4) tk.Label(topFrame, text="操作时间:").pack(side=tk.LEFT) self.strTime = tk.StringVar(value='') ttk.Entry(topFrame, width=8, textvariable=self.strTime).pack(side=tk.LEFT, padx=4) # 操作类型 self.operateTypeStr = tk.StringVar() cmbOperateType = ttk.Combobox(topFrame, width=8, textvariable=self.operateTypeStr, state='readonly') # Adding combobox drop down list cmbOperateType['values'] = ('买入', '卖出') cmbOperateType.current(0) cmbOperateType.pack(side=tk.LEFT, padx=4) cmbOperateType.bind("<<ComboboxSelected>>", self.on_cmb_operate_type_select) topFrame2 = tk.Frame(self) tk.Label(topFrame2, text="价格:").pack(side=tk.LEFT, padx=4, pady=2) self.strPrice = tk.StringVar(value='') ttk.Entry(topFrame2, width=8, textvariable=self.strPrice).pack(side=tk.LEFT, padx=4) tk.Label(topFrame2, text="数量:").pack(side=tk.LEFT) self.strAmount = tk.StringVar(value='') ttk.Entry(topFrame2, width=8, textvariable=self.strAmount).pack(side=tk.LEFT, padx=4) tk.Label(topFrame2, text="目标价位:").pack(side=tk.LEFT) self.strTargetPrice = tk.StringVar(value='') ttk.Entry(topFrame2, width=8, textvariable=self.strTargetPrice).pack(side=tk.LEFT, padx=4) tk.Label(topFrame2, text="止损价位:").pack(side=tk.LEFT) self.strStopPrice = tk.StringVar(value='') ttk.Entry(topFrame2, width=8, textvariable=self.strStopPrice).pack(side=tk.LEFT, padx=4) tk.Label(topFrame2, text="收益比:").pack(side=tk.LEFT) self.strProfitRate = tk.StringVar(value='') ttk.Entry(topFrame2, width=8, textvariable=self.strProfitRate).pack(side=tk.LEFT, padx=4) tk.Label(topFrame, text="盈利:").pack(side=tk.LEFT) self.strProfit = tk.StringVar(value='') ttk.Entry(topFrame, width=8, textvariable=self.strProfit).pack(side=tk.LEFT, padx=4) tk.Label(topFrame, text="备注:").pack(side=tk.LEFT) self.text = tk.Text(topFrame, width=50, height=4) self.text.pack(side=tk.LEFT, padx=4) tk.Button(topFrame2, text="添加", width=10, command=self.on_btn_add).pack(side=tk.LEFT, padx=4) topFrame.pack(side=tk.TOP, fill=tk.BOTH) topFrame2.pack(side=tk.TOP, fill=tk.BOTH) # 列表框 self.frameReport = tk.Frame(self) self.sheet = Sheet(self.frameReport) self.sheet.enable_bindings(( "single_select", # "single_select" or "toggle_select" "drag_select", # enables shift click selection as well "column_drag_and_drop", "row_drag_and_drop", "column_select", "row_select", "column_width_resize", "double_click_column_resize", "row_width_resize", "column_height_resize", "arrowkeys", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", "rc_insert_column", "rc_delete_column", "rc_insert_row", "rc_delete_row", "hide_columns", "copy", "cut", "paste", "delete", "undo", "edit_cell")) self.sheet.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.frameReport.pack(side=tk.TOP, fill=tk.BOTH, expand=1, pady=4) self.sheet.headers([ '日期', '编码', '名称', '操作时间', '操作方向', '价格', '数量', '目标价位', '止损', '收益比', '盈利', '备注' ]) self.sheet.refresh() def on_btn_main_page(self): self.controller.show_frame('PageMain') pass def on_btn_add(self): self.sheet.insert_row(values=(self.str_date.get(), self.strCode.get(), self.strName.get(), self.strTime.get(), self.operateTypeStr.get(), self.strPrice.get(), self.strAmount.get(), self.strTargetPrice.get(), self.strStopPrice.get(), self.strProfitRate.get(), self.strProfit.get(), self.text.get('0.0', tk.END))) self.sheet.refresh() pass def on_cmb_operate_type_select(self, event): if not self.operateTypeStr.get(): pass # self.nameEntered.delete(0, tk.END) # self.nameEntered.insert(0, self.measureTypeStr.get()) pass def tree_solution_selected(self, selected): print('tree_solution_selected items:', selected) pass