hikyuu 2.5.6__py3-none-win_amd64.whl → 2.6.1__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 (118) hide show
  1. hikyuu/__init__.py +33 -49
  2. hikyuu/__init__.pyi +530 -516
  3. hikyuu/analysis/__init__.pyi +498 -490
  4. hikyuu/analysis/analysis.pyi +499 -491
  5. hikyuu/core.pyi +500 -492
  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 +187 -22
  12. hikyuu/cpp/core311.pyd +0 -0
  13. hikyuu/cpp/core311.pyi +187 -22
  14. hikyuu/cpp/core312.pyd +0 -0
  15. hikyuu/cpp/core312.pyi +187 -22
  16. hikyuu/cpp/core313.pyd +0 -0
  17. hikyuu/cpp/core313.pyi +186 -22
  18. hikyuu/cpp/core39.pyd +0 -0
  19. hikyuu/cpp/core39.pyi +187 -22
  20. hikyuu/cpp/hikyuu.dll +0 -0
  21. hikyuu/cpp/hikyuu.lib +0 -0
  22. hikyuu/draw/__init__.pyi +1 -1
  23. hikyuu/draw/drawplot/__init__.py +2 -0
  24. hikyuu/draw/drawplot/__init__.pyi +9 -8
  25. hikyuu/draw/drawplot/bokeh_draw.pyi +519 -506
  26. hikyuu/draw/drawplot/common.pyi +1 -1
  27. hikyuu/draw/drawplot/echarts_draw.pyi +521 -508
  28. hikyuu/draw/drawplot/matplotlib_draw.py +80 -0
  29. hikyuu/draw/drawplot/matplotlib_draw.pyi +540 -517
  30. hikyuu/draw/elder.pyi +11 -11
  31. hikyuu/draw/kaufman.pyi +18 -18
  32. hikyuu/draw/volume.pyi +10 -10
  33. hikyuu/examples/notebook/002-HowToGetStock.ipynb +1 -1
  34. hikyuu/examples/notebook/004-IndicatorOverview.ipynb +117 -52
  35. hikyuu/extend.pyi +507 -500
  36. hikyuu/gui/HikyuuTDX.py +85 -15
  37. hikyuu/gui/data/ImportQmtToH5Task.py +209 -0
  38. hikyuu/gui/data/ImportTdxToH5Task.py +8 -1
  39. hikyuu/gui/data/MainWindow.py +94 -13
  40. hikyuu/gui/data/UseQmtImportToH5Thread.py +316 -0
  41. hikyuu/gui/data/UseTdxImportToH5Thread.py +221 -65
  42. hikyuu/gui/dataserver.py +25 -0
  43. hikyuu/gui/images/star.png +0 -0
  44. hikyuu/gui/importdata.py +24 -11
  45. hikyuu/hub.pyi +6 -6
  46. hikyuu/include/hikyuu/KData.h +5 -0
  47. hikyuu/include/hikyuu/KDataImp.h +4 -0
  48. hikyuu/include/hikyuu/StockManager.h +23 -0
  49. hikyuu/include/hikyuu/data_driver/kdata/mysql/KRecordTable.h +41 -2
  50. hikyuu/include/hikyuu/global/agent/spot_generated.h +3 -3
  51. hikyuu/include/hikyuu/indicator/crt/COUNT.h +3 -3
  52. hikyuu/include/hikyuu/indicator/crt/DISCARD.h +1 -1
  53. hikyuu/include/hikyuu/indicator/crt/ISINF.h +1 -1
  54. hikyuu/include/hikyuu/indicator/crt/ISINFA.h +1 -1
  55. hikyuu/include/hikyuu/indicator/crt/ISNA.h +1 -1
  56. hikyuu/include/hikyuu/indicator/crt/LAST.h +2 -2
  57. hikyuu/include/hikyuu/indicator/crt/MAX.h +1 -1
  58. hikyuu/include/hikyuu/indicator/crt/MIN.h +1 -1
  59. hikyuu/include/hikyuu/indicator/crt/PRICELIST.h +1 -15
  60. hikyuu/include/hikyuu/indicator/crt/SUMBARS.h +1 -1
  61. hikyuu/include/hikyuu/plugin/KDataToHdf5Importer.h +33 -0
  62. hikyuu/include/hikyuu/plugin/__init__.py +1 -0
  63. hikyuu/include/hikyuu/plugin/backtest.h +37 -0
  64. hikyuu/include/hikyuu/plugin/dataserver.h +18 -0
  65. hikyuu/include/hikyuu/plugin/device.h +29 -0
  66. hikyuu/include/hikyuu/plugin/interface/BackTestPluginInterface.h +26 -0
  67. hikyuu/include/hikyuu/plugin/interface/DataServerPluginInterface.h +23 -0
  68. hikyuu/include/hikyuu/plugin/interface/DevicePluginInterface.h +25 -0
  69. hikyuu/include/hikyuu/plugin/interface/ImportKDataToHdf5PluginInterface.h +33 -0
  70. hikyuu/include/hikyuu/plugin/interface/__init__.py +1 -0
  71. hikyuu/include/hikyuu/plugin/interface/plugins.h +22 -0
  72. hikyuu/include/hikyuu/python/pybind_utils.h +8 -0
  73. hikyuu/include/hikyuu/strategy/BrokerTradeManager.h +2 -1
  74. hikyuu/include/hikyuu/strategy/RunPortfolioInStrategy.h +1 -0
  75. hikyuu/include/hikyuu/strategy/Strategy.h +93 -16
  76. hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +4 -2
  77. hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +2 -1
  78. hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +12 -9
  79. hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector.h +1 -1
  80. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorSelector.h +12 -12
  81. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorValueSelector.h +2 -2
  82. hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/PerformanceOptimalSelector.h +1 -1
  83. hikyuu/include/hikyuu/trade_sys/system/System.h +12 -3
  84. hikyuu/include/hikyuu/trade_sys/system/imp/DelegateSystem.h +0 -1
  85. hikyuu/include/hikyuu/trade_sys/system/imp/WalkForwardSystem.h +0 -1
  86. hikyuu/include/hikyuu/trade_sys/system/imp/WalkForwardTradeManager.h +3 -2
  87. hikyuu/include/hikyuu/utilities/arithmetic.h +32 -22
  88. hikyuu/include/hikyuu/utilities/datetime/Datetime.h +1 -0
  89. hikyuu/include/hikyuu/utilities/plugin/PluginClient.h +2 -2
  90. hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +66 -13
  91. hikyuu/include/hikyuu/utilities/plugin/PluginManager.h +72 -0
  92. hikyuu/include/hikyuu/version.h +5 -5
  93. hikyuu/plugin/__init__.py +1 -0
  94. hikyuu/plugin/backtest.dll +0 -0
  95. hikyuu/plugin/dataserver.dll +0 -0
  96. hikyuu/plugin/device.dll +0 -0
  97. hikyuu/plugin/import2hdf5.dll +0 -0
  98. hikyuu/strategy/strategy_demo1.py +7 -8
  99. hikyuu/strategy/strategy_demo2.py +1 -1
  100. hikyuu/trade_manage/__init__.pyi +518 -505
  101. hikyuu/trade_manage/broker.pyi +3 -3
  102. hikyuu/trade_manage/broker_easytrader.pyi +1 -1
  103. hikyuu/trade_manage/trade.pyi +518 -505
  104. hikyuu/util/__init__.py +1 -0
  105. hikyuu/util/__init__.pyi +2 -1
  106. hikyuu/util/mylog.py +30 -3
  107. hikyuu/util/mylog.pyi +3 -1
  108. hikyuu/util/singleton.pyi +1 -1
  109. {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/METADATA +6 -2
  110. {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/RECORD +115 -97
  111. {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/entry_points.txt +1 -0
  112. {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/top_level.txt +4 -0
  113. hikyuu/cpp/core38.pyd +0 -0
  114. hikyuu/cpp/core38.pyi +0 -13173
  115. hikyuu/examples/notebook/011-PyechartsDrawplot.ipynb +0 -21821
  116. /hikyuu/gui/{hikyuu_small.png → images/hikyuu_small.png} +0 -0
  117. {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/LICENSE +0 -0
  118. {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,316 @@
1
+ # coding:utf-8
2
+ #
3
+ # The MIT License (MIT)
4
+ #
5
+ # Copyright (c) 2010-2017 fasiondog/hikyuu
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+ import logging
26
+ import sqlite3
27
+ import datetime
28
+ import mysql.connector
29
+ import queue
30
+ from multiprocessing import Queue, Process
31
+ from PyQt5.QtCore import QThread, pyqtSignal
32
+ from hikyuu.gui.data.ImportQmtToH5Task import ImportQmtToH5Task
33
+ from hikyuu.gui.data.ImportWeightToSqliteTask import ImportWeightToSqliteTask
34
+ from hikyuu.gui.data.ImportQmtToH5Task import ImportQmtToH5Task
35
+ from hikyuu.gui.data.ImportHistoryFinanceTask import ImportHistoryFinanceTask
36
+ from hikyuu.gui.data.ImportBlockInfoTask import ImportBlockInfoTask
37
+ from hikyuu.gui.data.ImportZhBond10Task import ImportZhBond10Task
38
+ from pytdx.hq import TdxHq_API
39
+ from hikyuu.data.common_pytdx import search_best_tdx
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
51
+
52
+
53
+ class UseQmtImportToH5Thread(QThread):
54
+ message = pyqtSignal(list)
55
+
56
+ def __init__(self, parent, config):
57
+ super(UseQmtImportToH5Thread, self).__init__()
58
+ self.parent = parent
59
+ self.log_queue = parent.mp_log_q if parent is not None else None
60
+ self.config = config
61
+ self.msg_name = 'HDF5_IMPORT'
62
+
63
+ self.process_list = []
64
+ self.hosts = []
65
+ self.tasks = []
66
+
67
+ self.quotations = []
68
+ if self.config['quotation']['stock']:
69
+ self.quotations.append('stock')
70
+ if self.config['quotation']['fund']:
71
+ self.quotations.append('fund')
72
+
73
+ self.queue = Queue()
74
+
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']
87
+
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('weight', 'enable', fallback=False):
100
+ task_count += (market_count*2)
101
+
102
+ self.logger.info('搜索通达信服务器')
103
+ self.send_message(['INFO', '搜索通达信服务器'])
104
+ self.hosts = search_best_tdx()
105
+ if not self.hosts:
106
+ self.logger.warn('无法连接通达信行情服务器!请检查网络设置!')
107
+ self.send_message(['INFO', '无法连接通达信行情服务器!请检查网络设置!'])
108
+ return
109
+
110
+ if task_count == 0:
111
+ self.send_message(['INFO', '未选择需要导入的行情数据!'])
112
+ return
113
+
114
+ use_tdx_number = min(
115
+ task_count, len(self.hosts),
116
+ self.config.getint('pytdx', 'use_tdx_number', fallback=10))
117
+ split = task_count // use_tdx_number
118
+ use_hosts = []
119
+ for i in range(use_tdx_number):
120
+ for j in range(split):
121
+ use_hosts.append((self.hosts[i][2], self.hosts[i][3]))
122
+ if len(use_hosts) < task_count:
123
+ for i in range(task_count - len(use_hosts)):
124
+ use_hosts.insert(0, (self.hosts[0][2], self.hosts[0][3]))
125
+ # for i in range(len(use_hosts)):
126
+ # print(i, use_hosts[i])
127
+
128
+ cur_host = 0
129
+ if self.config.getboolean('weight', 'enable', fallback=False):
130
+ for market in g_market_list:
131
+ self.tasks.append(
132
+ ImportWeightToSqliteTask(self.log_queue, self.queue,
133
+ self.config, dest_dir, market, 'weight', self.hosts[cur_host][2],
134
+ self.hosts[cur_host][3]))
135
+ cur_host += 1
136
+ if cur_host >= len(self.hosts):
137
+ cur_host = 0
138
+ self.tasks.append(
139
+ ImportWeightToSqliteTask(self.log_queue, self.queue,
140
+ self.config, dest_dir, market, 'finance', self.hosts[cur_host][2],
141
+ self.hosts[cur_host][3]))
142
+ cur_host += 1
143
+ if cur_host >= len(self.hosts):
144
+ cur_host = 0
145
+
146
+ ktype_list = []
147
+ if self.config.getboolean('ktype', 'day', fallback=False):
148
+ ktype_list.append('DAY')
149
+ if self.config.getboolean('ktype', 'min', fallback=False):
150
+ ktype_list.append('1MIN')
151
+ if self.config.getboolean('ktype', 'min5', fallback=False):
152
+ ktype_list.append('5MIN')
153
+ if len(ktype_list) > 0:
154
+ self.tasks.append(ImportQmtToH5Task(self.log_queue, self.queue, self.config,
155
+ ktype_list, self.quotations, dest_dir))
156
+
157
+ # if self.config.getboolean('ktype', 'day', fallback=False):
158
+ # self.tasks.append(ImportQmtToH5Task(self.log_queue, self.queue, self.config,
159
+ # 'DAY', self.quotations, dest_dir))
160
+ # if self.config.getboolean('ktype', 'min', fallback=False):
161
+ # self.tasks.append(ImportQmtToH5Task(self.log_queue, self.queue, self.config,
162
+ # '1MIN', self.quotations, dest_dir))
163
+ # if self.config.getboolean('ktype', 'min5', fallback=False):
164
+ # self.tasks.append(ImportQmtToH5Task(self.log_queue, self.queue, self.config,
165
+ # '5MIN', self.quotations, dest_dir))
166
+
167
+ def run(self):
168
+ try:
169
+ self.init_task()
170
+ self._run()
171
+ except Exception as e:
172
+ self.logger.error(str(e))
173
+ self.send_message(['THREAD', 'FAILURE', str(e)])
174
+ else:
175
+ self.logger.info('导入完毕')
176
+ self.send_message(['THREAD', 'FINISHED'])
177
+
178
+ @hku_catch(trace=True, re_raise=True)
179
+ def _run(self):
180
+ hdf5_import_progress = {}
181
+ trans_progress = {}
182
+ time_progress = {}
183
+ for market in g_market_list:
184
+ hdf5_import_progress[market] = {'DAY': 0, '1MIN': 0, '5MIN': 0}
185
+ trans_progress[market] = 0
186
+ time_progress[market] = 0
187
+
188
+ # 正在导入代码表
189
+ self.logger.info('导入股票代码表')
190
+ self.send_message(['INFO', '导入股票代码表'])
191
+
192
+ if self.config.getboolean('hdf5', 'enable', fallback=True):
193
+ connect = sqlite3.connect("{}/stock.db".format(
194
+ self.config['hdf5']['dir']))
195
+ create_database = sqlite_create_database
196
+ import_new_holidays = sqlite_import_new_holidays
197
+ import_index_name = sqlite_import_index_name
198
+ import_stock_name = sqlite_import_stock_name
199
+ else:
200
+ db_config = {
201
+ 'user': self.config['mysql']['usr'],
202
+ 'password': self.config['mysql']['pwd'],
203
+ 'host': self.config['mysql']['host'],
204
+ 'port': self.config['mysql']['port']
205
+ }
206
+ connect = mysql.connector.connect(**db_config)
207
+ create_database = mysql_create_database
208
+ import_new_holidays = mysql_import_new_holidays
209
+ import_index_name = mysql_import_index_name
210
+ import_stock_name = mysql_import_stock_name
211
+
212
+ create_database(connect)
213
+
214
+ pytdx_api = TdxHq_API()
215
+ hku_check(pytdx_api.connect(self.hosts[0][2], self.hosts[0][3]),
216
+ "failed connect pytdx {}:{}", self.hosts[0][2],
217
+ self.hosts[0][3])
218
+
219
+ self.logger.info("导入交易所休假日历")
220
+ import_new_holidays(connect)
221
+
222
+ count = import_index_name(connect)
223
+ self.logger.info("指数数量: {}".format(count))
224
+
225
+ for market in g_market_list:
226
+ count = import_stock_name(connect, pytdx_api, market,
227
+ self.quotations)
228
+ if count > 0:
229
+ self.logger.info("{} 新增股票数: {}".format(market, count))
230
+ self.send_message(
231
+ ['INFO', '{} 新增股票数:{}'.format(market, count)])
232
+
233
+ self.process_list.clear()
234
+ for task in self.tasks:
235
+ p = Process(target=task)
236
+ self.process_list.append(p)
237
+ p.start()
238
+
239
+ finished_count = len(self.tasks)
240
+ market_count = len(g_market_list)
241
+ while finished_count > 0:
242
+ try:
243
+ message = self.queue.get(timeout=10)
244
+ taskname, market, ktype, progress, total = message
245
+ if progress is None:
246
+ finished_count -= 1
247
+ if taskname in ('IMPORT_KDATA', 'IMPORT_TRANS',
248
+ 'IMPORT_TIME'):
249
+ self.send_message(
250
+ [taskname, 'FINISHED', market, ktype, total])
251
+ elif taskname == 'IMPORT_BLOCKINFO':
252
+ self.send_message([taskname, ktype])
253
+ elif taskname == 'IMPORT_ZH_BOND10':
254
+ self.send_message([taskname, ktype])
255
+ elif taskname == 'IMPORT_WEIGHT':
256
+ pass
257
+ else:
258
+ self.send_message([taskname, 'FINISHED'])
259
+ continue
260
+
261
+ if taskname == 'IMPORT_WEIGHT':
262
+ if market == 'INFO':
263
+ self.send_message(['INFO', ktype])
264
+ self.send_message([taskname, market, total])
265
+ elif taskname == 'IMPORT_FINANCE':
266
+ self.send_message([taskname, progress])
267
+ elif taskname == 'IMPORT_KDATA':
268
+ hdf5_import_progress[market][ktype] = progress
269
+ current_progress = 0
270
+ for market in g_market_list:
271
+ current_progress += hdf5_import_progress[market][ktype]
272
+ current_progress = current_progress // market_count
273
+ self.send_message([taskname, ktype, current_progress])
274
+ elif taskname == 'IMPORT_TRANS':
275
+ trans_progress[market] = progress
276
+ current_progress = 0
277
+ for market in g_market_list:
278
+ current_progress += trans_progress[market]
279
+ current_progress = current_progress // market_count
280
+ self.send_message([taskname, ktype, current_progress])
281
+ elif taskname == 'IMPORT_TIME':
282
+ time_progress[market] = progress
283
+ current_progress = 0
284
+ for market in g_market_list:
285
+ current_progress += time_progress[market]
286
+ current_progress = current_progress // market_count
287
+ self.send_message([taskname, ktype, current_progress])
288
+ elif taskname == 'IMPORT_BLOCKINFO':
289
+ self.send_message([taskname, market, ktype])
290
+ else:
291
+ self.logger.error("Unknow task: {}".format(taskname))
292
+ except queue.Empty:
293
+ if finished_count > 0:
294
+ ok = False
295
+ for p in self.process_list:
296
+ if p.is_alive():
297
+ ok = True
298
+ break
299
+ if not ok:
300
+ for task in self.tasks:
301
+ self.logger.info(
302
+ f"task ({task.__class__.__name__}) status: {task.status}!"
303
+ )
304
+ for p in self.process_list:
305
+ self.logger.info(
306
+ f"Process exit code: {p.exitcode}")
307
+ finished_count = 0
308
+ self.logger.error(
309
+ "All process is finished, but some tasks are running!"
310
+ )
311
+
312
+ except Exception as e:
313
+ self.logger.error(str(e))
314
+
315
+
316
+ class_logger(UseQmtImportToH5Thread)