hikyuu 2.6.2__py3-none-win_amd64.whl → 2.6.5__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. hikyuu/__init__.py +1 -1
  2. hikyuu/__init__.pyi +28 -13
  3. hikyuu/analysis/__init__.pyi +20 -0
  4. hikyuu/analysis/analysis.pyi +21 -1
  5. hikyuu/core.pyi +22 -2
  6. hikyuu/cpp/core310.pyd +0 -0
  7. hikyuu/cpp/core310.pyi +499 -50
  8. hikyuu/cpp/core311.pyd +0 -0
  9. hikyuu/cpp/core311.pyi +499 -50
  10. hikyuu/cpp/core312.pyd +0 -0
  11. hikyuu/cpp/core312.pyi +499 -50
  12. hikyuu/cpp/core313.pyd +0 -0
  13. hikyuu/cpp/core313.pyi +499 -50
  14. hikyuu/cpp/core39.pyd +0 -0
  15. hikyuu/cpp/core39.pyi +499 -50
  16. hikyuu/cpp/hikyuu.dll +0 -0
  17. hikyuu/cpp/hikyuu.lib +0 -0
  18. hikyuu/data/common.py +1 -1
  19. hikyuu/data/common_mysql.py +19 -0
  20. hikyuu/data/common_pytdx.py +2 -0
  21. hikyuu/data/common_sqlite3.py +1 -0
  22. hikyuu/data/hku_config_template.py +14 -0
  23. hikyuu/data/mysql_upgrade/0028.sql +95 -0
  24. hikyuu/data/pytdx_to_h5.py +53 -13
  25. hikyuu/data/pytdx_to_mysql.py +42 -9
  26. hikyuu/data/pytdx_to_taos.py +736 -0
  27. hikyuu/data/sqlite_upgrade/0028.sql +97 -0
  28. hikyuu/draw/__init__.pyi +1 -1
  29. hikyuu/draw/drawplot/__init__.pyi +1 -1
  30. hikyuu/draw/drawplot/bokeh_draw.pyi +24 -9
  31. hikyuu/draw/drawplot/echarts_draw.pyi +24 -9
  32. hikyuu/draw/drawplot/matplotlib_draw.py +26 -4
  33. hikyuu/draw/drawplot/matplotlib_draw.pyi +24 -9
  34. hikyuu/draw/kaufman.py +2 -2
  35. hikyuu/draw/kaufman.pyi +2 -2
  36. hikyuu/examples/notebook/001-overview.ipynb +65 -100
  37. hikyuu/examples/notebook/004-IndicatorOverview.ipynb +34 -32
  38. hikyuu/examples/notebook/007-SystemDetails.ipynb +64 -50
  39. hikyuu/examples/notebook/010-Portfolio.ipynb +120 -124
  40. hikyuu/extend.py +1 -1
  41. hikyuu/extend.pyi +24 -9
  42. hikyuu/fetcher/stock/zh_block_em.py +349 -5
  43. hikyuu/fetcher/stock/zh_stock_a_pytdx.py +2 -1
  44. hikyuu/gui/HikyuuTDX.py +47 -24
  45. hikyuu/gui/data/ImportBlockInfoTask.py +1 -1
  46. hikyuu/gui/data/ImportHistoryFinanceTask.py +48 -44
  47. hikyuu/gui/data/ImportPytdxTimeToH5Task.py +3 -1
  48. hikyuu/gui/data/ImportPytdxToH5Task.py +4 -2
  49. hikyuu/gui/data/ImportPytdxTransToH5Task.py +3 -1
  50. hikyuu/gui/data/ImportWeightToSqliteTask.py +2 -1
  51. hikyuu/gui/data/ImportZhBond10Task.py +1 -1
  52. hikyuu/gui/data/MainWindow.py +123 -106
  53. hikyuu/gui/data/UsePytdxImportToH5Thread.py +7 -3
  54. hikyuu/gui/data/UseQmtImportToH5Thread.py +1 -0
  55. hikyuu/gui/data/UseTdxImportToH5Thread.py +2 -1
  56. hikyuu/hub.pyi +6 -6
  57. hikyuu/include/hikyuu/Block.h +20 -0
  58. hikyuu/include/hikyuu/KQuery.h +8 -0
  59. hikyuu/include/hikyuu/MarketInfo.h +6 -0
  60. hikyuu/include/hikyuu/Stock.h +1 -1
  61. hikyuu/include/hikyuu/StockManager.h +6 -0
  62. hikyuu/include/hikyuu/data_driver/BaseInfoDriver.h +35 -0
  63. hikyuu/include/hikyuu/indicator/Indicator.h +5 -0
  64. hikyuu/include/hikyuu/indicator/IndicatorImp.h +8 -3
  65. hikyuu/include/hikyuu/indicator/build_in.h +1 -0
  66. hikyuu/include/hikyuu/indicator/crt/BARSLASTCOUNT.h +33 -0
  67. hikyuu/include/hikyuu/indicator/crt/INSUM.h +5 -10
  68. hikyuu/include/hikyuu/indicator/crt/RSI.h +2 -18
  69. hikyuu/include/hikyuu/indicator/imp/IBarsLastCount.h +27 -0
  70. hikyuu/include/hikyuu/plugin/backtest.h +3 -2
  71. hikyuu/include/hikyuu/plugin/device.h +6 -3
  72. hikyuu/include/hikyuu/plugin/extind.h +150 -0
  73. hikyuu/include/hikyuu/plugin/interface/BackTestPluginInterface.h +2 -1
  74. hikyuu/include/hikyuu/plugin/interface/DevicePluginInterface.h +1 -0
  75. hikyuu/include/hikyuu/plugin/interface/ExtendIndicatorsPluginInterface.h +26 -0
  76. hikyuu/include/hikyuu/plugin/interface/TMReportPluginInterface.h +80 -0
  77. hikyuu/include/hikyuu/plugin/interface/plugins.h +4 -0
  78. hikyuu/include/hikyuu/strategy/BrokerTradeManager.h +7 -5
  79. hikyuu/include/hikyuu/strategy/Strategy.h +22 -9
  80. hikyuu/include/hikyuu/trade_manage/OrderBrokerBase.h +11 -4
  81. hikyuu/include/hikyuu/trade_manage/Performance.h +17 -9
  82. hikyuu/include/hikyuu/trade_manage/PositionExtInfo.h +92 -0
  83. hikyuu/include/hikyuu/trade_manage/PositionRecord.h +7 -1
  84. hikyuu/include/hikyuu/trade_manage/TradeManager.h +8 -5
  85. hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +66 -5
  86. hikyuu/include/hikyuu/trade_manage/TradeRecord.h +9 -1
  87. hikyuu/include/hikyuu/trade_sys/multifactor/MultiFactorBase.h +8 -5
  88. hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_EqualWeight.h +4 -1
  89. hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_ICIRWeight.h +4 -1
  90. hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_ICWeight.h +4 -1
  91. hikyuu/include/hikyuu/trade_sys/multifactor/crt/MF_Weight.h +4 -1
  92. hikyuu/include/hikyuu/trade_sys/multifactor/imp/EqualWeightMultiFactor.h +2 -1
  93. hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICIRMultiFactor.h +2 -1
  94. hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICMultiFactor.h +2 -1
  95. hikyuu/include/hikyuu/trade_sys/multifactor/imp/WeightMultiFactor.h +1 -1
  96. hikyuu/include/hikyuu/trade_sys/selector/crt/SE_Optimal.h +8 -0
  97. hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/OptimalEvaluateSelector.h +28 -0
  98. hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/OptimalSelectorBase.h +1 -0
  99. hikyuu/include/hikyuu/trade_sys/system/TradeRequest.h +7 -4
  100. hikyuu/include/hikyuu/trade_sys/system/imp/WalkForwardTradeManager.h +17 -13
  101. hikyuu/include/hikyuu/utilities/DllLoader.h +226 -0
  102. hikyuu/include/hikyuu/utilities/datetime/Datetime.h +20 -0
  103. hikyuu/include/hikyuu/utilities/datetime/TimeDelta.h +6 -0
  104. hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +10 -10
  105. hikyuu/include/hikyuu/utilities/thread/{MQStealThreadPool.h → GlobalMQStealThreadPool.h} +12 -12
  106. hikyuu/include/hikyuu/utilities/thread/GlobalMQThreadPool.h +271 -0
  107. hikyuu/include/hikyuu/utilities/thread/{StealThreadPool.h → GlobalStealThreadPool.h} +11 -10
  108. hikyuu/include/hikyuu/utilities/thread/GlobalThreadPool.h +224 -0
  109. hikyuu/include/hikyuu/utilities/thread/InterruptFlag.h +16 -0
  110. hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +40 -77
  111. hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +31 -59
  112. hikyuu/include/hikyuu/utilities/thread/ThreadSafeQueue.h +4 -0
  113. hikyuu/include/hikyuu/utilities/thread/algorithm.h +9 -9
  114. hikyuu/include/hikyuu/utilities/thread/thread.h +4 -0
  115. hikyuu/include/hikyuu/version.h +4 -4
  116. hikyuu/plugin/backtest.dll +0 -0
  117. hikyuu/plugin/dataserver.dll +0 -0
  118. hikyuu/plugin/device.dll +0 -0
  119. hikyuu/plugin/extind.dll +0 -0
  120. hikyuu/plugin/import2hdf5.dll +0 -0
  121. hikyuu/plugin/tmreport.dll +0 -0
  122. hikyuu/trade_manage/__init__.pyi +23 -8
  123. hikyuu/trade_manage/broker.py +8 -8
  124. hikyuu/trade_manage/broker.pyi +4 -4
  125. hikyuu/trade_manage/broker_easytrader.py +3 -3
  126. hikyuu/trade_manage/broker_easytrader.pyi +2 -2
  127. hikyuu/trade_manage/broker_mail.py +2 -2
  128. hikyuu/trade_manage/broker_mail.pyi +2 -2
  129. hikyuu/trade_manage/trade.pyi +23 -8
  130. hikyuu/util/singleton.pyi +1 -1
  131. {hikyuu-2.6.2.dist-info → hikyuu-2.6.5.dist-info}/METADATA +4 -3
  132. {hikyuu-2.6.2.dist-info → hikyuu-2.6.5.dist-info}/RECORD +136 -121
  133. {hikyuu-2.6.2.dist-info → hikyuu-2.6.5.dist-info}/LICENSE +0 -0
  134. {hikyuu-2.6.2.dist-info → hikyuu-2.6.5.dist-info}/WHEEL +0 -0
  135. {hikyuu-2.6.2.dist-info → hikyuu-2.6.5.dist-info}/entry_points.txt +0 -0
  136. {hikyuu-2.6.2.dist-info → hikyuu-2.6.5.dist-info}/top_level.txt +0 -0
