hikyuu 2.6.0__py3-none-win_amd64.whl → 2.6.2__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 (89) hide show
  1. hikyuu/__init__.py +19 -50
  2. hikyuu/__init__.pyi +530 -525
  3. hikyuu/analysis/__init__.pyi +498 -497
  4. hikyuu/analysis/analysis.pyi +499 -498
  5. hikyuu/core.pyi +500 -499
  6. hikyuu/cpp/__init__.pyi +2 -2
  7. hikyuu/cpp/boost_date_time-mt.dll +0 -0
  8. hikyuu/cpp/boost_serialization-mt.dll +0 -0
  9. hikyuu/cpp/boost_wserialization-mt.dll +0 -0
  10. hikyuu/cpp/core310.pyd +0 -0
  11. hikyuu/cpp/core310.pyi +60 -8
  12. hikyuu/cpp/core311.pyd +0 -0
  13. hikyuu/cpp/core311.pyi +60 -8
  14. hikyuu/cpp/core312.pyd +0 -0
  15. hikyuu/cpp/core312.pyi +60 -8
  16. hikyuu/cpp/core313.pyd +0 -0
  17. hikyuu/cpp/core313.pyi +60 -8
  18. hikyuu/cpp/core39.pyd +0 -0
  19. hikyuu/cpp/core39.pyi +60 -8
  20. hikyuu/cpp/hikyuu.dll +0 -0
  21. hikyuu/cpp/hikyuu.lib +0 -0
  22. hikyuu/cpp/sqlite3.dll +0 -0
  23. hikyuu/draw/drawplot/__init__.pyi +9 -9
  24. hikyuu/draw/drawplot/bokeh_draw.pyi +519 -514
  25. hikyuu/draw/drawplot/common.pyi +1 -1
  26. hikyuu/draw/drawplot/echarts_draw.pyi +521 -516
  27. hikyuu/draw/drawplot/matplotlib_draw.pyi +531 -526
  28. hikyuu/draw/elder.pyi +11 -11
  29. hikyuu/draw/kaufman.pyi +18 -18
  30. hikyuu/draw/volume.pyi +10 -10
  31. hikyuu/extend.py +0 -14
  32. hikyuu/extend.pyi +506 -509
  33. hikyuu/gui/HikyuuTDX.py +66 -12
  34. hikyuu/gui/data/ImportQmtToH5Task.py +209 -0
  35. hikyuu/gui/data/ImportTdxToH5Task.py +8 -1
  36. hikyuu/gui/data/MainWindow.py +68 -50
  37. hikyuu/gui/data/UseQmtImportToH5Thread.py +316 -0
  38. hikyuu/gui/data/UseTdxImportToH5Thread.py +221 -65
  39. hikyuu/gui/importdata.py +24 -11
  40. hikyuu/hub.pyi +6 -6
  41. hikyuu/include/hikyuu/KData.h +5 -0
  42. hikyuu/include/hikyuu/KDataImp.h +4 -0
  43. hikyuu/include/hikyuu/data_driver/kdata/mysql/KRecordTable.h +41 -2
  44. hikyuu/include/hikyuu/indicator/crt/CONTEXT.h +6 -2
  45. hikyuu/include/hikyuu/indicator/crt/COUNT.h +3 -3
  46. hikyuu/include/hikyuu/indicator/crt/DISCARD.h +1 -1
  47. hikyuu/include/hikyuu/indicator/crt/ISINF.h +1 -1
  48. hikyuu/include/hikyuu/indicator/crt/ISINFA.h +1 -1
  49. hikyuu/include/hikyuu/indicator/crt/ISNA.h +1 -1
  50. hikyuu/include/hikyuu/indicator/crt/LAST.h +2 -2
  51. hikyuu/include/hikyuu/indicator/crt/MAX.h +1 -1
  52. hikyuu/include/hikyuu/indicator/crt/MIN.h +1 -1
  53. hikyuu/include/hikyuu/indicator/crt/PRICELIST.h +1 -15
  54. hikyuu/include/hikyuu/indicator/crt/SUMBARS.h +1 -1
  55. hikyuu/include/hikyuu/plugin/KDataToHdf5Importer.h +33 -0
  56. hikyuu/include/hikyuu/plugin/interface/ImportKDataToHdf5PluginInterface.h +33 -0
  57. hikyuu/include/hikyuu/plugin/interface/plugins.h +2 -0
  58. hikyuu/include/hikyuu/strategy/Strategy.h +3 -6
  59. hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +2 -1
  60. hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +12 -9
  61. hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector.h +1 -1
  62. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorSelector.h +12 -12
  63. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorValueSelector.h +2 -2
  64. hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/PerformanceOptimalSelector.h +1 -1
  65. hikyuu/include/hikyuu/trade_sys/system/System.h +12 -3
  66. hikyuu/include/hikyuu/trade_sys/system/imp/DelegateSystem.h +0 -1
  67. hikyuu/include/hikyuu/trade_sys/system/imp/WalkForwardSystem.h +0 -1
  68. hikyuu/include/hikyuu/utilities/arithmetic.h +32 -22
  69. hikyuu/include/hikyuu/utilities/datetime/Datetime.h +1 -0
  70. hikyuu/include/hikyuu/version.h +4 -4
  71. hikyuu/plugin/backtest.dll +0 -0
  72. hikyuu/plugin/dataserver.dll +0 -0
  73. hikyuu/plugin/device.dll +0 -0
  74. hikyuu/plugin/import2hdf5.dll +0 -0
  75. hikyuu/trade_manage/__init__.pyi +518 -513
  76. hikyuu/trade_manage/broker.pyi +3 -3
  77. hikyuu/trade_manage/broker_easytrader.pyi +1 -1
  78. hikyuu/trade_manage/trade.pyi +518 -513
  79. hikyuu/util/__init__.py +1 -0
  80. hikyuu/util/__init__.pyi +3 -2
  81. hikyuu/util/mylog.py +30 -3
  82. hikyuu/util/mylog.pyi +3 -1
  83. hikyuu/util/singleton.pyi +1 -1
  84. {hikyuu-2.6.0.dist-info → hikyuu-2.6.2.dist-info}/METADATA +1 -1
  85. {hikyuu-2.6.0.dist-info → hikyuu-2.6.2.dist-info}/RECORD +89 -84
  86. {hikyuu-2.6.0.dist-info → hikyuu-2.6.2.dist-info}/LICENSE +0 -0
  87. {hikyuu-2.6.0.dist-info → hikyuu-2.6.2.dist-info}/WHEEL +0 -0
  88. {hikyuu-2.6.0.dist-info → hikyuu-2.6.2.dist-info}/entry_points.txt +0 -0
  89. {hikyuu-2.6.0.dist-info → hikyuu-2.6.2.dist-info}/top_level.txt +0 -0
