def main(): app = QApplication(sys.argv) data_hub = StockAnalysisSystem().get_data_hub_entry() update_table = StockAnalysisSystem().get_database_entry().get_update_table( ) dlg = WrapperQDialog(DataUpdateUi(data_hub, update_table)) dlg.exec()
def main(): app = QApplication(sys.argv) sas = StockAnalysisSystem() data_hub = sas.get_data_hub_entry() data_center = data_hub.get_data_center() dlg = WrapperQDialog(DataHubUi(data_center)) dlg.exec()
def run_calc_factor(): sas = StockAnalysisSystem() data_hub = sas.get_data_hub_entry() data_center = data_hub.get_data_center() # factor_center = sas.get_factor_center() # factor_center.reload_plugin() # df = factor_center.query('000021.SZSE', # ['货币资金/有息负债', '货币资金/短期负债', '流动比率', '速动比率'], # (default_since(), now()), {}, {}) # print(df) check_fields = [ '货币资金/有息负债', '货币资金/短期负债', '有息负债/资产总计', '有息负债/货币金融资产', '流动比率', '速动比率' ] df = data_center.query('Factor.Finance', '000021.SZSE', (default_since(), now()), fields=check_fields, readable=True) print(df) data_center.update_local_data('Factor.Finance', '000021.SZSE', (default_since(), now()), fields=check_fields) df = data_center.query('Factor.Finance', '000021.SZSE', (default_since(), now()), fields=check_fields, readable=True) print(df)
def run_console(): sas = StockAnalysisSystem() sas.check_initialize() # update_special() # update_local([ # # 'Market.SecuritiesInfo', # # # # 'Market.NamingHistory', # # 'Market.TradeCalender', # # # # 'Finance.Audit', # # 'Finance.BalanceSheet', # # 'Finance.IncomeStatement', # # 'Finance.CashFlowStatement', # # # # 'Stockholder.PledgeStatus', # # 'Stockholder.PledgeHistory', # # 'Stockholder.Statistics', # # # # 'TradeData.Stock.Daily', # # # # 'Market.IndexInfo', # # 'TradeData.Index.Daily', # ], True) # run_strategy() run_calc_factor() exit(0)
def config_ui(self): data_utility = StockAnalysisSystem().get_data_hub_entry( ).get_data_utility() stock_list = data_utility.get_stock_list() for stock_identity, stock_name in stock_list: self.__combo_name.addItem(stock_identity + ' | ' + stock_name) self.__combo_name.setEditable(True) self.setMinimumSize(QSize(600, 400))
def closeEvent(self, event): if StockAnalysisSystem().can_sys_quit(): StockAnalysisSystem().finalize() super().closeEvent(event) else: QMessageBox.information( self, QtCore.QCoreApplication.translate('main', '无法退出'), QtCore.QCoreApplication.translate('main', '有任务正在执行中,无法退出程序'), QMessageBox.Ok, QMessageBox.Ok) event.ignore()
def run_test(): sas = StockAnalysisSystem() data_hub = sas.get_data_hub_entry() data_center = data_hub.get_data_center() result = data_center.query('Finance.BalanceSheet', '600000.SSE', fields=['存货', '长期待摊费用', '拆出资金'], readable=True) assert '存货' in result.columns assert '拆出资金' in result.columns assert '长期待摊费用' in result.columns
def __init__(self, data_hub_entry: DataHubEntry, update_table: UpdateTableEx): super(DataUpdateUi, self).__init__() # Access entry self.__data_hub = data_hub_entry self.__data_center = self.__data_hub.get_data_center() self.__update_table = update_table # Table content self.__display_uri = [] self.__display_identities = None self.__display_table_lines = [] # Page related self.__page = 0 self.__item_per_page = 20 # For processing updating self.__processing_update_tasks = [] # Fot task counting self.__processing_update_tasks_count = [] self.task_finish_signal.connect(self.__on_task_done) self.refresh_finish_signal.connect(self.update_table_display) # Timer for update status self.__timer = QTimer() self.__timer.setInterval(1000) self.__timer.timeout.connect(self.on_timer) self.__timer.start() # UI related self.__info_panel = QLabel(DEFAULT_INFO) self.__table_main = TableViewEx() self.__button_head_page = QPushButton('<<') self.__button_prev_page = QPushButton('<') self.__button_next_page = QPushButton('>') self.__button_tail_page = QPushButton('>>') self.__button_upper_level = QPushButton('↑') self.__button_refresh = QPushButton('Refresh') self.__button_batch_auto_update = QPushButton('Auto Update Select') self.__button_batch_force_update = QPushButton('Force Update Select') self.init_ui() # Post update and cache stock list after posting RefreshTask data_utility = self.__data_hub.get_data_utility() StockAnalysisSystem().get_task_queue().add_observer(self) StockAnalysisSystem().get_task_queue().append_task( UpdateStockListTask(data_utility))
def __build_post_update_task(self, uri: str, identities: list or None, force: bool) -> bool: agent = self.__data_center.get_data_agent(uri) task = UpdateTask(self, self.__data_hub, self.__data_center, force) task.set_work_package(agent, identities) self.__processing_update_tasks.append(task) self.__processing_update_tasks_count.append(task) ret = StockAnalysisSystem().get_task_queue().append_task(task) # After updating market info, also update stock list cache if ret and (uri == 'Market.SecuritiesInfo' or uri == 'Market.IndexInfo'): data_utility = self.__data_hub.get_data_utility() StockAnalysisSystem().get_task_queue().append_task(UpdateStockListTask(data_utility)) return ret
def extension_window_init(self): sas = StockAnalysisSystem() extension_manager = sas.get_extension_manager() widgets_config = extension_manager.create_extensions_widgets(self) for widget, _config in widgets_config: self.add_sub_window(widget, _config.get('name'), { 'DockFloat': True, 'MenuPresent': True, 'DockArea': Qt.AllDockWidgetAreas, 'DockShow': _config.get('show', False), 'DockName': _config.get('name', 'Extension'), 'ActionTips': _config.get('name', 'Extension'), }, self.__menu_extension)
def __ui_to_config(self): sas = StockAnalysisSystem() config = sas.get_config() config.set('TS_TOKEN', self.__line_ts_token.text()) config.set('NOSQL_DB_HOST', self.__line_nosql_db_host.text()) config.set('NOSQL_DB_PORT', self.__line_nosql_db_port.text()) config.set('NOSQL_DB_USER', self.__line_nosql_db_user.text()) config.set('NOSQL_DB_PASS', self.__line_nosql_db_pass.text()) config.set('PROXY_PROTOCOL', self.__combo_web_proxy_protocol.currentText()) config.set('PROXY_HOST', self.__line_web_proxy_host.text()) config.save_config()
def execute_update_task(self): options = AnalysisTask.OPTION_CALC if not self.__check_force_calc.isChecked(): options |= AnalysisTask.OPTION_FROM_CACHE if self.__check_auto_cache.isChecked(): options |= AnalysisTask.OPTION_UPDATE_CACHE if self.__check_load_json.isChecked(): options |= AnalysisTask.OPTION_LOAD_JSON if self.__check_dump_json.isChecked(): options |= AnalysisTask.OPTION_DUMP_JSON if self.__check_load_dump_all.isChecked(): options |= AnalysisTask.OPTION_LOAD_DUMP_ALL if self.__check_attach_basic_index.isChecked(): options |= AnalysisTask.OPTION_ATTACH_BASIC_INDEX time_serial = (to_py_datetime(self.__datetime_time_since.dateTime()), to_py_datetime(self.__datetime_time_until.dateTime())) self.__timing_clock.reset() task = AnalysisTask(self, self.__strategy_entry, self.__data_hub_entry, self.__selector_list, self.__analyzer_list, time_serial, options, self.__result_output, self.__progress_rate) StockAnalysisSystem().get_task_queue().append_task(task)
def __config_to_ui(self): sas = StockAnalysisSystem() config = sas.get_config() if config.load_config(): text = config.get('TS_TOKEN') self.__line_ts_token.setText(text) text = config.get('NOSQL_DB_HOST') self.__line_nosql_db_host.setText(text) self.__line_nosql_db_port.setText(config.get('NOSQL_DB_PORT')) self.__line_nosql_db_user.setText(config.get('NOSQL_DB_USER')) self.__line_nosql_db_pass.setText(config.get('NOSQL_DB_PASS')) self.__combo_web_proxy_protocol.setEditText(config.get('PROXY_PROTOCOL')) self.__combo_web_proxy_protocol.setCurrentIndex(0) self.__line_web_proxy_host.setText(config.get('PROXY_HOST'))
def __on_task_done(self): StockAnalysisSystem().release_sys_quit() QMessageBox.information( self, QtCore.QCoreApplication.translate('main', '远行完成'), QtCore.QCoreApplication.translate( 'main', '策略运行完成,耗时' + str(self.__timing_clock.elapsed_s()) + '秒\n' + '报告生成路径:' + self.__result_output), QMessageBox.Ok, QMessageBox.Ok)
def __init__(self): super(MainWindow, self).__init__(hold_menu=True) # --------- init Member --------- self.__menu_config = None self.__menu_extension = None self.__translate = QtCore.QCoreApplication.translate self.__ui_root_path = os.path.dirname(os.path.abspath(__file__)) # ---------- Modules and Sub Window ---------- data_hub_entry = StockAnalysisSystem().get_data_hub_entry() strategy_entry = StockAnalysisSystem().get_strategy_entry() database_entry = StockAnalysisSystem().get_database_entry() update_table = database_entry.get_update_table() self.__data_hub_ui = DataHubUi(data_hub_entry.get_data_center()) self.__strategy_ui = AnalyzerUi(data_hub_entry, strategy_entry) self.__data_update_ui = DataUpdateUi(data_hub_entry, update_table) # Deprecated, use stock memo black list and tags # self.__gray_list_ui = XListTableUi(database_entry.get_gray_table(), '灰名单') # self.__black_list_ui = XListTableUi(database_entry.get_black_table(), '黑名单') # self.__focus_list_ui = XListTableUi(database_entry.get_focus_table(), '关注名单') # self.__alias_table_module = database_entry.get_alias_table() # self.__alias_table_ui = AliasTableUi(self.__alias_table_module) self.__task_queue_ui = TaskQueueUi( StockAnalysisSystem().get_task_queue()) # -------- UI Extenerion -------- extension_plugin = PluginManager() extension_plugin.add_plugin_path( os.path.join(self.__ui_root_path, 'Extension')) self.__extension_manager = ExtensionManager(StockAnalysisSystem(), extension_plugin) self.__extension_manager.init() # ---------- Deep init ---------- self.init_ui() self.init_menu() self.init_sub_window() # self.modules_init() # self.modules_ui_init() self.extension_window_init()
def __test_factor_for_one_stock(sas: StockAnalysisSystem, factors: [str]): if not isinstance(factors, (list, tuple)): factors = [factors] data_hub = sas.get_data_hub_entry() data_center = data_hub.get_data_center() df = data_center.query_from_factor('Factor.Finance', '000021.SZSE', (default_since(), now()), fields=factors, readable=True) print(df) assert df is not None and len(df) > 0 for fct in factors: assert fct in df.columns
def __config_control(self): self.setWindowTitle('System Config') self.__button_ok.clicked.connect(self.on_button_ok) self.__button_exit.clicked.connect(self.on_button_exit) self.__button_browse.clicked.connect(self.on_button_browse) self.__button_import.clicked.connect(self.on_button_import) self.__button_export.clicked.connect(self.on_button_export) # self.__text_information.setEnabled(False) self.__text_information.setStyleSheet("QLabel{border:2px solid rgb(0, 0, 0);}") self.__text_information.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) self.__combo_web_proxy_protocol.setEditable(True) self.__combo_web_proxy_protocol.addItem('HTTP_PROXY') self.__combo_web_proxy_protocol.addItem('HTTPS_PROXY') sas = StockAnalysisSystem() logs = sas.get_log_errors() self.__config_to_ui() self.__text_information.setText('\n'.join(logs))
def __test_factor_for_all_stock(sas: StockAnalysisSystem, factors: [str]): if not isinstance(factors, (list, tuple)): factors = [factors] data_hub = sas.get_data_hub_entry() data_center = data_hub.get_data_center() df = data_center.query_from_factor('Factor.Finance', '', (text_auto_time('2018-12-01'), text_auto_time('2018-12-31')), fields=factors, readable=True) print(df) assert df is not None and len(df) > 0 for fct in factors: assert fct in df.columns
def update_special(): sas = StockAnalysisSystem() data_hub = sas.get_data_hub_entry() data_center = data_hub.get_data_center() data_utility = data_hub.get_data_utility() df1 = data_center.query_from_plugin('Finance.Audit', '000021.SZSE', force=True) df2 = data_center.query_from_plugin('Finance.BalanceSheet', '000021.SZSE', force=True) df3 = data_center.query_from_plugin('Finance.IncomeStatement', '000021.SZSE', force=True) df4 = data_center.query_from_plugin('Finance.CashFlowStatement', '000021.SZSE', force=True) print(df1) print(df2) print(df3) print(df4)
def analysis(self, securities_list: [str]) -> [AnalysisResult]: clock_all = Clock() total_result = self.__strategy.analysis_advance( securities_list, self.__analyzer_list, self.__time_serial, self.__progress_rate, self.__options & AnalysisTask.OPTION_CALC != 0, self.__options & AnalysisTask.OPTION_FROM_CACHE != 0, self.__options & AnalysisTask.OPTION_UPDATE_CACHE != 0, self.__options & AnalysisTask.OPTION_FROM_JSON != 0, self.__options & AnalysisTask.OPTION_DUMP_JSON != 0, os.path.join(StockAnalysisSystem().get_project_path(), 'TestData')) print('All analysis finished, time spending: %ss' % clock_all.elapsed_s()) return total_result
def analysis(self, securities_list: [str]) -> [AnalysisResult]: clock_all = Clock() full_dump_path = os.path.join(StockAnalysisSystem().get_project_path(), 'TestData', 'analysis_result.json') if self.__options & AnalysisTask.OPTION_LOAD_JSON != 0 and \ self.__options & AnalysisTask.OPTION_LOAD_DUMP_ALL != 0: clock_load = Clock() total_result = self.__strategy.load_analysis_report(full_dump_path) print('Load all analysis result finished, Time spending: %ss' % clock_load.elapsed_s()) else: total_result = self.__strategy.analysis_advance( securities_list, self.__analyzer_list, self.__time_serial, self.__progress_rate, self.__options & AnalysisTask.OPTION_CALC != 0, self.__options & AnalysisTask.OPTION_FROM_CACHE != 0, self.__options & AnalysisTask.OPTION_UPDATE_CACHE != 0, self.__options & AnalysisTask.OPTION_LOAD_JSON != 0, self.__options & AnalysisTask.OPTION_DUMP_JSON != 0, os.path.join(StockAnalysisSystem().get_project_path(), 'TestData')) if self.__options & AnalysisTask.OPTION_DUMP_JSON != 0 and \ self.__options & AnalysisTask.OPTION_LOAD_DUMP_ALL != 0: clock_dump = Clock() name_dict_path = os.path.join( StockAnalysisSystem().get_project_path(), 'TestData', 'analyzer_names.json') self.__strategy.dump_analysis_report(total_result, full_dump_path) self.__strategy.dump_strategy_name_dict(name_dict_path) print('Dump all analysis result finished, Time spending: %ss' % clock_dump.elapsed_s()) print('All analysis finished, time spending: %ss' % clock_all.elapsed_s()) return total_result
def run_ui(): app = QApplication(sys.argv) sas = StockAnalysisSystem() sas.check_initialize() while not sas.is_initialized(): dlg = WrapperQDialog(ConfigUi(False)) dlg.exec() sas.check_initialize() main_wnd = MainWindow() main_wnd.show() sys.exit(app.exec())
def __init__(self, sas: StockAnalysisSystem): super(StockHistoryUi, self).__init__() self.__sas = sas self.__paint_securities = '' self.__paint_trade_data = None # Record set project_path = sas.get_project_path( ) if sas is not None else os.getcwd() self.__root_path = memo_path_from_project_path(project_path) self.__memo_recordset = RecordSet(self.__root_path) # vnpy chart self.__vnpy_chart = ChartWidget() # Memo editor self.__memo_editor = StockMemoEditor(self.__sas, self.__memo_recordset) # Timer for workaround signal fired twice self.__accepted = False self.__timer = QTimer() self.__timer.setInterval(1000) self.__timer.timeout.connect(self.on_timer) self.__timer.start() # Ui component data_utility = self.__sas.get_data_hub_entry().get_data_utility( ) if self.__sas is not None else None self.__combo_name = SecuritiesSelector(data_utility) self.__button_ensure = QPushButton('确定') self.__check_memo = QCheckBox('笔记') self.__check_volume = QCheckBox('成交量') self.__radio_adj_tail = QRadioButton('后复权') self.__radio_adj_head = QRadioButton('前复权') self.__radio_adj_none = QRadioButton('不复权') self.__group_adj = QButtonGroup(self) self.__radio_log_return = QRadioButton('对数收益') self.__radio_simple_return = QRadioButton('算术收益') self.__group_return = QButtonGroup(self) self.__init_ui() self.__config_ui()
def __init__(self): super(MainWindow, self).__init__(hold_menu=True) # --------- init Member --------- self.__menu_config = None self.__menu_extension = None self.__translate = QtCore.QCoreApplication.translate # ---------- Modules and Sub Window ---------- data_hub_entry = StockAnalysisSystem().get_data_hub_entry() strategy_entry = StockAnalysisSystem().get_strategy_entry() database_entry = StockAnalysisSystem().get_database_entry() update_table = database_entry.get_update_table() self.__data_hub_ui = DataHubUi(data_hub_entry.get_data_center()) self.__strategy_ui = AnalyzerUi(data_hub_entry, strategy_entry) self.__data_update_ui = DataUpdateUi(data_hub_entry, update_table) # Deprecated, use stock memo black list and tags # self.__gray_list_ui = XListTableUi(database_entry.get_gray_table(), '灰名单') # self.__black_list_ui = XListTableUi(database_entry.get_black_table(), '黑名单') # self.__focus_list_ui = XListTableUi(database_entry.get_focus_table(), '关注名单') # self.__alias_table_module = database_entry.get_alias_table() # self.__alias_table_ui = AliasTableUi(self.__alias_table_module) self.__task_queue_ui = TaskQueueUi( StockAnalysisSystem().get_task_queue()) # ---------- Deep init ---------- self.init_ui() self.init_menu() self.init_sub_window() # self.modules_init() # self.modules_ui_init() self.extension_window_init()
def execute_update_task(self): options = AnalysisTask.OPTION_CALC if not self.__check_force_calc.isChecked(): options |= AnalysisTask.OPTION_FROM_CACHE if self.__check_auto_cache.isChecked(): options |= AnalysisTask.OPTION_UPDATE_CACHE if self.__check_from_json.isChecked(): options |= AnalysisTask.OPTION_FROM_JSON if self.__check_dump_json.isChecked(): options |= AnalysisTask.OPTION_DUMP_JSON time_serial = (to_py_datetime(self.__datetime_time_since.dateTime()), to_py_datetime(self.__datetime_time_until.dateTime())) task = AnalysisTask(self, self.__strategy_entry, self.__data_hub_entry, self.__selector_list, self.__analyzer_list, time_serial, options, self.__result_output, self.__progress_rate) StockAnalysisSystem().get_task_queue().append_task(task)
def main(): app = QApplication(sys.argv) data_hub_entry = StockAnalysisSystem().get_data_hub_entry() strategy_entry = StockAnalysisSystem().get_strategy_entry() dlg = WrapperQDialog(AnalyzerUi(data_hub_entry, strategy_entry)) dlg.exec()
def update_table(self): self.__table_main.Clear() self.__table_main.SetColumn(DataUpdateUi.TABLE_HEADER) self.__table_main.AppendRow(['', '刷新中...', '', '', '', '', '', '', '']) task = RefreshTask(self) StockAnalysisSystem().get_task_queue().append_task(task)
def __init__(self, data_hub_entry: DataHubEntry, strategy_entry: StrategyEntry): super(AnalyzerUi, self).__init__() self.__data_hub_entry = data_hub_entry self.__strategy_entry = strategy_entry self.__analyzer_info = self.__strategy_entry.analyzer_info() # Thread and task related self.__selector_list = [] self.__analyzer_list = [] self.__result_output = StockAnalysisSystem().get_project_path() self.__timing_clock = Clock() self.__progress_rate = ProgressRate() self.task_finish_signal.connect(self.__on_task_done) # Timer for update status self.__timer = QTimer() self.__timer.setInterval(1000) self.__timer.timeout.connect(self.on_timer) self.__timer.start() # UI related group, layout = create_v_group_box('Selector') self.__group_selector = group self.__layout_selector = layout group, layout = create_v_group_box('Analyzer') self.__group_analyzer = group self.__layout_analyzer = layout group, layout = create_v_group_box('Option') self.__group_option = group self.__layout_option = layout group, layout = create_h_group_box('Result') self.__group_result = group self.__layout_result = layout self.__table_selector = TableViewEx() self.__table_analyzer = TableViewEx() # self.__radio_group_selector = QButtonGroup(self) # self.__radio_all = QRadioButton('All') # self.__radio_tags = QRadioButton('Tags') # self.__radio_manual = QRadioButton('Manual') # self.__table_preview = QTableWidget() self.__check_force_calc = QCheckBox('Force Calc') self.__check_auto_cache = QCheckBox('Cache Result') self.__check_load_json = QCheckBox('Load Json') self.__check_dump_json = QCheckBox('Dump Json') self.__check_load_dump_all = QCheckBox('Load/Dump All') self.__datetime_time_since = QDateTimeEdit(years_ago(5)) self.__datetime_time_until = QDateTimeEdit(now()) self.__edit_path = QLineEdit('analysis_report.xlsx') self.__button_browse = QPushButton('Browse') self.__button_selector = QPushButton('Selector') self.__button_analyzer = QPushButton('Analyzer') self.__button_result = QPushButton('Result') self.__button_run_strategy = QPushButton('Run Strategy') self.__check_attach_basic_index = QCheckBox('Attach Basic Index') self.init_ui() self.update_selector() self.update_analyzer()
def sas() -> StockAnalysisSystem: return StockAnalysisSystem()
def update_local(update_list: [str], force: bool = False): sas = StockAnalysisSystem() sas.check_initialize() data_hub = sas.get_data_hub_entry() data_center = data_hub.get_data_center() data_utility = data_hub.get_data_utility() if 'Market.SecuritiesInfo' in update_list: print('Updating SecuritiesInfo...') data_center.update_local_data('Market.SecuritiesInfo', force=force) if 'Market.NamingHistory' in update_list: print('Updating Naming History...') data_center.update_local_data('Market.NamingHistory', force=force) if 'Market.TradeCalender' in update_list: print('Updating TradeCalender...') data_center.update_local_data('Market.TradeCalender', exchange='SSE', force=force) stock_list = data_utility.get_stock_list() start_total = time.time() print('Updating Finance Data for All A-SHARE Stock.') counter = 0 for stock_identity, name in stock_list: start_single = time.time() print('Updating Finance Data for ' + stock_identity + ' [' + name + ']') if 'Finance.Audit' in update_list: data_center.update_local_data('Finance.Audit', stock_identity, force=force) if 'Finance.BalanceSheet' in update_list: data_center.update_local_data('Finance.BalanceSheet', stock_identity, force=force) if 'Finance.IncomeStatement' in update_list: data_center.update_local_data('Finance.IncomeStatement', stock_identity, force=force) if 'Finance.CashFlowStatement' in update_list: data_center.update_local_data('Finance.CashFlowStatement', stock_identity, force=force) if 'TradeData.Stock.Daily' in update_list: data_center.update_local_data('TradeData.Stock.Daily', stock_identity, force=force) if 'Stockholder.PledgeStatus' in update_list: data_center.update_local_data('Stockholder.PledgeStatus', stock_identity, force=force) if 'Stockholder.PledgeHistory' in update_list: data_center.update_local_data('Stockholder.PledgeHistory', stock_identity, force=force) if 'Stockholder.Statistics' in update_list: data_center.update_local_data('Stockholder.Statistics', stock_identity, force=force) counter += 1 print('Done (%s / %s). Time Spending: %s s' % (counter, len(stock_list), time.time() - start_single)) if 'Market.IndexInfo' in update_list: print('Updating IndexInfo...') data_center.update_local_data('Market.IndexInfo', force=force, dump_flag=True) index_dict = data_utility.get_support_index_identities() index_list = list(index_dict.keys()) print('Updating Index Data for All Support Market.') counter = 0 for index_identity, name in index_list: start_single = time.time() if 'TradeData.Index.Daily' in update_list: data_center.update_local_data('TradeData.Index.Daily', index_identity, force=force) counter += 1 print('Done (%s / %s). Time Spending: %s s' % (counter, len(index_list), time.time() - start_single)) print('Update Finance Data for All A-SHARE Stock Done. Time Spending: ' + str(time.time() - start_total) + 's')