hikyuu/gui/HikyuuTDX.py CHANGED
@@ -34,7 +34,7 @@ from hikyuu.gui.data.CollectSpotThread import CollectSpotThread
34
34
  from hikyuu.gui.data.SchedImportThread import SchedImportThread
35
35
  from hikyuu.gui.spot_server import release_nng_senders
36
36
 
37
- from hikyuu import can_upgrade, get_last_version, fetch_trial_license, view_license
37
+ from hikyuu import can_upgrade, get_last_version, fetch_trial_license, view_license, is_valid_license
38
38
  from hikyuu.data import hku_config_template
39
39
  from hikyuu.util import *
40
40
 
@@ -93,6 +93,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
93
93
  def getHikyuuConfigFileName(self):
94
94
  return self.getUserConfigDir() + '/hikyuu.ini'
95
95
 
96
+ @hku_catch()
96
97
  def saveConfig(self):
97
98
  if not os.path.lexists(self.getUserConfigDir()):
98
99
  os.mkdir(self.getUserConfigDir())
@@ -105,7 +106,10 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
105
106
  if current_config.getboolean('hdf5', 'enable', fallback=True):
106
107
  data_dir = current_config['hdf5']['dir']
107
108
  if not os.path.lexists(data_dir + '/tmp'):
108
- os.mkdir(data_dir + '/tmp')
109
+ try:
110
+ os.mkdir(data_dir + '/tmp')
111
+ except:
112
+ pass
109
113
  # 此处不能使用 utf-8 参数,否则导致Windows下getBlock无法找到板块分类