@@ -24,18 +24,30 @@
24
24
 
25
25
  import logging
26
26
  import sqlite3
27
+ import datetime
28
+ import mysql.connector
29
+ import queue
27
30
  from multiprocessing import Queue, Process
28
31
  from PyQt5.QtCore import QThread, pyqtSignal
29
32
  from hikyuu.gui.data.ImportTdxToH5Task import ImportTdxToH5Task
30
33
  from hikyuu.gui.data.ImportWeightToSqliteTask import ImportWeightToSqliteTask
34
+ from hikyuu.gui.data.ImportTdxToH5Task import ImportTdxToH5Task
31
35
  from hikyuu.gui.data.ImportHistoryFinanceTask import ImportHistoryFinanceTask
32
-
36
+ from hikyuu.gui.data.ImportBlockInfoTask import ImportBlockInfoTask
37
+ from hikyuu.gui.data.ImportZhBond10Task import ImportZhBond10Task
33
38
  from pytdx.hq import TdxHq_API
34
- from hikyuu.data.common import g_market_list
35
- from hikyuu.data.common_sqlite3 import create_database
36
39
  from hikyuu.data.common_pytdx import search_best_tdx
37
- from hikyuu.data.tdx_to_h5 import tdx_import_stock_name_from_file
38
- from hikyuu.util import *
40
+
41
+ from hikyuu.data.common import *
42
+ from hikyuu.data.common_sqlite3 import import_new_holidays as sqlite_import_new_holidays
43
+ from hikyuu.data.common_sqlite3 import create_database as sqlite_create_database
44
+ from hikyuu.data.pytdx_to_h5 import import_index_name as sqlite_import_index_name
45
+ from hikyuu.data.pytdx_to_h5 import import_stock_name as sqlite_import_stock_name
46
+ from hikyuu.data.common_mysql import create_database as mysql_create_database
47
+ from hikyuu.data.common_mysql import import_new_holidays as mysql_import_new_holidays
48
+ from hikyuu.data.pytdx_to_mysql import import_index_name as mysql_import_index_name
49
+ from hikyuu.data.pytdx_to_mysql import import_stock_name as mysql_import_stock_name
50
+ from hikyuu.util.mylog import class_logger
39
51
 
40
52
 
41
53
  class UseTdxImportToH5Thread(QThread):
@@ -43,66 +55,120 @@ class UseTdxImportToH5Thread(QThread):
43
55
 
44
56
  def __init__(self, parent, config):
45
57
  super(UseTdxImportToH5Thread, self).__init__()
46
- self.logger = logging.getLogger(self.__class__.__name__)
47
58
  self.parent = parent
48
59
  self.log_queue = parent.mp_log_q if parent is not None else None
49
60
  self.config = config
50
61
  self.msg_name = 'HDF5_IMPORT'
51
62
 
52
63
  self.process_list = []
53
-
54
- src_dir = config['tdx']['dir']
55
- dest_dir = config['hdf5']['dir']
56
- sqlite_file_name = dest_dir + "/stock.db"
64
+ self.hosts = []
65
+ self.tasks = []
57
66
 
