def tree_node_selected(self, selected, un_selected): """ 树节点选中事件 :param selected: :param un_selected: :return: """ if selected.indexes() is None or len(selected.indexes()) == 0: return index = selected.indexes()[0] pk_field = index.data(Category.IDRole) # 查询一下是哪张表 table_name = None pk_table_meta = None is_redis = False instance = DataCenter.get_instance() query_table_name = "select table_name, ana_category.pk_tablemeta, is_redis from ana_category join table_meta " \ "on ana_category.pk_tablemeta=table_meta.pk_tablemeta where pk_category='" query_table_name = query_table_name + str(pk_field) + "'" ret_val = instance.common_query(query_table_name) if len(ret_val) > 0: table_name = ret_val[0][0] pk_table_meta = ret_val[0][1] is_redis = ret_val[0][2] == 'Y' self.ana_result_type(table_name, pk_table_meta)
def calculate_period_win(self, period, calculate_data): period_field_map = { 3: "three_day", 7: 'seven_day', 30: 'one_month', 60: 'two_month' } if len(calculate_data) == 0: return for item in calculate_data: # 首先查询出最近历史的数据 data_center = DataCenter.get_instance() query_sql = "select close from stock_base_info where ts_code='" query_sql = query_sql + item[0] + "' and trade_date > '" query_sql = query_sql + item[1].strftime("%Y%m%d") + "' order by trade_date limit 70" base_infos = data_center.common_query(query_sql) for single_period in period: if len(base_infos) >= single_period: target_day_close = base_infos[single_period - 1][0] in_price = item[2] win_pct = (target_day_close - in_price) / target_day_close * 100 win_pct = win_pct update_sql = "update " + self.table_name + " set " update_sql = update_sql + period_field_map[single_period] + "='" + str(win_pct) + "'" update_sql = update_sql + " where pk_period_verify='" + str(item[3]) + "'" data_center.common_query(update_sql) # FIXME -- 此处写死吧!!!! if single_period == 60: update_sql = "update " + self.table_name + " set finished=1 where pk_period_verify=" update_sql = update_sql + str(item[3]) + "'" data_center.common_query(update_sql)
def __call__(self, *args, **kwargs): self.data_center = DataCenter() if len(self.ts_codes) == 0: return result = pandas.DataFrame(columns=('ts_code', 'in_price', 'in_date', 'origin_from', 'in_reason', 'finished', 'manual')) for ts_code in self.ts_codes: field_suffix = "_" + str(self.fast) + "_" + str( self.slow) + "_" + str(self.signal) macd_field_name = 'MACD' + field_suffix histogram_field_name = 'MACDh' + field_suffix signal_field_name = 'MACDs' + field_suffix base_infos = self.data_center.fetch_base_data(ts_code) if base_infos is None or len(base_infos) == 0: continue close = base_infos['close'] macd_ret = ta.macd(close, self.fast, self.slow, signal=self.signal) if len(macd_ret) < 2: continue rst_length = len(macd_ret) start_index = min(rst_length, self.BUY_SIGNAL_PERIOD) start_index = rst_length - start_index low_flag = False for i in range(start_index, rst_length): if macd_ret.at[i, macd_field_name] is not None and macd_ret.at[i, signal_field_name] is not None and \ macd_ret.at[i, macd_field_name] < macd_ret.at[i, signal_field_name]: low_flag = True else: if low_flag: now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') temp_dict = { 'ts_code': ts_code, 'in_price': close[i], 'in_date': base_infos.at[start_index, 'trade_date'], 'origin_from': 'macd', 'in_reason': 'macd金叉', 'finished': 0, 'manual': 0 } result = result.append(temp_dict, ignore_index=True) return result
def init_data_from_db(self): # 获取没有结束掉的股票 query_sql = "select ts_code, in_date, in_price, pk_period_verify from period_verify where finished='0'" data_center = DataCenter.get_instance() ret_data = data_center.common_query(query_sql) # 首先计算一下各个阶段的收益 period = [3, 7, 30, 60] self.calculate_period_win(period, ret_data) super().init_data_from_db()
def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # 树结构初始化 # model = QFileSystemModel() # model.setRootPath(QDir.currentPath()) # # tree = QTreeView(self) # tree.setFixedWidth(200) # tree.setFixedHeight(600) # tree.setModel(model) # 设置相关的监听事件 self.tree_model = CategoryTreeModel() self.ui.treeView.setModel(self.tree_model) self.ui.treeView.selectionModel().selectionChanged.connect( self.tree_node_selected) self.ui.tableView.doubleClicked.connect(self.table_row_double_clicked) self.table_model = MainTableModel() self.ui.tableView.setModel(self.table_model) self.ui.tableView.setSortingEnabled(True) # 设置表格的邮件菜单 self.ui.tableView.setContextMenuPolicy( PySide2.QtCore.Qt.ActionsContextMenu) # 具体菜单项 manual_flag = QAction(self.ui.tableView) manual_flag.setText("标记为手动") manual_flag.triggered.connect(self.mark_manual) # 点击菜单中的“发送控制代码”执行的函数 # tableView 添加具体的右键菜单 self.ui.tableView.addAction(manual_flag) # K线图组件初始化 data_center = DataCenter() self.view_model = StockChartModel(data_center) self.ui.openGLWidget.set_model(self.view_model) # 创建一个弹出窗,然后显示单根K线的信息 display = InfoDisplay(self) display.setModal(PySide2.QtCore.Qt.NonModal) display.show() self.ui.openGLWidget.mouse_on_changed.connect( display.stock_info_changed) # 相关按钮的初始化 self.ui.actionrefresh.triggered.connect(self.refresh_stock_list) self.ui.actiondaily_info.triggered.connect(self.fetch_daily_info)
def fetch_daily_info(): data_center = DataCenter.get_instance() last_record_day = data_center.common_query( "select trade_date from stock_base_info order by trade_date desc limit 1" ) last_record_day = last_record_day[0][0] last_record_day = datetime.date(int(last_record_day[0:4]), int(last_record_day[4:6]), int(last_record_day[6:8])) last_record_day += datetime.timedelta(days=1) last_record_day = last_record_day.strftime("%Y%m%d") print("last record day is " + last_record_day) data_center.fetch_all_daily_info_until_now(trade_date=last_record_day)
def __call__(self, *args, **kwargs): self.data_center = DataCenter() if self.stock_codes is None or len(self.stock_codes) == 0: return # 统计所有的股票,在:param peirod期间之内的盈利情况 sum_dict = { 'win_pct_less_than_50': 0, 'win_pct_bigger_than_50': 0, 'win_pct_bigger_than_60': 0, 'win_pct_bigger_than_70': 0, } for stock_code in self.stock_codes: base_infos = self.data_center.fetch_base_data(stock_code) shift_close = base_infos['close'].shift(self.period) win_pct = (shift_close - base_infos['close']) / base_infos['close'] base_infos['win_pct'] = win_pct base_infos.drop(['vol', 'amount', 'pre_close', 'change'], axis=1, inplace=True) if not base_infos.empty: count_percent = len(base_infos[base_infos['win_pct'] > 0]) / len(base_infos) sum_dict['win_pct_less_than_50'] = sum_dict['win_pct_less_than_50'] + 1 if count_percent < 0.5 \ else sum_dict['win_pct_less_than_50'] sum_dict['win_pct_bigger_than_50'] = sum_dict['win_pct_bigger_than_50'] + 1 if count_percent >= 0.5 \ else sum_dict['win_pct_bigger_than_50'] sum_dict['win_pct_bigger_than_60'] = sum_dict['win_pct_bigger_than_60'] + 1 if count_percent >= 0.6 \ else sum_dict['win_pct_bigger_than_60'] sum_dict['win_pct_bigger_than_70'] = sum_dict['win_pct_bigger_than_70'] + 1 if count_percent >= 0.7 \ else sum_dict['win_pct_bigger_than_70'] sum_str = "win count percent is " + str(count_percent) file_name = "period_simulate_" + stock_code now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') file_name += '_' + now_time_str file_name += '.csv' FileOutput.csv_output(None, base_infos, file_name, spe_dir_name=self.judge_out_name, extra_content=sum_str) return sum_dict
def __init__(self, parent=None): super().__init__(parent) self.root_item: TreeItem = TreeItem() # 做初始化逻辑 data_center = DataCenter.get_instance() query_sql = "select * from ana_category" ret_val = data_center.common_query(query_sql) category_list = [] for item in ret_val: temp_category = Category() temp_category.id = item[3] temp_category.parent_id = item[1] temp_category.category_name = item[2] category_list.append(temp_category) self.root_item.init_with_data(category_list)
def merge_table_data(data_center: DataCenter, tables): """ 从多个表格里面查询出来股票编码,然后做个交集 :param data_center: :param tables: :return: """ if tables is None or len(tables) == 0: return pandas.Series() ret_series = pandas.Series() for item in tables: sql = "select ts_code from " + item temp_data = data_center.common_query_to_pandas(sql) temp_series = temp_data['ts_code'] ret_series = ret_series.append(temp_series, ignore_index=True) return ret_series.unique()
def init_data_from_db(self): """ 通用的从数据库查询数据的结果处理类 :return: """ data_center = DataCenter.get_instance() query_sql = "select table_name, is_redis from table_meta where pk_tablemeta='" query_sql = query_sql + str(self.table_meta) + "'" table_meta = data_center.common_query(query_sql) if table_meta is None or len(table_meta) == 0: return self.db_table_name = table_meta[0][0] is_redis = table_meta[0][1] == 'Y' if is_redis: return query_sql = "select column_name, display_name, columntype from table_column where pk_tablemeta='" query_sql = query_sql + str( self.table_meta) + "' order by display_order" table_infos = data_center.common_query(query_sql) for item in table_infos: self.db_columns.append(item[0]) self.display_head.append(item[1]) self.column_type.append(item[2]) if len(self.db_columns) == 0: return # 此处特殊处理一下ts_name字段 query_sql = "select stock_list.name as ts_name, " for item in self.db_columns: if item == 'ts_name': continue real_item = self.db_table_name + ".ts_code " if item == 'ts_code' else item query_sql = query_sql + real_item + "," query_sql = query_sql[:-1] query_sql = query_sql + " from " + self.db_table_name query_sql = query_sql + " left join stock_list on stock_list.ts_code=" + self.db_table_name + ".ts_code " if self.filter is not None: query_sql = query_sql + " " + self.filter data = data_center.common_query(query_sql) for item in data: self.data.append(list(item)) # 处理一下数据类型问题 self.process_data_type()
def select_data(self): """ 查询数据,更新表格 :return: """ query_sql = "" for i in range(len(self.select_columns)): query_sql = query_sql + self.select_columns[i] + "," query_sql = query_sql + self.select_columns[len(self.select_columns) - 1] query_sql = query_sql + " from " + self.table_name + " " query_sql = query_sql + self.filter data_center = DataCenter.get_instance() query_rst = data_center.common_query(query_sql) for item in query_rst: self.table_data.append(item) super().endResetModel()
class Simulate: BUY_FLAG = 1 SOLD_FLAG = -1 DO_NOTHING = 0 MULTI_INDI_BETWEEN = 5 # 如果有多种指标,多少天之内均发出买入信号就决定买入 def __init__(self, stock_codes, judge_out_name, judge_time=None): self.initial_mny = None self.stock_codes = stock_codes self.judge_time = judge_time self.hold_num = 0 # 持仓手数 self.left_mny = 0 # 剩余金额 self.judge_out_name = judge_out_name # 判定输出目录名称 def set_registry(self, judge_time): self.judge_time = judge_time def set_judge_name(self, judge_name): self.judge_out_name = judge_name def set_init_mny(self, init_mny): """ 设置初始金额,金额为RMB :param init_mny: :return: """ self.initial_mny = init_mny self.left_mny = init_mny def reset(self): self.left_mny = self.initial_mny self.hold_num = 0 def __call__(self, *args, **kwargs): # TODO -- 看一下Python的数值计算方式,是否有小数??? self.data_center = DataCenter() final_sum_dict = { 'win_num': 0, 'lose_num': 0, 'max_win_pct': 0, 'max_lost_pct': 0, 'ave_win_mny': 0 } trade_rst = pandas.DataFrame(columns=('ts_code', 'trade_times', 'final_win', 'win_pct')) for stock_code in self.stock_codes: trade_rst_dict = { 'ts_code': stock_code, 'trade_times': 0, 'final_win': 0, 'win_pct': 0 } base_infos = self.data_center.fetch_base_data(stock_code) if base_infos is None or len(base_infos) == 0: continue ret_time = [] for item in self.judge_time: ret_time.append(item(base_infos)) if ret_time is None or len(ret_time) == 0: continue detail_trade_info = pandas.DataFrame( columns=('ts_code', 'curr_close', 'trade_date', 'trade_num', 'hold_num', 'hold_mny', 'total_mny')) if len(ret_time[0]) != len(base_infos): print("Not equals!!!") for i in range(len(ret_time[0])): # 判定是否是买入时机 operate_flag = self.DO_NOTHING temp_buy_pct = 0.1 for item in ret_time: # 从当前往前5天之内是否有发出过买入信号,如果有,就算有 start_index = i - self.MULTI_INDI_BETWEEN start_index = 0 if start_index < 0 else start_index temp_val = self.DO_NOTHING for j in range(start_index, i + 1): if item.at[j, 'flag'] == self.BUY_FLAG: temp_val = self.BUY_FLAG temp_buy_pct = item.at[j, 'percent'] if 0 < item.at[j, 'percent'] < temp_buy_pct \ else temp_buy_pct break elif item.at[j, 'flag'] == self.SOLD_FLAG: temp_val = self.SOLD_FLAG temp_buy_pct = item.at[j, 'percent'] if 0 < item.at[j, 'percent'] < temp_buy_pct \ else temp_buy_pct break if operate_flag == self.DO_NOTHING or operate_flag == temp_val: operate_flag = temp_val continue else: operate_flag = self.DO_NOTHING break if operate_flag == self.BUY_FLAG: # 默认买入10% buy_pct = temp_buy_pct buy_mny = self.initial_mny * buy_pct buy_mny = self.left_mny if self.left_mny < buy_mny else buy_mny buy_num = buy_mny / base_infos.at[i, 'close'] self.hold_num = self.hold_num + buy_num self.left_mny = self.left_mny - buy_mny hold_mny = self.hold_num * base_infos.at[i, 'close'] # 记录买入信息 temp_dict = { 'ts_code': stock_code, 'trade_date': base_infos.at[i, 'trade_date'], 'trade_num': buy_num, 'hold_num': self.hold_num, 'hold_mny': hold_mny, 'total_mny': self.left_mny + hold_mny, 'curr_close': base_infos.at[i, 'close'] } detail_trade_info = detail_trade_info.append(temp_dict, ignore_index=True) trade_rst_dict['trade_times'] = trade_rst_dict['trade_times'] + 1 elif operate_flag == self.SOLD_FLAG: # 默认卖出持仓数量的10% sold_pct = temp_buy_pct sold_num = self.hold_num * sold_pct sold_num = sold_num / 100 * 100 self.hold_num = self.hold_num - sold_num sold_mny = sold_num * base_infos.at[i, 'close'] self.left_mny = self.left_mny + sold_mny hold_mny = self.hold_num * base_infos.at[i, 'close'] # 记录卖出信息 temp_dict = { 'ts_code': stock_code, 'trade_date': base_infos.at[i, 'trade_date'], 'trade_num': sold_num, 'hold_num': self.hold_num, 'hold_mny': hold_mny, 'total_mny': self.left_mny + hold_mny, 'curr_close': base_infos.at[i, 'close'] } detail_trade_info = detail_trade_info.append(temp_dict, ignore_index=True) trade_rst_dict['trade_times'] = trade_rst_dict['trade_times'] + 1 if not detail_trade_info.empty: file_name = "simulate_" + str(stock_code) now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') file_name += '_' + now_time_str file_name += '.csv' FileOutput.csv_output(None, detail_trade_info, file_name, spe_dir_name=self.judge_out_name) else: print("no such stock!") self.reset() if detail_trade_info.empty: continue # 统计该只股票的最终盈利 last_win = detail_trade_info.at[(len(detail_trade_info) - 1), 'total_mny'] - self.initial_mny last_win_pct = last_win / self.initial_mny trade_rst_dict['final_win'] = last_win trade_rst_dict['win_pct'] = last_win_pct trade_rst = trade_rst.append(trade_rst_dict, ignore_index=True) # 统计多只股票的汇总 final_sum_dict['win_num'] = final_sum_dict['win_num'] + 1 if last_win > 0 else final_sum_dict['win_num'] final_sum_dict['lose_num'] = final_sum_dict['lose_num'] + 1 if last_win <= 0 else final_sum_dict['lose_num'] final_sum_dict['max_win_pct'] = last_win_pct if last_win_pct > final_sum_dict['max_win_pct'] else \ final_sum_dict['max_win_pct'] final_sum_dict['max_lost_pct'] = last_win_pct if last_win_pct <= final_sum_dict['max_lost_pct'] else \ final_sum_dict['max_lost_pct'] sum_str = "获利数量:" + str(final_sum_dict['win_num']) + " 损失数量:" + str(final_sum_dict['lose_num']) \ + " 最大获利百分比:" + str(final_sum_dict['max_win_pct']) + " 最大损失百分比:" + \ str(final_sum_dict['max_lost_pct']) if not trade_rst.empty: file_name = "trade_group_" + self.stock_codes[0] now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') file_name += '_' + now_time_str file_name += '.csv' FileOutput.csv_output(None, trade_rst, file_name, spe_dir_name=self.judge_out_name, extra_content=sum_str) return final_sum_dict
def refresh_stock_list(): data_center = DataCenter.get_instance() data_center.refresh_stock_list()