110
114
  with open(filename, 'w', encoding='utf-8') as f:
111
115
  f.write(
@@ -140,8 +144,13 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
140
144
  )
141
145
  )
142
146
 
143
- else:
147
+ elif current_config.getboolean('mysql', 'enable', fallback=True):
144
148
  data_dir = current_config['mysql']['tmpdir']
149
+ if not os.path.lexists(data_dir + '/tmp'):
150
+ try:
151
+ os.mkdir(data_dir + '/tmp')
152
+ except:
153
+ pass
145
154
  with open(filename, 'w', encoding="utf-8") as f:
146
155
  f.write(
147
156
  hku_config_template.mysql_template.format(
@@ -179,15 +188,21 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
179
188
  )
180
189
  )
181
190
 
182
- if not os.path.lexists(data_dir):
183
- os.makedirs(data_dir)
191
+ try:
192
+ if not data_dir and not os.path.lexists(data_dir):
193
+ os.makedirs(data_dir)
194
+ except:
195
+ pass
184
196
 
185
- if not os.path.lexists(data_dir + '/block'):
186
- current_dir = os.path.dirname(os.path.abspath(__file__))
187
- dirname, _ = os.path.split(current_dir)
188
- dirname = os.path.join(dirname, 'config/block')
189
- shutil.copytree(dirname, data_dir + '/block')
190
- os.remove(data_dir + '/block/__init__.py')
197
+ try:
198
+ if not data_dir and not os.path.lexists(data_dir + '/block'):
199
+ current_dir = os.path.dirname(os.path.abspath(__file__))
200
+ dirname, _ = os.path.split(current_dir)
201
+ dirname = os.path.join(dirname, 'config/block')
202
+ shutil.copytree(dirname, data_dir + '/block')
203
+ os.remove(data_dir + '/block/__init__.py')
204
+ except:
205
+ pass
191
206
 