58
67
  self.quotations = []
59
68
  if self.config['quotation']['stock']:
60
69
  self.quotations.append('stock')
61
70
  if self.config['quotation']['fund']:
62
71
  self.quotations.append('fund')
63
- # if self.config['quotation']['future']:
64
- # self.quotations.append('future')
65
72
 
66
- # 通达信盘后没有债券数据。另外,如果用Pytdx下载债券数据,
67
- # 每个债券本身的数据很少但债券种类太多占用空间和时间太多,用途较少不再考虑导入
68
- # if self.config['quotation']['bond']:
69
- # self.quotations.append('bond')
73
+ self.queue = Queue()
70
74
 
71
- hosts = search_best_tdx()
72
- api = TdxHq_API()
73
- hku_check(api.connect(hosts[0][2], hosts[0][3]), "failed connect pytdx {}:{}!", hosts[0][2], hosts[0][3])
75
+ def __del__(self):
76
+ for p in self.process_list:
77
+ if p.is_alive():
78
+ p.terminate()
79
+
80
+ def send_message(self, msg):
81
+ self.message.emit([self.msg_name] + msg)
82
+
83
+ def init_task(self):
84
+ config = self.config
85
+ src_dir = config['tdx']['dir']
86
+ dest_dir = config['hdf5']['dir']
74
87
 
75
- self.queue = Queue()
76
88
  self.tasks = []
89
+ if self.config.getboolean('finance', 'enable', fallback=True):
90
+ self.tasks.append(
91
+ ImportHistoryFinanceTask(self.log_queue, self.queue, self.config, dest_dir))
92
+
93
+ self.tasks.append(ImportBlockInfoTask(self.log_queue, self.queue,
94
+ self.config, ('行业板块', '概念板块', '地域板块', '指数板块')))
95
+ self.tasks.append(ImportZhBond10Task(self.log_queue, self.queue, self.config))
96
+
97
+ task_count = 0
98
+ market_count = len(g_market_list)
99
+ if self.config.getboolean('ktype', 'day', fallback=False):
100
+ task_count += market_count
101
+ if self.config.getboolean('ktype', 'min5', fallback=False):
102
+ task_count += market_count
103
+ if self.config.getboolean('ktype', 'min', fallback=False):
104
+ task_count += market_count
105
+ # 本地暂不支持分时和分笔导入
106
+ # if self.config.getboolean('ktype', 'trans', fallback=False):
107
+ # task_count += market_count
108
+ # if self.config.getboolean('ktype', 'time', fallback=False):
109
+ # task_count += market_count
110
+ if self.config.getboolean('weight', 'enable', fallback=False):
111
+ task_count += (market_count*2)
112
+
113
+ self.logger.info('搜索通达信服务器')
114
+ self.send_message(['INFO', '搜索通达信服务器'])
115
+ self.hosts = search_best_tdx()
116
+ if not self.hosts:
117
+ self.logger.warn('无法连接通达信行情服务器!请检查网络设置!')
118
+ self.send_message(['INFO', '无法连接通达信行情服务器!请检查网络设置!'])
119
+ return
120
+
121
+ if task_count == 0:
122
+ self.send_message(['INFO', '未选择需要导入的行情数据!'])
123
+ return
124
+
125
+ use_tdx_number = min(
126
+ task_count, len(self.hosts),
127
+ self.config.getint('pytdx', 'use_tdx_number', fallback=10))
128
+ split = task_count // use_tdx_number
129
+ use_hosts = []
130
+ for i in range(use_tdx_number):
131
+ for j in range(split):
132
+ use_hosts.append((self.hosts[i][2], self.hosts[i][3]))
133
+ if len(use_hosts) < task_count:
134
+ for i in range(task_count - len(use_hosts)):
135
+ use_hosts.insert(0, (self.hosts[0][2], self.hosts[0][3]))
136
+ # for i in range(len(use_hosts)):
137
+ # print(i, use_hosts[i])
77
138
 
78
139
  cur_host = 0
79
140
  if self.config.getboolean('weight', 'enable', fallback=False):
80
141
  for market in g_market_list:
81
142
  self.tasks.append(
82
143
  ImportWeightToSqliteTask(self.log_queue, self.queue,
83
- self.config, dest_dir, market, 'weight', hosts[cur_host][2],
84
- hosts[cur_host][3]))
144
+ self.config, dest_dir, market, 'weight', self.hosts[cur_host][2],
145
+ self.hosts[cur_host][3]))
85
146
  cur_host += 1
86
- if cur_host >= len(hosts):
147
+ if cur_host >= len(self.hosts):
87
148
  cur_host = 0
88
149
  self.tasks.append(
89
150
  ImportWeightToSqliteTask(self.log_queue, self.queue,
90
- self.config, dest_dir, market, 'finance', hosts[cur_host][2],
91
- hosts[cur_host][3]))
151
+ self.config, dest_dir, market, 'finance', self.hosts[cur_host][2],
152
+ self.hosts[cur_host][3]))
92
153
  cur_host += 1
93
- if cur_host >= len(hosts):
154
+ if cur_host >= len(self.hosts):
94
155
  cur_host = 0
95
156
 
96
- if self.config.getboolean('finance', 'enable', fallback=True):
97
- self.tasks.append(ImportHistoryFinanceTask(self.log_queue, self.queue, self.config, dest_dir))
98
157
  if self.config.getboolean('ktype', 'day', fallback=False):
158
+ self.tasks.append(
159
+ ImportTdxToH5Task(self.log_queue, self.queue, config, 'BJ', 'DAY', self.quotations, src_dir, dest_dir)
160
+ )
99
161
  self.tasks.append(
100
162
  ImportTdxToH5Task(self.log_queue, self.queue, config, 'SH', 'DAY', self.quotations, src_dir, dest_dir)
101
163
  )
102
164
  self.tasks.append(
103
165
  ImportTdxToH5Task(self.log_queue, self.queue, config, 'SZ', 'DAY', self.quotations, src_dir, dest_dir)
104
166
  )
167
+
105
168
  if self.config.getboolean('ktype', 'min5', fallback=False):
169
+ self.tasks.append(
170
+ ImportTdxToH5Task(self.log_queue, self.queue, config, 'BJ', '5MIN', self.quotations, src_dir, dest_dir)
171
+ )
106
172
  self.tasks.append(
107
173
  ImportTdxToH5Task(self.log_queue, self.queue, config, 'SH', '5MIN', self.quotations, src_dir, dest_dir)
108
174
  )
@@ -110,6 +176,9 @@ class UseTdxImportToH5Thread(QThread):
110
176
  ImportTdxToH5Task(self.log_queue, self.queue, config, 'SZ', '5MIN', self.quotations, src_dir, dest_dir)
111
177
  )
112
178
  if self.config.getboolean('ktype', 'min', fallback=False):
179
+ self.tasks.append(
180
+ ImportTdxToH5Task(self.log_queue, self.queue, config, 'BJ', '1MIN', self.quotations, src_dir, dest_dir)
181
+ )
113
182
  self.tasks.append(
114
183
  ImportTdxToH5Task(self.log_queue, self.queue, config, 'SH', '1MIN', self.quotations, src_dir, dest_dir)
115
184
  )
@@ -117,38 +186,71 @@ class UseTdxImportToH5Thread(QThread):
117
186
  ImportTdxToH5Task(self.log_queue, self.queue, config, 'SZ', '1MIN', self.quotations, src_dir, dest_dir)
118
187
  )
119
188
 
120
- def __del__(self):
121
- for p in self.process_list:
122
- if p.is_alive():
123
- p.terminate()
124
-
125
- def send_message(self, msg):
126
- self.message.emit([self.msg_name] + msg)
127
-
128
189
  def run(self):
129
190
  try:
191
+ self.init_task()
130
192
  self._run()
131
193
  except Exception as e:
194
+ self.logger.error(str(e))
132
195
  self.send_message(['THREAD', 'FAILURE', str(e)])
133
196
  else:
197
+ self.logger.info('导入完毕')
134
198
  self.send_message(['THREAD', 'FINISHED'])
135
199
 
136
200
  @hku_catch(trace=True, re_raise=True)
137
201
  def _run(self):
138
- src_dir = self.config['tdx']['dir']
139
- dest_dir = self.config['hdf5']['dir']
140
- hdf5_import_progress = {'SH': {'DAY': 0, '1MIN': 0, '5MIN': 0}, 'SZ': {'DAY': 0, '1MIN': 0, '5MIN': 0}}
202
+ hdf5_import_progress = {}
203
+ trans_progress = {}
204
+ time_progress = {}
205
+ for market in g_market_list:
206
+ hdf5_import_progress[market] = {'DAY': 0, '1MIN': 0, '5MIN': 0}
207
+ trans_progress[market] = 0
208
+ time_progress[market] = 0
141
209
 
142
210
  # 正在导入代码表
143
- self.send_message(['START_IMPORT_CODE'])
211
+ self.logger.info('导入股票代码表')
212
+ self.send_message(['INFO', '导入股票代码表'])
213
+
214
+ if self.config.getboolean('hdf5', 'enable', fallback=True):
215
+ connect = sqlite3.connect("{}/stock.db".format(
216
+ self.config['hdf5']['dir']))
217
+ create_database = sqlite_create_database
218
+ import_new_holidays = sqlite_import_new_holidays
219
+ import_index_name = sqlite_import_index_name
220
+ import_stock_name = sqlite_import_stock_name
221
+ else:
222
+ db_config = {
223
+ 'user': self.config['mysql']['usr'],
224
+ 'password': self.config['mysql']['pwd'],
225
+ 'host': self.config['mysql']['host'],
226
+ 'port': self.config['mysql']['port']
227
+ }
228
+ connect = mysql.connector.connect(**db_config)
229
+ create_database = mysql_create_database
230
+ import_new_holidays = mysql_import_new_holidays
231
+ import_index_name = mysql_import_index_name
232
+ import_stock_name = mysql_import_stock_name
144
233
 