192
207
  @pyqtSlot()
193
208
  def on_save_pushButton_clicked(self):
@@ -309,6 +324,8 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
309
324
 
310
325
  # 初始化权息与财务数据设置
311
326
  self.import_weight_checkBox.setChecked(import_config.getboolean('weight', 'enable', fallback=True))
327
+ self.import_history_finance_checkBox.setChecked(import_config.getboolean('finance', 'enable', fallback=True))
328
+ self.import_block_checkBox.setChecked(import_config.getboolean('block', 'enable', fallback=True))
312
329
 
313
330
  # 初始化通道信目录配置
314
331
  tdx_enable = import_config.getboolean('tdx', 'enable', fallback=False)
@@ -350,7 +367,8 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
350
367
  if hdf5_enable:
351
368
  mysql_enable = False
352
369
  self.enable_mysql_radioButton.setChecked(mysql_enable)
353
- self.mysql_tmpdir_lineEdit.setText(import_config.get('mysql', 'tmpdir', fallback='c:/stock'))
370
+ self.mysql_tmpdir_lineEdit.setText(import_config.get('mysql', 'tmpdir', fallback='d:/stock'))
371
+ self.mysql_tmpdir_pushButton.setEnabled(mysql_enable)
354
372
  mysql_ip = import_config.get('mysql', 'host', fallback='127.0.0.1')
355
373
  self.mysql_ip_lineEdit.setText(mysql_ip)