145
- connect = sqlite3.connect(dest_dir + "/stock.db")
146
234
  create_database(connect)
147
235
 
148
- tdx_import_stock_name_from_file(connect, src_dir + "/T0002/hq_cache/shm.tnf", 'SH', self.quotations)
149
- tdx_import_stock_name_from_file(connect, src_dir + "/T0002/hq_cache/szm.tnf", 'SZ', self.quotations)
236
+ pytdx_api = TdxHq_API()
237
+ hku_check(pytdx_api.connect(self.hosts[0][2], self.hosts[0][3]),
238
+ "failed connect pytdx {}:{}", self.hosts[0][2],
239
+ self.hosts[0][3])
150
240
 
151
- self.send_message(['FINISHED_IMPORT_CODE'])
241
+ self.logger.info("导入交易所休假日历")
242
+ import_new_holidays(connect)
243
+
244
+ count = import_index_name(connect)
245
+ self.logger.info("指数数量: {}".format(count))
246
+
247
+ for market in g_market_list:
248
+ count = import_stock_name(connect, pytdx_api, market,
249
+ self.quotations)
250
+ if count > 0:
251
+ self.logger.info("{} 新增股票数: {}".format(market, count))
252
+ self.send_message(
253
+ ['INFO', '{} 新增股票数:{}'.format(market, count)])
152
254
 
153
255
  self.process_list.clear()
154
256
  for task in self.tasks:
@@ -157,26 +259,80 @@ class UseTdxImportToH5Thread(QThread):
157
259
  p.start()
158
260
 
159
261
  finished_count = len(self.tasks)
262
+ market_count = len(g_market_list)
160
263
  while finished_count > 0:
161
- message = self.queue.get()
162
- taskname, market, ktype, progress, total = message
163
- if progress is None:
164
- finished_count -= 1
165
- if taskname == 'IMPORT_KDATA':
166
- self.send_message(['IMPORT_KDATA', 'FINISHED', market, ktype, total])
264
+ try:
265
+ message = self.queue.get(timeout=10)
266
+ taskname, market, ktype, progress, total = message
267
+ if progress is None:
268
+ finished_count -= 1
269
+ if taskname in ('IMPORT_KDATA', 'IMPORT_TRANS',
270
+ 'IMPORT_TIME'):
271
+ self.send_message(
272
+ [taskname, 'FINISHED', market, ktype, total])
273
+ elif taskname == 'IMPORT_BLOCKINFO':
274
+ self.send_message([taskname, ktype])
275
+ elif taskname == 'IMPORT_ZH_BOND10':
276
+ self.send_message([taskname, ktype])
277
+ elif taskname == 'IMPORT_WEIGHT':
278
+ pass
279
+ else:
280
+ self.send_message([taskname, 'FINISHED'])
281
+ continue
282
+
283
+ if taskname == 'IMPORT_WEIGHT':
284
+ if market == 'INFO':
285
+ self.send_message(['INFO', ktype])
286
+ self.send_message([taskname, market, total])
287
+ elif taskname == 'IMPORT_FINANCE':
288
+ self.send_message([taskname, progress])
289
+ elif taskname == 'IMPORT_KDATA':
290
+ hdf5_import_progress[market][ktype] = progress
291
+ current_progress = 0
292
+ for market in g_market_list:
293
+ current_progress += hdf5_import_progress[market][ktype]
294
+ current_progress = current_progress // market_count
295
+ self.send_message([taskname, ktype, current_progress])
296
+ elif taskname == 'IMPORT_TRANS':
297
+ trans_progress[market] = progress
298
+ current_progress = 0
299
+ for market in g_market_list:
300
+ current_progress += trans_progress[market]
301
+ current_progress = current_progress // market_count
302
+ self.send_message([taskname, ktype, current_progress])
303
+ elif taskname == 'IMPORT_TIME':
304
+ time_progress[market] = progress
305
+ current_progress = 0
306
+ for market in g_market_list:
307
+ current_progress += time_progress[market]
308
+ current_progress = current_progress // market_count
309
+ self.send_message([taskname, ktype, current_progress])
310
+ elif taskname == 'IMPORT_BLOCKINFO':
311
+ self.send_message([taskname, market, ktype])
167
312
  else:
168
- self.send_message([taskname, 'FINISHED'])
169
- continue
170
-
171
- if taskname == 'IMPORT_WEIGHT':
172
- if market == 'INFO':
173
- self.send_message(['INFO', ktype])
174
- self.send_message(['IMPORT_WEIGHT', market, total])
175
- elif taskname == 'IMPORT_KDATA':
176
- hdf5_import_progress[market][ktype] = progress
177
- current_progress = (hdf5_import_progress['SH'][ktype] + hdf5_import_progress['SZ'][ktype]) // 2
178
- self.send_message(['IMPORT_KDATA', ktype, current_progress])
179
- elif taskname == 'IMPORT_FINANCE':
180
- self.send_message([taskname, progress])
181
- else:
182
- self.logger.error("Unknow task: {}".format(taskname))
313
+ self.logger.error("Unknow task: {}".format(taskname))
314
+ except queue.Empty:
315
+ if finished_count > 0:
316
+ ok = False
317
+ for p in self.process_list:
318
+ if p.is_alive():
319
+ ok = True
320
+ break
321
+ if not ok:
322
+ for task in self.tasks:
323
+ self.logger.info(
324
+ f"task ({task.__class__.__name__}) status: {task.status}!"
325
+ )
326
+ for p in self.process_list:
327
+ self.logger.info(
328
+ f"Process exit code: {p.exitcode}")
329
+ finished_count = 0
330
+ self.logger.error(
331
+ "All process is finished, but some tasks are running!"
332
+ )
333
+
334
+ except Exception as e:
335
+ self.logger.error(str(e))
336
+
337
+
338
+ class_logger(UseTdxImportToH5Thread)
hikyuu/gui/importdata.py CHANGED
@@ -3,7 +3,8 @@
3
3
  # cp936
4
4
 
5
5
  import os.path
6
- import sys, time
6
+ import sys
7
+ import time
7
8
  from configparser import ConfigParser
8
9
 
9
10
  from hikyuu.data.weight_to_sqlite import qianlong_import_weight
@@ -14,7 +15,8 @@ from hikyuu.gui.data.UsePytdxImportToH5Thread import UsePytdxImportToH5Thread
14
15
 
15
16
 
16
17
  class HKUImportDataCMD:
17
- def __init__(self):
18
+ def __init__(self, ignore_kdata=False):
19
+ self.ignore_kdata = ignore_kdata # 忽略K线数据导入
18
20
  self.initThreads()
19
21
 
20
22
  def getUserConfigDir(self):
@@ -25,6 +27,12 @@ class HKUImportDataCMD:
25
27
  this_dir = self.getUserConfigDir()
26
28
  import_config = ConfigParser()
27
29
  import_config.read(this_dir + '/importdata-gui.ini', encoding='utf-8')
30
+ if self.ignore_kdata:
31
+ import_config.set('ktype', 'day', 'False')
32
+ import_config.set('ktype', 'min', 'False')
33
+ import_config.set('ktype', 'min5', 'False')
34
+ import_config.set('ktype', 'trans', 'False')
35
+ import_config.set('ktype', 'time', 'False')
28
36
  return import_config
29
37
 
30
38
  def initThreads(self):
@@ -46,7 +54,8 @@ class HKUImportDataCMD:
46
54
  def print_progress(self, ktype, progress):
47
55
  if progress != self.progress[ktype]:
48
56
  print(
49
- 'import progress: {}% - {} - 已耗时 {:>.2f} 分钟'.format(progress, self.info_type[ktype], self.time_escaped())
57
+ 'import progress: {}% - {} - 已耗时 {:>.2f} 分钟'.format(progress,
58
+ self.info_type[ktype], self.time_escaped())
50
59
  )
51
60
  self.progress[ktype] = progress
52
61
 
@@ -65,11 +74,12 @@ class HKUImportDataCMD:
65
74
  if status == 'FAILURE':
66
75
  self.details.append(msg[3])
67
76
  print("\n导入完毕, 共耗时 {:>.2f} 分钟".format(self.time_escaped()))
68
- print('\n=========================================================')
69
- print("导入详情:")
70
- for info in self.details:
71
- print(info)
72
- print('=========================================================')
77
+ if not self.ignore_kdata:
78
+ print('\n=========================================================')
79
+ print("导入详情:")
80
+ for info in self.details:
81
+ print(info)
82
+ print('=========================================================')
73
83
  self.import_running = False
74
84
 
75
85
  elif msg_task_name == 'IMPORT_KDATA':
@@ -144,10 +154,13 @@ class HKUImportDataCMD:
144
154
  self.hdf5_import_thread.run()
145
155
 
146
156
 
147
- def main():
148
- x = HKUImportDataCMD()
157
+ def main(ignore_kdata=False):
158
+ x = HKUImportDataCMD(ignore_kdata=ignore_kdata)
149
159
  x.start_import_data()
150
160
 
151
161
 
152
162
  if __name__ == '__main__':
153
- main()
163
+ if len(sys.argv) > 1 and sys.argv[1] == '--ignore-kdata':
164
+ main(ignore_kdata=True)
165
+ else:
166
+ main(ignore_kdata=False)
hikyuu/hub.pyi CHANGED
@@ -28,11 +28,11 @@ import sys as sys
28
28
  import typing
29
29
  __all__: list = ['add_remote_hub', 'add_local_hub', 'update_hub', 'remove_hub', 'build_hub', 'help_part', 'get_part', 'get_part_list', 'get_hub_path', 'get_part_info', 'get_part_module', 'print_part_info', 'get_hub_name_list', 'get_part_name_list', 'get_current_hub', 'search_part']