356
374
  self.mysql_ip_lineEdit.setEnabled(mysql_enable)
@@ -442,6 +460,12 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
442
460
  import_config['weight'] = {
443
461
  'enable': self.import_weight_checkBox.isChecked(),
444
462
  }
463
+ import_config['finance'] = {
464
+ 'enable': self.import_history_finance_checkBox.isChecked(),
465
+ }
466
+ import_config['block'] = {
467
+ 'enable': self.import_block_checkBox.isChecked(),
468
+ }
445
469
  import_config['tdx'] = {'enable': self.tdx_radioButton.isChecked(), 'dir': self.tdx_dir_lineEdit.text()}
446
470
  import_config['pytdx'] = {
447
471
  'enable': self.pytdx_radioButton.isChecked(),
@@ -597,23 +621,22 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
597
621
  def on_enable_hdf55_radioButton_clicked(self):
598
622
  if self.enable_hdf55_radioButton.isChecked():
599
623
  self.enable_mysql_radioButton.setChecked(False)
600
- self.on_enable_hdf5_or_mysql_toggled()
624
+ self.on_enable_database_toggled(hdf5=True, mysql=False)
601
625
 
602
626
  @pyqtSlot()
603
627
  def on_enable_mysql_radioButton_clicked(self):
604
628
  if self.enable_mysql_radioButton.isChecked():
605
629
  self.enable_hdf55_radioButton.setChecked(False)
606
- self.on_enable_hdf5_or_mysql_toggled()
607
-
608
- def on_enable_hdf5_or_mysql_toggled(self):
609
- hdf5_enable = self.enable_hdf55_radioButton.isChecked()
610
- mysql_enable = not hdf5_enable
611
- self.hdf5_dir_lineEdit.setEnabled(hdf5_enable)
612
- self.mysql_ip_lineEdit.setEnabled(mysql_enable)
613
- self.mysql_port_lineEdit.setEnabled(mysql_enable)
614
- self.mysql_usr_lineEdit.setEnabled(mysql_enable)
615
- self.mysql_pwd_lineEdit.setEnabled(mysql_enable)
616
- self.mysql_test_pushButton.setEnabled(mysql_enable)
630
+ self.on_enable_database_toggled(hdf5=False, mysql=True)
631
+
632
+ def on_enable_database_toggled(self, hdf5, mysql):
633
+ self.hdf5_dir_lineEdit.setEnabled(hdf5)
634
+ self.mysql_ip_lineEdit.setEnabled(mysql)
635
+ self.mysql_port_lineEdit.setEnabled(mysql)
636
+ self.mysql_usr_lineEdit.setEnabled(mysql)
637
+ self.mysql_pwd_lineEdit.setEnabled(mysql)
638
+ self.mysql_test_pushButton.setEnabled(mysql)
639
+ self.mysql_tmpdir_pushButton.setEnabled(mysql)
617
640
 
618
641
  @pyqtSlot()
619
642
  def on_mysql_tmpdir_pushButton_clicked(self):
@@ -29,7 +29,7 @@ class ImportBlockInfoTask:
29
29
  sqlite_file = "{}/stock.db".format(self.config['hdf5']['dir'])
30
30
  connect = sqlite3.connect(sqlite_file, timeout=1800)
31
31
  import_block = em_import_block_to_sqlite
32
- else:
32
+ elif self.config.getboolean('mysql', 'enable', fallback=True):
33
33
  db_config = {
34
34
  'user': self.config['mysql']['usr'],
35
35
  'password': self.config['mysql']['pwd'],
@@ -30,7 +30,6 @@ import mysql.connector
30
30
  from pytdx.hq import TdxHq_API
31
31
  from hikyuu.data.pytdx_finance_to_mysql import history_finance_import_mysql
32
32
  from hikyuu.data.pytdx_finance_to_sqlite import history_finance_import_sqlite
33
- from hikyuu.data.common_pytdx import search_best_tdx
34
33
  from hikyuu.util import *
35
34
 
36
35
 
@@ -46,13 +45,13 @@ class ImportHistoryFinanceTask:
46
45
  self.total_count = 0
47
46
  self.status = "no run"
48
47
 
49
- def connect(self):
50
- self.api = TdxHq_API()
48
+ def connect_to_pytdx(self):
49
+ api = TdxHq_API()
51
50
  # 不是所有服务器都提供下载
52
- hku_check(self.api.connect('120.76.152.87', 7709), "failed connect pytdx!")
51
+ hku_check(api.connect('120.76.152.87', 7709), "failed connect pytdx!")
52
+ return api
53
53
 
54
54
  def get_list_info(self):
55
- result = []
56
55
  content = self.api.get_report_file_by_size('tdxfin/gpcw.txt')
57
56
  content = content.decode('utf-8')
58
57
  content = content.strip().split('\r\n')
@@ -62,72 +61,77 @@ class ImportHistoryFinanceTask:
62
61
 
63
62
  return [l2d(i.strip().split(',')) for i in content]
64
63
 
65
- def import_to_db(self, filename):
64
+ def connect_db(self):
66
65
  if self.config.getboolean('hdf5', 'enable', fallback=True):
67
66
  sqlite_file = "{}/stock.db".format(self.config['hdf5']['dir'])
68
- connect = sqlite3.connect(sqlite_file, timeout=1800)
69
- history_finance_import = history_finance_import_sqlite
70
- else:
67
+ self.db_connect = sqlite3.connect(sqlite_file, timeout=1800)
68
+ self.history_finance_import = history_finance_import_sqlite
69
+ self.engine = 'hdf5'
70
+ elif self.config.getboolean('mysql', 'enable', fallback=True):
71
71
  db_config = {
72
72
  'user': self.config['mysql']['usr'],
73
73
  'password': self.config['mysql']['pwd'],
74
74
  'host': self.config['mysql']['host'],
75
75
  'port': self.config['mysql']['port']
76
76
  }
77
- connect = mysql.connector.connect(**db_config)
78
- history_finance_import = history_finance_import_mysql
77
+ self.db_connect = mysql.connector.connect(**db_config)
78
+ self.history_finance_import = history_finance_import_mysql
79
+ self.engine = 'mysql'
79
80
 
81
+ def import_to_db(self, filename):
80
82
  try:
81
- history_finance_import(connect, filename)
83
+ self.history_finance_import(self.db_connect, filename)
82
84
  except Exception as e:
83
85
  hku_error(str(e))
84
- finally:
85
- connect.commit()
86
- connect.close()
87
86
 
88
- def download_file(self, item):
87
+ def download_file(self, item, dest_dir):
89
88
  filename = item['filename']
90
- # filesize = item['filesize']
91
- # get_report_file_by_size 传入实际的 filesize,实际会出错
92
- data = self.api.get_report_file_by_size(f'tdxfin/{filename}', 0)
93
- hku_info(f"Download finance file: {filename}")
94
- dest_file_name = self.dest_dir + "/" + filename
95
- with open(dest_file_name, 'wb') as f:
96
- f.write(data)
97
- shutil.unpack_archive(dest_file_name, extract_dir=self.dest_dir)
98
- self.import_to_db(f'{self.dest_dir}/{filename[0:-4]}.dat')
99
- hku_info(f"Import finance file: {self.dest_dir}/{filename[0:-4]}.dat")
89
+ dest_file_name = dest_dir + "/" + filename
90
+ need_download = False
91
+ if not os.path.exists(dest_file_name):
92
+ need_download = True
93
+ else:
94
+ old_md5 = ''
95
+ with open(dest_file_name, 'rb') as f:
96
+ old_md5 = hashlib.md5(f.read()).hexdigest()
97
+ if old_md5 != item['hash']:
98
+ need_download = True
99
+
100
+ if need_download:
101
+ api = TdxHq_API()
102
+ # 不是所有服务器都提供下载
103
+ hku_check(api.connect('120.76.152.87', 7709), "failed connect pytdx!")
104
+ data = api.get_report_file_by_size(f'tdxfin/{filename}', 0)
105
+ hku_info(f"Download finance file: {filename}")
106
+ with open(dest_file_name, 'wb') as f:
107
+ f.write(data)
108
+ api.disconnect()
109
+
110
+ shutil.unpack_archive(dest_file_name, extract_dir=dest_dir)
111
+ self.import_to_db(f'{dest_dir}/{filename[0:-4]}.dat')
112
+ hku_info(f"Import finance file: {dest_dir}/{filename[0:-4]}.dat")
100
113
 
101
114
  @hku_catch(trace=True)
102
115
  def __call__(self):
103
116
  self.status = "running"
104
117
  capture_multiprocess_all_logger(self.log_queue)
105
- self.connect()
118
+ self.api = self.connect_to_pytdx()
106
119
  data_list = self.get_list_info()
107
120
  self.total_count = len(data_list)
108
121
  count = 0
122
+ data_list.sort(key=lambda x: x['filename'])
123
+
124
+ self.connect_db()
109
125
  for item in data_list:
110
126
  try:
111
- dest_file = '{}/{}'.format(self.dest_dir, item['filename'])
112
- if not os.path.exists(dest_file):
113
- self.download_file(item)
114
- else:
115
- old_md5 = ''
116
- with open(dest_file, 'rb') as f:
117
- old_md5 = hashlib.md5(f.read()).hexdigest()
118
- if old_md5 != item['hash']:
119
- self.download_file(item)
120
- else:
121
- # 不管是否有变化,都导入一次,以便切换引擎时可以导入
122
- shutil.unpack_archive(dest_file, extract_dir=self.dest_dir)
123
- filename = item['filename']
124
- filename = f'{self.dest_dir}/{filename[0:-4]}.dat'
125
- self.import_to_db(filename)
126
- hku_info(f"Import finance file: {filename}")
127
+ self.download_file(item, self.dest_dir)
127
128
  count += 1
128
129
  self.queue.put([self.task_name, None, None, int(100 * count / self.total_count), self.total_count])
129
130
  except Exception as e:
130
131
  hku_error(str(e))
132
+ self.db_connect.close()
133
+ self.api.disconnect()
134
+
131
135
  self.queue.put([self.task_name, None, None, None, self.total_count])
132
136
  self.status = "finished"
133
137
 
@@ -138,6 +142,6 @@ if __name__ == "__main__":
138
142
  this_dir = os.path.expanduser('~') + '/.hikyuu'
139
143
  import_config = ConfigParser()
140
144
  import_config.read(this_dir + '/importdata-gui.ini', encoding='utf-8')
141
- task = ImportHistoryFinanceTask(None, None, None, "c:\\stock")
145
+ task = ImportHistoryFinanceTask(None, None, None, "/Users/fasiondog/stock")
142
146
  task()
143
147
  print("over!")
@@ -64,7 +64,7 @@ class ImportPytdxTimeToH5:
64
64
  sqlite_file = "{}/stock.db".format(self.config['hdf5']['dir'])
65
65
  connect = sqlite3.connect(sqlite_file, timeout=1800)
66
66
  import_time = h5_import_time
67
- else:
67
+ elif self.config.getboolean('mysql', 'enable', fallback=True):
68
68
  db_config = {
69
69
  'user': self.config['mysql']['usr'],
70
70
  'password': self.config['mysql']['pwd'],
@@ -84,9 +84,11 @@ class ImportPytdxTimeToH5:
84
84
  connect, self.market, self.quotations, api, self.dest_dir, max_days=self.max_days, progress=progress
85
85
  )
86
86
  self.logger.info("导入 {} 分时记录数: {}".format(self.market, count))
87
+ api.disconnect()
87
88
  except Exception as e:
88
89
  self.logger.error(e)
89
90
  finally:
91
+ api.close()
90
92
  connect.commit()
91
93
  connect.close()
92
94
 
@@ -66,12 +66,12 @@ class ImportPytdxToH5:
66
66
  connect = sqlite3.connect(sqlite_file, timeout=1800)
67
67
  import_data = h5_import_data
68
68
  self.logger.debug('use hdf5 import kdata')
69
- else:
69
+ elif self.config.getboolean('mysql', 'enable', fallback=True):
70
70
  db_config = {
71
71
  'user': self.config['mysql']['usr'],
72
72
  'password': self.config['mysql']['pwd'],
73
73
  'host': self.config['mysql']['host'],
74
- 'port': self.config['mysql']['port']
74
+ 'port': int(self.config['mysql']['port'])
75
75
  }
76
76
  connect = mysql.connector.connect(**db_config)
77
77
  import_data = mysql_import_data
@@ -87,10 +87,12 @@ class ImportPytdxToH5:
87
87
  connect, self.market, self.ktype, self.quotations, api, self.dest_dir, self.startDatetime, progress
88
88
  )
89
89
  self.logger.info("导入 {} {} 记录数: {}".format(self.market, self.ktype, count))
90
+ api.disconnect()
90
91
  except Exception as e:
91
92
  self.logger.error("ImportPytdxToH5Task failed! {}".format(e))
92
93
  # self.queue.put([self.task_name, self.market, self.ktype, str(e), count])
93
94
  finally:
95
+ api.close()
94
96
  connect.commit()
95
97
  connect.close()
96
98
 
@@ -64,7 +64,7 @@ class ImportPytdxTransToH5:
64
64
  sqlite_file = "{}/stock.db".format(self.config['hdf5']['dir'])
65
65
  connect = sqlite3.connect(sqlite_file, timeout=1800)
66
66
  import_trans = h5_import_trans
67
- else:
67
+ elif self.config.getboolean('mysql', 'enable', fallback=True):
68
68
  db_config = {
69
69
  'user': self.config['mysql']['usr'],
70
70
  'password': self.config['mysql']['pwd'],
@@ -84,9 +84,11 @@ class ImportPytdxTransToH5:
84
84
  connect, self.market, self.quotations, api, self.dest_dir, max_days=self.max_days, progress=progress
85
85
  )
86
86
  self.logger.info("导入 {} 分笔记录数: {}".format(self.market, count))
87
+ api.disconnect()
87
88
  except Exception as e:
88
89
  self.logger.error(e)
89
90
  finally:
91
+ api.close()
90
92
  connect.commit()
91
93
  connect.close()
92
94
 
@@ -67,7 +67,7 @@ class ImportWeightToSqliteTask:
67
67
  pytdx_import_weight = pytdx_import_weight_to_sqlite
68
68
  pytdx_import_finance = pytdx_import_finance_to_sqlite
69
69
  self.logger.debug('use sqlite import weight')
70
- else:
70
+ elif self.config.getboolean('mysql', 'enable', fallback=True):
71
71
  db_config = {
72
72
  'user': self.config['mysql']['usr'],
73
73
  'password': self.config['mysql']['pwd'],
@@ -107,6 +107,7 @@ class ImportWeightToSqliteTask:
107
107
  # self.queue.put([self.msg_name, str(e), -1, 0, total_count])
108
108
  self.queue.put([self.msg_name, 'INFO', str(e), 0, 0])
109
109
  finally:
110
+ api.close()
110
111
  connect.commit()
111
112
  connect.close()
112
113
 
@@ -27,7 +27,7 @@ class ImportZhBond10Task:
27
27
  sqlite_file = "{}/stock.db".format(self.config['hdf5']['dir'])
28
28
  connect = sqlite3.connect(sqlite_file, timeout=1800)
29
29
  import_zh_bond10 = import_zh_bond10_to_sqlite
30
- else:
30
+ elif self.config.getboolean('mysql', 'enable', fallback=True):
31
31
  db_config = {
32
32
  'user': self.config['mysql']['usr'],
33
33
  'password': self.config['mysql']['pwd'],