30
30
  class ConfigModel(sqlalchemy.orm.decl_api.Base):
31
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x2b2ffb758e0; ConfigModel>
31
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x1bb12cebc10; ConfigModel>
32
32
  __table__: typing.ClassVar[sqlalchemy.sql.schema.Table] # value = Table('hub_config', MetaData(), Column('id', Integer(), table=<hub_config>, primary_key=True, nullable=False, default=Sequence('config_id_seq', metadata=MetaData())), Column('key', String(), table=<hub_config>), Column('value', String(), table=<hub_config>), schema=None)
33
33
  __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('key', String(), table=<hub_config>)))
34
34
  __tablename__: typing.ClassVar[str] = 'hub_config'
35
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.ConfigModel'> at 2b280530e10>
35
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.ConfigModel'> at 1bb12d3db30>
36
36
  def __init__(self, **kwargs):
37
37
  """
38
38
  A simple constructor that allows initialization from kwargs.
@@ -109,11 +109,11 @@ class HubManager:
109
109
  def print_part_info(self, name):
110
110
  ...
111
111
  class HubModel(sqlalchemy.orm.decl_api.Base):
112
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x2b280513020; HubModel>
112
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x1bb12d75280; HubModel>
113
113
  __table__: typing.ClassVar[sqlalchemy.sql.schema.Table] # value = Table('hub_repo', MetaData(), Column('id', Integer(), table=<hub_repo>, primary_key=True, nullable=False, default=Sequence('remote_id_seq', metadata=MetaData())), Column('name', String(), table=<hub_repo>), Column('hub_type', String(), table=<hub_repo>), Column('local_base', String(), table=<hub_repo>), Column('local', String(), table=<hub_repo>), Column('url', String(), table=<hub_repo>), Column('branch', String(), table=<hub_repo>), schema=None)
114
114
  __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('name', String(), table=<hub_repo>)))
115
115
  __tablename__: typing.ClassVar[str] = 'hub_repo'
116
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.HubModel'> at 2b280549720>
116
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.HubModel'> at 1bb12d6e5e0>
117
117
  def __init__(self, **kwargs):
118
118
  """
119
119
  A simple constructor that allows initialization from kwargs.
@@ -146,11 +146,11 @@ class ModuleConflictError(Exception):
146
146
  def __str__(self):
147
147
  ...
148
148
  class PartModel(sqlalchemy.orm.decl_api.Base):
149
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x2b280513800; PartModel>
149
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x1bb12d851f0; PartModel>
150
150
  __table__: typing.ClassVar[sqlalchemy.sql.schema.Table] # value = Table('hub_part', MetaData(), Column('id', Integer(), table=<hub_part>, primary_key=True, nullable=False, default=Sequence('part_id_seq', metadata=MetaData())), Column('hub_name', String(), table=<hub_part>), Column('part', String(), table=<hub_part>), Column('name', String(), table=<hub_part>), Column('author', String(), table=<hub_part>), Column('version', String(), table=<hub_part>), Column('doc', String(), table=<hub_part>), Column('module_name', String(), table=<hub_part>), Column('label', String(), table=<hub_part>), schema=None)
151
151
  __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('name', String(), table=<hub_part>)))
152
152
  __tablename__: typing.ClassVar[str] = 'hub_part'
153
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.PartModel'> at 2b28054a2b0>
153
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.PartModel'> at 1bb12d83090>
154
154
  def __init__(self, **kwargs):
155
155
  """
156
156
  A simple constructor that allows initialization from kwargs.
@@ -117,6 +117,7 @@ public:
117
117
  const_iterator cbegin() const;
118
118
  const_iterator cend() const;
119
119
  const KRecord* data() const;
120
+ KRecord* data(); // 谨慎使用(用于强制调整数据)
120
121
 
121
122
  private:
122
123
  static KRecord ms_null_krecord;
@@ -261,6 +262,10 @@ inline const KRecord* KData::data() const {
261
262
  return m_imp->data();
262
263
  }
263
264
 
265
+ inline KRecord* KData::data() {
266
+ return m_imp->data();
267
+ }
268
+
264
269
  } /* namespace hku */
265
270
 
266
271
  #if FMT_VERSION >= 90000
@@ -49,6 +49,10 @@ public:
49
49
  return m_buffer.data();
50
50
  }
51
51
 
52
+ KRecord* data() {
53
+ return m_buffer.data();
54
+ }
55
+
52
56
  DatetimeList getDatetimeList() const;
53
57
 
54
58
  public:
@@ -9,6 +9,7 @@
9
9
  #define HIKYUU_DATA_DRIVER_KDATA_MYSQL_KRECORDTABLE_H
10
10
 
11
11
  #include "../../../KQuery.h"
12
+ #include "../../../KRecord.h"
12
13
  #include "../../../utilities/db_connect/SQLStatementBase.h"
13
14
 
14
15
  namespace hku {
@@ -32,6 +33,45 @@ public:
32
33
  to_lower(m_db_name);
33
34
  };
34
35
 
36
+ KRecordTable(const string& market, const string& code, const KQuery::KType& ktype,
37
+ const KRecord& record)
38
+ : KRecordTable(market, code, ktype) {
39
+ m_date = record.datetime.ymdhm();
40
+ m_open = record.openPrice;
41
+ m_high = record.highPrice;
42
+ m_low = record.lowPrice;
43
+ m_close = record.closePrice;
44
+ m_count = record.transCount;
45
+ m_amount = record.transAmount;
46
+ }
47
+
48
+ KRecordTable(const KRecordTable&) = default;
49
+ KRecordTable& operator=(const KRecordTable&) = default;
50
+ KRecordTable(KRecordTable&& rhs)
51
+ : m_db_name(std::move(rhs.m_db_name)),
52
+ m_code(std::move(rhs.m_code)),
53
+ m_date(rhs.m_date),
54
+ m_open(rhs.m_open),
55
+ m_high(rhs.m_high),
56
+ m_low(rhs.m_low),
57
+ m_close(rhs.m_close),
58
+ m_amount(rhs.m_amount),
59
+ m_count(rhs.m_count) {}
60
+
61
+ KRecordTable& operator=(KRecordTable&& rhs) {
62
+ if (&rhs != this) {
63
+ m_db_name = std::move(rhs.m_db_name);
64
+ m_code = std::move(rhs.m_code);
65
+ m_date = rhs.m_date;
66
+ m_open = rhs.m_open;
67
+ m_high = rhs.m_high;
68
+ m_low = rhs.m_low;
69
+ m_close = rhs.m_close;
70
+ m_amount = rhs.m_amount;
71
+ }
72
+ return *this;
73
+ }
74
+
35
75
  Datetime date() const {
36
76
  return m_date == 0 ? Null<Datetime>() : Datetime((uint64_t)m_date);
37
77
  }
@@ -90,8 +130,7 @@ public:
90
130
 
91
131
  string getSelectSQLNoDB() {
92
132
  return fmt::format(
93
- "select `date`,`open`,`high`, `low`, `close`, `amount`, `count` from `{}`",
94
- m_code);
133
+ "select `date`,`open`,`high`, `low`, `close`, `amount`, `count` from `{}`", m_code);
95
134
  }
96
135
 
97
136
  void save(const SQLStatementPtr& st) const {
@@ -13,10 +13,14 @@ namespace hku {
13
13
 
14
14
  /**
15
15
  * 独立上下文指标
16
+ * @param ind 待包装指标
17
+ * @param fill_null 是否填充空值,默认为 false
16
18
  * @ingroup Indicator
17
19
  */
18
- Indicator HKU_API CONTEXT(const Indicator& ind, bool fill_null = true);
19
- Indicator HKU_API CONTEXT(bool fill_null = true);
20
+ Indicator HKU_API CONTEXT(const Indicator& ind, bool fill_null = false, bool use_self_ktype = false,
21
+ bool use_self_recover_type = false);
22
+ Indicator HKU_API CONTEXT(bool fill_null = false, bool use_self_ktype = false,
23
+ bool use_self_recover_type = false);
20
24
 
21
25
  /**
22
26
  * 获取指标上下文
@@ -6,8 +6,8 @@
6
6
  */
7
7
 
8
8
  #pragma once
9
- #ifndef COUNT_H_
10
- #define COUNT_H_
9
+ #ifndef INDICATOR_CRT_COUNT_H_
10
+ #define INDICATOR_CRT_COUNT_H_
11
11
 
12
12
  #include "../Indicator.h"
13
13
 
@@ -51,4 +51,4 @@ inline Indicator HKU_API COUNT(const Indicator& ind, const Indicator& n) {
51
51
 
52
52
  } // namespace hku
53
53
 
54
- #endif /* CVAL_H_ */
54
+ #endif /* INDICATOR_CRT_COUNT_H_ */
@@ -11,7 +11,7 @@
11
11
  #ifndef INDICATOR_CRT_DISCARD_H_
12
12
  #define INDICATOR_CRT_DISCARD_H_
13
13
 
14
- #include "CVAL.h"
14
+ #include "../Indicator.h"
15
15
 
16
16
  namespace hku {
17
17
 
@@ -9,7 +9,7 @@
9
9
  #ifndef INDICATOR_CRT_ISINF_H_
10
10
  #define INDICATOR_CRT_ISINF_H_
11
11
 
12
- #include "CVAL.h"
12
+ #include "../Indicator.h"
13
13
 
14
14
  namespace hku {
15
15
 
@@ -9,7 +9,7 @@
9
9
  #ifndef INDICATOR_CRT_ISINFA_H_
10
10
  #define INDICATOR_CRT_ISINFA_H_
11
11
 
12
- #include "CVAL.h"
12
+ #include "../Indicator.h"
13
13
 
14
14
  namespace hku {
15
15