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.
- hikyuu/__init__.py +33 -49
- hikyuu/__init__.pyi +530 -516
- hikyuu/analysis/__init__.pyi +498 -490
- hikyuu/analysis/analysis.pyi +499 -491
- hikyuu/core.pyi +500 -492
- hikyuu/cpp/__init__.pyi +2 -2
- hikyuu/cpp/boost_date_time-mt.dll +0 -0
- hikyuu/cpp/boost_serialization-mt.dll +0 -0
- hikyuu/cpp/boost_wserialization-mt.dll +0 -0
- hikyuu/cpp/core310.pyd +0 -0
- hikyuu/cpp/core310.pyi +187 -22
- hikyuu/cpp/core311.pyd +0 -0
- hikyuu/cpp/core311.pyi +187 -22
- hikyuu/cpp/core312.pyd +0 -0
- hikyuu/cpp/core312.pyi +187 -22
- hikyuu/cpp/core313.pyd +0 -0
- hikyuu/cpp/core313.pyi +186 -22
- hikyuu/cpp/core39.pyd +0 -0
- hikyuu/cpp/core39.pyi +187 -22
- hikyuu/cpp/hikyuu.dll +0 -0
- hikyuu/cpp/hikyuu.lib +0 -0
- hikyuu/draw/__init__.pyi +1 -1
- hikyuu/draw/drawplot/__init__.py +2 -0
- hikyuu/draw/drawplot/__init__.pyi +9 -8
- hikyuu/draw/drawplot/bokeh_draw.pyi +519 -506
- hikyuu/draw/drawplot/common.pyi +1 -1
- hikyuu/draw/drawplot/echarts_draw.pyi +521 -508
- hikyuu/draw/drawplot/matplotlib_draw.py +80 -0
- hikyuu/draw/drawplot/matplotlib_draw.pyi +540 -517
- hikyuu/draw/elder.pyi +11 -11
- hikyuu/draw/kaufman.pyi +18 -18
- hikyuu/draw/volume.pyi +10 -10
- hikyuu/examples/notebook/002-HowToGetStock.ipynb +1 -1
- hikyuu/examples/notebook/004-IndicatorOverview.ipynb +117 -52
- hikyuu/extend.pyi +507 -500
- hikyuu/gui/HikyuuTDX.py +85 -15
- hikyuu/gui/data/ImportQmtToH5Task.py +209 -0
- hikyuu/gui/data/ImportTdxToH5Task.py +8 -1
- hikyuu/gui/data/MainWindow.py +94 -13
- hikyuu/gui/data/UseQmtImportToH5Thread.py +316 -0
- hikyuu/gui/data/UseTdxImportToH5Thread.py +221 -65
- hikyuu/gui/dataserver.py +25 -0
- hikyuu/gui/images/star.png +0 -0
- hikyuu/gui/importdata.py +24 -11
- hikyuu/hub.pyi +6 -6
- hikyuu/include/hikyuu/KData.h +5 -0
- hikyuu/include/hikyuu/KDataImp.h +4 -0
- hikyuu/include/hikyuu/StockManager.h +23 -0
- hikyuu/include/hikyuu/data_driver/kdata/mysql/KRecordTable.h +41 -2
- hikyuu/include/hikyuu/global/agent/spot_generated.h +3 -3
- hikyuu/include/hikyuu/indicator/crt/COUNT.h +3 -3
- hikyuu/include/hikyuu/indicator/crt/DISCARD.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/ISINF.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/ISINFA.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/ISNA.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/LAST.h +2 -2
- hikyuu/include/hikyuu/indicator/crt/MAX.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/MIN.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/PRICELIST.h +1 -15
- hikyuu/include/hikyuu/indicator/crt/SUMBARS.h +1 -1
- hikyuu/include/hikyuu/plugin/KDataToHdf5Importer.h +33 -0
- hikyuu/include/hikyuu/plugin/__init__.py +1 -0
- hikyuu/include/hikyuu/plugin/backtest.h +37 -0
- hikyuu/include/hikyuu/plugin/dataserver.h +18 -0
- hikyuu/include/hikyuu/plugin/device.h +29 -0
- hikyuu/include/hikyuu/plugin/interface/BackTestPluginInterface.h +26 -0
- hikyuu/include/hikyuu/plugin/interface/DataServerPluginInterface.h +23 -0
- hikyuu/include/hikyuu/plugin/interface/DevicePluginInterface.h +25 -0
- hikyuu/include/hikyuu/plugin/interface/ImportKDataToHdf5PluginInterface.h +33 -0
- hikyuu/include/hikyuu/plugin/interface/__init__.py +1 -0
- hikyuu/include/hikyuu/plugin/interface/plugins.h +22 -0
- hikyuu/include/hikyuu/python/pybind_utils.h +8 -0
- hikyuu/include/hikyuu/strategy/BrokerTradeManager.h +2 -1
- hikyuu/include/hikyuu/strategy/RunPortfolioInStrategy.h +1 -0
- hikyuu/include/hikyuu/strategy/Strategy.h +93 -16
- hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +4 -2
- hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +2 -1
- hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +12 -9
- hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector.h +1 -1
- hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorSelector.h +12 -12
- hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorValueSelector.h +2 -2
- hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/PerformanceOptimalSelector.h +1 -1
- hikyuu/include/hikyuu/trade_sys/system/System.h +12 -3
- hikyuu/include/hikyuu/trade_sys/system/imp/DelegateSystem.h +0 -1
- hikyuu/include/hikyuu/trade_sys/system/imp/WalkForwardSystem.h +0 -1
- hikyuu/include/hikyuu/trade_sys/system/imp/WalkForwardTradeManager.h +3 -2
- hikyuu/include/hikyuu/utilities/arithmetic.h +32 -22
- hikyuu/include/hikyuu/utilities/datetime/Datetime.h +1 -0
- hikyuu/include/hikyuu/utilities/plugin/PluginClient.h +2 -2
- hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +66 -13
- hikyuu/include/hikyuu/utilities/plugin/PluginManager.h +72 -0
- hikyuu/include/hikyuu/version.h +5 -5
- hikyuu/plugin/__init__.py +1 -0
- hikyuu/plugin/backtest.dll +0 -0
- hikyuu/plugin/dataserver.dll +0 -0
- hikyuu/plugin/device.dll +0 -0
- hikyuu/plugin/import2hdf5.dll +0 -0
- hikyuu/strategy/strategy_demo1.py +7 -8
- hikyuu/strategy/strategy_demo2.py +1 -1
- hikyuu/trade_manage/__init__.pyi +518 -505
- hikyuu/trade_manage/broker.pyi +3 -3
- hikyuu/trade_manage/broker_easytrader.pyi +1 -1
- hikyuu/trade_manage/trade.pyi +518 -505
- hikyuu/util/__init__.py +1 -0
- hikyuu/util/__init__.pyi +2 -1
- hikyuu/util/mylog.py +30 -3
- hikyuu/util/mylog.pyi +3 -1
- hikyuu/util/singleton.pyi +1 -1
- {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/METADATA +6 -2
- {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/RECORD +115 -97
- {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/entry_points.txt +1 -0
- {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/top_level.txt +4 -0
- hikyuu/cpp/core38.pyd +0 -0
- hikyuu/cpp/core38.pyi +0 -13173
- hikyuu/examples/notebook/011-PyechartsDrawplot.ipynb +0 -21821
- /hikyuu/gui/{hikyuu_small.png → images/hikyuu_small.png} +0 -0
- {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/LICENSE +0 -0
- {hikyuu-2.5.6.dist-info → hikyuu-2.6.1.dist-info}/WHEEL +0 -0
hikyuu/gui/HikyuuTDX.py
CHANGED
|
@@ -16,7 +16,7 @@ import PyQt5
|
|
|
16
16
|
|
|
17
17
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox
|
|
18
18
|
from PyQt5.QtCore import pyqtSlot, QObject, pyqtSignal
|
|
19
|
-
from PyQt5.QtGui import QIcon, QTextCursor, QFont, QPalette
|
|
19
|
+
from PyQt5.QtGui import QIcon, QTextCursor, QFont, QPalette, QPixmap
|
|
20
20
|
|
|
21
21
|
import mysql.connector
|
|
22
22
|
from mysql.connector import errorcode
|
|
@@ -27,13 +27,14 @@ from hikyuu.gui.data.EscapetimeThread import EscapetimeThread
|
|
|
27
27
|
from hikyuu.gui.data.UseTdxImportToH5Thread import UseTdxImportToH5Thread
|
|
28
28
|
from hikyuu.gui.data.ImportTdxToH5Task import ImportTdxToH5Task
|
|
29
29
|
from hikyuu.gui.data.UsePytdxImportToH5Thread import UsePytdxImportToH5Thread
|
|
30
|
+
from hikyuu.gui.data.UseQmtImportToH5Thread import UseQmtImportToH5Thread
|
|
30
31
|
# from hikyuu.gui.data.CollectToMySQLThread import CollectToMySQLThread
|
|
31
32
|
# from hikyuu.gui.data.CollectToMemThread import CollectToMemThread
|
|
32
33
|
from hikyuu.gui.data.CollectSpotThread import CollectSpotThread
|
|
33
34
|
from hikyuu.gui.data.SchedImportThread import SchedImportThread
|
|
34
35
|
from hikyuu.gui.spot_server import release_nng_senders
|
|
35
36
|
|
|
36
|
-
from hikyuu import can_upgrade, get_last_version
|
|
37
|
+
from hikyuu import can_upgrade, get_last_version, fetch_trial_license, view_license
|
|
37
38
|
from hikyuu.data import hku_config_template
|
|
38
39
|
from hikyuu.util import *
|
|
39
40
|
|
|
@@ -267,7 +268,14 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
267
268
|
self.log_textEdit.document().setMaximumBlockCount(1000)
|
|
268
269
|
|
|
269
270
|
current_dir = os.path.dirname(__file__)
|
|
270
|
-
icon = QIcon(f"{current_dir}/hikyuu_small.png")
|
|
271
|
+
icon = QIcon(f"{current_dir}/images/hikyuu_small.png")
|
|
272
|
+
star_img = QPixmap(f"{current_dir}/images/star.png")
|
|
273
|
+
self.label_44.setPixmap(star_img)
|
|
274
|
+
self.label_46.setOpenExternalLinks(True)
|
|
275
|
+
self.label_license.setText(view_license())
|
|
276
|
+
if os.path.exists(self.getUserConfigDir() + '/.hikyuu.lic'):
|
|
277
|
+
self.fetch_trial_pushButton.setEnabled(False)
|
|
278
|
+
|
|
271
279
|
self.setWindowIcon(icon)
|
|
272
280
|
QApplication.instance().setWindowIcon(icon)
|
|
273
281
|
self.import_detail_textEdit.clear()
|
|
@@ -309,11 +317,23 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
309
317
|
self.tdx_dir_lineEdit.setEnabled(tdx_enable)
|
|
310
318
|
self.select_tdx_dir_pushButton.setEnabled(tdx_enable)
|
|
311
319
|
self.tdx_dir_lineEdit.setText(tdx_dir)
|
|
320
|
+
if tdx_enable:
|
|
321
|
+
self.use_download = 'tdx'
|
|
312
322
|
|
|
313
323
|
# 初始化pytdx配置及显示
|
|
314
|
-
|
|
324
|
+
use_pytdx_download = import_config.getboolean('pytdx', 'enable', fallback=True)
|
|
325
|
+
self.pytdx_radioButton.setChecked(use_pytdx_download)
|
|
326
|
+
if use_pytdx_download:
|
|
327
|
+
self.use_download = 'pytdx'
|
|
315
328
|
self.use_tdx_number_spinBox.setValue(import_config.getint('pytdx', 'use_tdx_number', fallback=10))
|
|
316
329
|
|
|
330
|
+
# 屏蔽,qmt下载缓慢到发指,且容易中断
|
|
331
|
+
# use_qmt_download = import_config.getboolean('qmt', 'enable', fallback=False)
|
|
332
|
+
# self.qmt_radioButton.setChecked(use_qmt_download)
|
|
333
|
+
# if use_qmt_download:
|
|
334
|
+
# self.use_download = 'qmt'
|
|
335
|
+
self.qmt_radioButton.setEnabled(False)
|
|
336
|
+
|
|
317
337
|
self.on_tdx_or_pytdx_toggled()
|
|
318
338
|
|
|
319
339
|
# 初始化hdf5设置
|
|
@@ -427,6 +447,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
427
447
|
'enable': self.pytdx_radioButton.isChecked(),
|
|
428
448
|
'use_tdx_number': self.use_tdx_number_spinBox.value()
|
|
429
449
|
}
|
|
450
|
+
import_config['qmt'] = {'enable': self.qmt_radioButton.isChecked()}
|
|
430
451
|
import_config['hdf5'] = {
|
|
431
452
|
'enable': self.enable_hdf55_radioButton.isChecked(),
|
|
432
453
|
'dir': self.hdf5_dir_lineEdit.text()
|
|
@@ -494,27 +515,63 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
494
515
|
'5MIN': self.hdf5_5min_progressBar
|
|
495
516
|
}
|
|
496
517
|
|
|
518
|
+
@pyqtSlot()
|
|
519
|
+
def on_fetch_trial_pushButton_clicked(self):
|
|
520
|
+
email = self.email_lineEdit.text()
|
|
521
|
+
info = fetch_trial_license(email)
|
|
522
|
+
QMessageBox.about(self, "获取试用许可", info)
|
|
523
|
+
self.label_license.setText(view_license())
|
|
524
|
+
if os.path.exists(self.getUserConfigDir() + '/.hikyuu.lic'):
|
|
525
|
+
self.fetch_trial_pushButton.setEnabled(False)
|
|
526
|
+
|
|
497
527
|
@pyqtSlot()
|
|
498
528
|
def on_pytdx_radioButton_clicked(self):
|
|
499
529
|
if self.pytdx_radioButton.isChecked():
|
|
500
530
|
self.tdx_radioButton.setChecked(False)
|
|
531
|
+
self.qmt_radioButton.setChecked(False)
|
|
532
|
+
self.use_download = 'pytdx'
|
|
501
533
|
self.on_tdx_or_pytdx_toggled()
|
|
502
534
|
|
|
503
535
|
@pyqtSlot()
|
|
504
536
|
def on_tdx_radioButton_clicked(self):
|
|
505
537
|
if self.tdx_radioButton.isChecked():
|
|
506
538
|
self.pytdx_radioButton.setChecked(False)
|
|
539
|
+
self.qmt_radioButton.setChecked(False)
|
|
540
|
+
self.use_download = 'tdx'
|
|
541
|
+
self.on_tdx_or_pytdx_toggled()
|
|
542
|
+
|
|
543
|
+
def on_qmt_radioButton_clicked(self):
|
|
544
|
+
if self.qmt_radioButton.isChecked():
|
|
545
|
+
self.tdx_radioButton.setChecked(False)
|
|
546
|
+
self.pytdx_radioButton.setChecked(False)
|
|
547
|
+
self.use_download = 'qmt'
|
|
507
548
|
self.on_tdx_or_pytdx_toggled()
|
|
508
549
|
|
|
509
550
|
def on_tdx_or_pytdx_toggled(self):
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
551
|
+
if self.use_download == 'tdx':
|
|
552
|
+
self.tdx_dir_lineEdit.setEnabled(True)
|
|
553
|
+
self.select_tdx_dir_pushButton.setEnabled(True)
|
|
554
|
+
self.import_trans_checkBox.setEnabled(False)
|
|
555
|
+
self.import_time_checkBox.setEnabled(False)
|
|
556
|
+
self.trans_start_dateEdit.setEnabled(False)
|
|
557
|
+
self.time_start_dateEdit.setEnabled(False)
|
|
558
|
+
self.use_tdx_number_spinBox.setEnabled(False)
|
|
559
|
+
elif self.use_download == 'pytdx':
|
|
560
|
+
self.tdx_dir_lineEdit.setEnabled(False)
|
|
561
|
+
self.select_tdx_dir_pushButton.setEnabled(False)
|
|
562
|
+
self.import_trans_checkBox.setEnabled(True)
|
|
563
|
+
self.import_time_checkBox.setEnabled(True)
|
|
564
|
+
self.trans_start_dateEdit.setEnabled(True)
|
|
565
|
+
self.time_start_dateEdit.setEnabled(True)
|
|
566
|
+
self.use_tdx_number_spinBox.setEnabled(True)
|
|
567
|
+
elif self.use_download == 'qmt':
|
|
568
|
+
self.tdx_dir_lineEdit.setEnabled(False)
|
|
569
|
+
self.select_tdx_dir_pushButton.setEnabled(False)
|
|
570
|
+
self.import_trans_checkBox.setEnabled(False)
|
|
571
|
+
self.import_time_checkBox.setEnabled(False)
|
|
572
|
+
self.trans_start_dateEdit.setEnabled(False)
|
|
573
|
+
self.time_start_dateEdit.setEnabled(False)
|
|
574
|
+
self.use_tdx_number_spinBox.setEnabled(False)
|
|
518
575
|
|
|
519
576
|
@pyqtSlot()
|
|
520
577
|
def on_select_tdx_dir_pushButton_clicked(self):
|
|
@@ -646,7 +703,10 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
646
703
|
if ktype != 'FINISHED':
|
|
647
704
|
self.hdf5_import_progress_bar[ktype].setValue(progress)
|
|
648
705
|
else:
|
|
649
|
-
self.
|
|
706
|
+
if self.use_download == 'qmt':
|
|
707
|
+
self.import_detail_textEdit.append('导入 {} 记录数:{}'.format(msg[4], msg[5]))
|
|
708
|
+
else:
|
|
709
|
+
self.import_detail_textEdit.append('导入 {} {} 记录数:{}'.format(msg[3], msg[4], msg[5]))
|
|
650
710
|
|
|
651
711
|
elif msg_task_name == 'IMPORT_TRANS':
|
|
652
712
|
ktype, progress = msg[2:4]
|
|
@@ -732,10 +792,20 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
732
792
|
self.import_status_label.setText("正在启动任务....")
|
|
733
793
|
QApplication.processEvents()
|
|
734
794
|
|
|
735
|
-
if self.
|
|
795
|
+
if self.use_download == 'tdx':
|
|
736
796
|
self.hdf5_import_thread = UseTdxImportToH5Thread(self, config)
|
|
737
|
-
|
|
797
|
+
elif self.use_download == 'pytdx':
|
|
738
798
|
self.hdf5_import_thread = UsePytdxImportToH5Thread(self, config)
|
|
799
|
+
elif self.use_download == 'qmt':
|
|
800
|
+
if sys.platform != 'win32':
|
|
801
|
+
QMessageBox.about(self, "错误", "qmt导入功能仅支持Windows系统!")
|
|
802
|
+
return
|
|
803
|
+
try:
|
|
804
|
+
import xtquant
|
|
805
|
+
except ImportError:
|
|
806
|
+
QMessageBox.about(self, "错误", "请安装xtquant后再次尝试!")
|
|
807
|
+
return
|
|
808
|
+
self.hdf5_import_thread = UseQmtImportToH5Thread(self, config)
|
|
739
809
|
|
|
740
810
|
self.hdf5_import_thread.message.connect(self.on_message_from_thread)
|
|
741
811
|
self.hdf5_import_thread.start()
|
|
@@ -0,0 +1,209 @@
|
|
|
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 time
|
|
26
|
+
import logging
|
|
27
|
+
import sqlite3
|
|
28
|
+
import mysql.connector
|
|
29
|
+
from hikyuu.util.check import hku_catch
|
|
30
|
+
|
|
31
|
+
from hikyuu.util.mylog import class_logger
|
|
32
|
+
from hikyuu.util import capture_multiprocess_all_logger, get_default_logger
|
|
33
|
+
from hikyuu.data.common import g_market_list
|
|
34
|
+
from hikyuu.data.common_sqlite3 import get_stock_list as sqlite_get_stock_list
|
|
35
|
+
from hikyuu.data.common_mysql import get_stock_list as mysql_get_stock_list
|
|
36
|
+
from hikyuu import KDataToHdf5Importer, Query, KRecord, Datetime, KRecordList
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def ktype_to_qmt_period(ktype):
|
|
40
|
+
if ktype == 'DAY':
|
|
41
|
+
return '1d'
|
|
42
|
+
elif ktype == '5MIN':
|
|
43
|
+
return '5m'
|
|
44
|
+
elif ktype == '1MIN':
|
|
45
|
+
return '1m'
|
|
46
|
+
else:
|
|
47
|
+
raise ValueError('ktype must be DAY, 1MIN or 5MIN')
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ProgressBar:
|
|
51
|
+
def __init__(self, src, market, ktype):
|
|
52
|
+
self.src = src
|
|
53
|
+
self.market = market
|
|
54
|
+
self.ktype = ktype
|
|
55
|
+
self.finished = False
|
|
56
|
+
self.total = 0
|
|
57
|
+
self.cur = 0
|
|
58
|
+
|
|
59
|
+
def __call__(self, data):
|
|
60
|
+
print(data)
|
|
61
|
+
self.total = data['total']
|
|
62
|
+
self.cur = data['finished']
|
|
63
|
+
if self.src.queue:
|
|
64
|
+
self.src.queue.put([self.src.task_name, self.market, self.ktype, (self.cur + 1) * 100 // self.total, 0])
|
|
65
|
+
if self.cur == self.total:
|
|
66
|
+
self.finished = True
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ImportQmtToH5Task:
|
|
70
|
+
def __init__(self, log_queue, queue, config, ktype_list, quotations, dest_dir):
|
|
71
|
+
super(ImportQmtToH5Task, self).__init__()
|
|
72
|
+
self.logger = logging.getLogger(self.__class__.__name__)
|
|
73
|
+
self.task_name = 'IMPORT_KDATA'
|
|
74
|
+
self.log_queue = log_queue
|
|
75
|
+
self.queue = queue
|
|
76
|
+
self.config = config
|
|
77
|
+
self.ktype_list = [ktype.upper() for ktype in ktype_list]
|
|
78
|
+
self.quotations = quotations
|
|
79
|
+
self.dest_dir = dest_dir
|
|
80
|
+
self.status = "no run"
|
|
81
|
+
|
|
82
|
+
def __del__(self):
|
|
83
|
+
# print(self.__class__.__name__, self.market, self.ktype, "__del__")
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
@hku_catch(trace=True)
|
|
87
|
+
def __call__(self):
|
|
88
|
+
self.status = "no run"
|
|
89
|
+
capture_multiprocess_all_logger(self.log_queue)
|
|
90
|
+
use_hdf = False
|
|
91
|
+
if self.config.getboolean('hdf5', 'enable', fallback=True):
|
|
92
|
+
sqlite_file = "{}/stock.db".format(self.config['hdf5']['dir'])
|
|
93
|
+
connect = sqlite3.connect(sqlite_file, timeout=1800)
|
|
94
|
+
get_stock_list = sqlite_get_stock_list
|
|
95
|
+
self.logger.debug('use hdf5 import kdata')
|
|
96
|
+
use_hdf = True
|
|
97
|
+
else:
|
|
98
|
+
db_config = {
|
|
99
|
+
'user': self.config['mysql']['usr'],
|
|
100
|
+
'password': self.config['mysql']['pwd'],
|
|
101
|
+
'host': self.config['mysql']['host'],
|
|
102
|
+
'port': self.config['mysql']['port']
|
|
103
|
+
}
|
|
104
|
+
connect = mysql.connector.connect(**db_config)
|
|
105
|
+
get_stock_list = mysql_get_stock_list
|
|
106
|
+
self.logger.debug('use mysql import kdata')
|
|
107
|
+
|
|
108
|
+
from xtquant import xtdata
|
|
109
|
+
total = 0
|
|
110
|
+
for ktype in self.ktype_list:
|
|
111
|
+
for market in g_market_list:
|
|
112
|
+
import time
|
|
113
|
+
start_time = time.time()
|
|
114
|
+
process = ProgressBar(self, market, ktype)
|
|
115
|
+
try:
|
|
116
|
+
code_list = []
|
|
117
|
+
only_code_list = []
|
|
118
|
+
stock_list = get_stock_list(connect, market, self.quotations)
|
|
119
|
+
tmp_list = [f'{stock[2]}.{market}' for stock in stock_list]
|
|
120
|
+
code_list.extend(tmp_list)
|
|
121
|
+
tmp_list = [f'{stock[2]}' for stock in stock_list]
|
|
122
|
+
only_code_list.extend(tmp_list)
|
|
123
|
+
xtdata.download_history_data2(code_list[:1], period=ktype_to_qmt_period(ktype), start_time='', end_time='',
|
|
124
|
+
callback=process, incrementally=True)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
self.logger.error(e)
|
|
127
|
+
|
|
128
|
+
while not process.finished:
|
|
129
|
+
time.sleep(0.1)
|
|
130
|
+
end_time = time.time()
|
|
131
|
+
if (end_time - start_time) > 30 and process.total == 0:
|
|
132
|
+
self.logger.error(f'QMT 超时没反应 {market} {ktype}')
|
|
133
|
+
break
|
|
134
|
+
|
|
135
|
+
total += process.total
|
|
136
|
+
|
|
137
|
+
self.import_qmt_to_h5(market, only_code_list[:1], ktype, self.dest_dir)
|
|
138
|
+
|
|
139
|
+
if self.queue:
|
|
140
|
+
self.queue.put([self.task_name, 'ALL', 'ALL', None, total])
|
|
141
|
+
|
|
142
|
+
self.status = "finished"
|
|
143
|
+
|
|
144
|
+
@hku_catch(trace=True)
|
|
145
|
+
def import_qmt_to_h5(self, market, code_list, ktype, dest_dir):
|
|
146
|
+
im = KDataToHdf5Importer()
|
|
147
|
+
if not im.set_config(dest_dir, [market]):
|
|
148
|
+
self.logger.error('KDataToHdf5Importer set config error! Maybe no license!')
|
|
149
|
+
return
|
|
150
|
+
if ktype == '1MIN':
|
|
151
|
+
nktype = Query.MIN
|
|
152
|
+
elif ktype == '5MIN':
|
|
153
|
+
nktype = Query.MIN5
|
|
154
|
+
elif ktype == 'DAY':
|
|
155
|
+
nktype = Query.DAY
|
|
156
|
+
else:
|
|
157
|
+
self.logger.error(f'Error ktype! {ktype}')
|
|
158
|
+
return
|
|
159
|
+
total = len(code_list)
|
|
160
|
+
cnt = 0
|
|
161
|
+
from xtquant import xtdata
|
|
162
|
+
for code in code_list:
|
|
163
|
+
last_date = im.get_last_datetime(market, code, nktype)
|
|
164
|
+
if not last_date.is_null():
|
|
165
|
+
if last_date >= Datetime.today():
|
|
166
|
+
cnt += 1
|
|
167
|
+
print(f"已导入 {cnt}, 总数: {total}, {market}{code}")
|
|
168
|
+
continue
|
|
169
|
+
df = xtdata.get_local_data(field_list=['open', 'high', 'low', 'close', 'amount', 'volume'],
|
|
170
|
+
stock_list=[f"{code}.{market}",], period=ktype_to_qmt_period(ktype),
|
|
171
|
+
start_time=str(last_date.number*100+1),
|
|
172
|
+
end_time='', count=-1, dividend_type='none', fill_data=False)
|
|
173
|
+
else:
|
|
174
|
+
df = xtdata.get_local_data(field_list=['open', 'high', 'low', 'close', 'amount', 'volume'],
|
|
175
|
+
stock_list=[f"{code}.{market}",], period=ktype_to_qmt_period(ktype),
|
|
176
|
+
dividend_type='none', fill_data=False)
|
|
177
|
+
|
|
178
|
+
if df:
|
|
179
|
+
df = df[f"{code}.{market}"]
|
|
180
|
+
ks = KRecordList()
|
|
181
|
+
for index, row in df.iterrows():
|
|
182
|
+
k = KRecord()
|
|
183
|
+
k.datetime = Datetime(index) if ktype == 'DAY' else Datetime(index/100)
|
|
184
|
+
k.open, k.high, k.low, k.close, k.volume, k.amount = row
|
|
185
|
+
ks.append(k)
|
|
186
|
+
if len(ks) > 0:
|
|
187
|
+
im.add_krecord_list(market, code, ks, nktype)
|
|
188
|
+
if nktype in (Query.DAY, Query.MIN5):
|
|
189
|
+
im.update_index(market, code, nktype)
|
|
190
|
+
|
|
191
|
+
cnt += 1
|
|
192
|
+
print(f"导入hikyuu 已完成: {cnt}, 总数: {total}, {market}{code}")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
if __name__ == '__main__':
|
|
196
|
+
from hikyuu import *
|
|
197
|
+
from configparser import ConfigParser
|
|
198
|
+
import os
|
|
199
|
+
|
|
200
|
+
filename = os.path.expanduser('~') + '/.hikyuu' + '/importdata-gui.ini'
|
|
201
|
+
import_config = ConfigParser()
|
|
202
|
+
import_config.read(filename, encoding='utf-8')
|
|
203
|
+
|
|
204
|
+
from xtquant import xtdata
|
|
205
|
+
# get_default_logger()
|
|
206
|
+
|
|
207
|
+
# self, log_queue, queue, config, ktype, quotations, dest_dir
|
|
208
|
+
task = ImportQmtToH5Task(None, None, import_config, ['DAY'], ['stock', 'fund'], 'd:\\tmp\\stock')
|
|
209
|
+
task()
|
|
@@ -66,11 +66,18 @@ class ImportTdxToH5Task:
|
|
|
66
66
|
self.src_dir = src_dir + "/vipdoc/sz/minline"
|
|
67
67
|
elif self.ktype == '5MIN':
|
|
68
68
|
self.src_dir = src_dir + "/vipdoc/sz/fzline"
|
|
69
|
+
elif self.market == 'BJ':
|
|
70
|
+
if self.ktype == 'DAY':
|
|
71
|
+
self.src_dir = src_dir + "/vipdoc/bj/lday"
|
|
72
|
+
elif self.ktype == '1MIN':
|
|
73
|
+
self.src_dir = src_dir + "/vipdoc/bj/minline"
|
|
74
|
+
elif self.ktype == '5MIN':
|
|
75
|
+
self.src_dir = src_dir + "/vipdoc/bj/fzline"
|
|
69
76
|
self.dest_dir = dest_dir
|
|
70
77
|
self.status = "no run"
|
|
71
78
|
|
|
72
79
|
def __del__(self):
|
|
73
|
-
#print(self.__class__.__name__, self.market, self.ktype, "__del__")
|
|
80
|
+
# print(self.__class__.__name__, self.market, self.ktype, "__del__")
|
|
74
81
|
pass
|
|
75
82
|
|
|
76
83
|
@hku_catch(trace=True)
|
hikyuu/gui/data/MainWindow.py
CHANGED
|
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|
|
14
14
|
class Ui_MainWindow(object):
|
|
15
15
|
def setupUi(self, MainWindow):
|
|
16
16
|
MainWindow.setObjectName("MainWindow")
|
|
17
|
-
MainWindow.resize(1269,
|
|
17
|
+
MainWindow.resize(1269, 797)
|
|
18
18
|
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
|
19
19
|
self.centralwidget.setObjectName("centralwidget")
|
|
20
20
|
self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.centralwidget)
|
|
@@ -75,6 +75,14 @@ class Ui_MainWindow(object):
|
|
|
75
75
|
self.gridLayout_2 = QtWidgets.QGridLayout()
|
|
76
76
|
self.gridLayout_2.setContentsMargins(10, -1, -1, 10)
|
|
77
77
|
self.gridLayout_2.setObjectName("gridLayout_2")
|
|
78
|
+
self.select_tdx_dir_pushButton = QtWidgets.QPushButton(self.groupBox_2)
|
|
79
|
+
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
|
80
|
+
sizePolicy.setHorizontalStretch(0)
|
|
81
|
+
sizePolicy.setVerticalStretch(0)
|
|
82
|
+
sizePolicy.setHeightForWidth(self.select_tdx_dir_pushButton.sizePolicy().hasHeightForWidth())
|
|
83
|
+
self.select_tdx_dir_pushButton.setSizePolicy(sizePolicy)
|
|
84
|
+
self.select_tdx_dir_pushButton.setObjectName("select_tdx_dir_pushButton")
|
|
85
|
+
self.gridLayout_2.addWidget(self.select_tdx_dir_pushButton, 0, 3, 1, 1)
|
|
78
86
|
self.label_2 = QtWidgets.QLabel(self.groupBox_2)
|
|
79
87
|
self.label_2.setObjectName("label_2")
|
|
80
88
|
self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
|
|
@@ -86,15 +94,14 @@ class Ui_MainWindow(object):
|
|
|
86
94
|
self.tdx_dir_lineEdit.setSizePolicy(sizePolicy)
|
|
87
95
|
self.tdx_dir_lineEdit.setObjectName("tdx_dir_lineEdit")
|
|
88
96
|
self.gridLayout_2.addWidget(self.tdx_dir_lineEdit, 0, 1, 1, 2)
|
|
89
|
-
self.select_tdx_dir_pushButton = QtWidgets.QPushButton(self.groupBox_2)
|
|
90
|
-
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
|
91
|
-
sizePolicy.setHorizontalStretch(0)
|
|
92
|
-
sizePolicy.setVerticalStretch(0)
|
|
93
|
-
sizePolicy.setHeightForWidth(self.select_tdx_dir_pushButton.sizePolicy().hasHeightForWidth())
|
|
94
|
-
self.select_tdx_dir_pushButton.setSizePolicy(sizePolicy)
|
|
95
|
-
self.select_tdx_dir_pushButton.setObjectName("select_tdx_dir_pushButton")
|
|
96
|
-
self.gridLayout_2.addWidget(self.select_tdx_dir_pushButton, 0, 3, 1, 1)
|
|
97
97
|
self.verticalLayout_12.addLayout(self.gridLayout_2)
|
|
98
|
+
self.horizontalLayout_24 = QtWidgets.QHBoxLayout()
|
|
99
|
+
self.horizontalLayout_24.setContentsMargins(10, 0, -1, -1)
|
|
100
|
+
self.horizontalLayout_24.setObjectName("horizontalLayout_24")
|
|
101
|
+
self.qmt_radioButton = QtWidgets.QRadioButton(self.groupBox_2)
|
|
102
|
+
self.qmt_radioButton.setObjectName("qmt_radioButton")
|
|
103
|
+
self.horizontalLayout_24.addWidget(self.qmt_radioButton)
|
|
104
|
+
self.verticalLayout_12.addLayout(self.horizontalLayout_24)
|
|
98
105
|
self.verticalLayout_13.addWidget(self.groupBox_2)
|
|
99
106
|
spacerItem2 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
|
100
107
|
self.verticalLayout_13.addItem(spacerItem2)
|
|
@@ -165,7 +172,7 @@ class Ui_MainWindow(object):
|
|
|
165
172
|
self.label_6.setObjectName("label_6")
|
|
166
173
|
self.gridLayout_4.addWidget(self.label_6, 3, 0, 1, 1)
|
|
167
174
|
self.min5_start_dateEdit = QtWidgets.QDateEdit(self.groupBox_7)
|
|
168
|
-
self.min5_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(1989, 12,
|
|
175
|
+
self.min5_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(1989, 12, 27), QtCore.QTime(8, 0, 0)))
|
|
169
176
|
self.min5_start_dateEdit.setCalendarPopup(True)
|
|
170
177
|
self.min5_start_dateEdit.setObjectName("min5_start_dateEdit")
|
|
171
178
|
self.gridLayout_4.addWidget(self.min5_start_dateEdit, 1, 1, 1, 1)
|
|
@@ -187,7 +194,7 @@ class Ui_MainWindow(object):
|
|
|
187
194
|
self.trans_start_dateEdit.setObjectName("trans_start_dateEdit")
|
|
188
195
|
self.gridLayout_4.addWidget(self.trans_start_dateEdit, 3, 1, 1, 1)
|
|
189
196
|
self.day_start_dateEdit = QtWidgets.QDateEdit(self.groupBox_7)
|
|
190
|
-
self.day_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(1989, 12,
|
|
197
|
+
self.day_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(1989, 12, 27), QtCore.QTime(8, 0, 0)))
|
|
191
198
|
self.day_start_dateEdit.setCalendarPopup(True)
|
|
192
199
|
self.day_start_dateEdit.setObjectName("day_start_dateEdit")
|
|
193
200
|
self.gridLayout_4.addWidget(self.day_start_dateEdit, 0, 1, 1, 1)
|
|
@@ -681,6 +688,71 @@ class Ui_MainWindow(object):
|
|
|
681
688
|
self.horizontalLayout_17.addWidget(self.textBrowser)
|
|
682
689
|
self.verticalLayout_2.addLayout(self.horizontalLayout_17)
|
|
683
690
|
self.tabWidget.addTab(self.tab, "")
|
|
691
|
+
self.tab_star = QtWidgets.QWidget()
|
|
692
|
+
self.tab_star.setEnabled(True)
|
|
693
|
+
self.tab_star.setObjectName("tab_star")
|
|
694
|
+
self.label_44 = QtWidgets.QLabel(self.tab_star)
|
|
695
|
+
self.label_44.setGeometry(QtCore.QRect(40, 380, 291, 171))
|
|
696
|
+
self.label_44.setText("")
|
|
697
|
+
self.label_44.setPixmap(QtGui.QPixmap("../images/star.png"))
|
|
698
|
+
self.label_44.setScaledContents(True)
|
|
699
|
+
self.label_44.setObjectName("label_44")
|
|
700
|
+
self.label_46 = QtWidgets.QLabel(self.tab_star)
|
|
701
|
+
self.label_46.setGeometry(QtCore.QRect(30, 20, 561, 221))
|
|
702
|
+
self.label_46.setWordWrap(True)
|
|
703
|
+
self.label_46.setObjectName("label_46")
|
|
704
|
+
self.line_2 = QtWidgets.QFrame(self.tab_star)
|
|
705
|
+
self.line_2.setGeometry(QtCore.QRect(30, 240, 531, 16))
|
|
706
|
+
self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
|
|
707
|
+
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
708
|
+
self.line_2.setObjectName("line_2")
|
|
709
|
+
self.label_47 = QtWidgets.QLabel(self.tab_star)
|
|
710
|
+
self.label_47.setGeometry(QtCore.QRect(40, 260, 151, 16))
|
|
711
|
+
font = QtGui.QFont()
|
|
712
|
+
font.setBold(True)
|
|
713
|
+
self.label_47.setFont(font)
|
|
714
|
+
self.label_47.setObjectName("label_47")
|
|
715
|
+
self.line_3 = QtWidgets.QFrame(self.tab_star)
|
|
716
|
+
self.line_3.setGeometry(QtCore.QRect(30, 330, 531, 16))
|
|
717
|
+
self.line_3.setFrameShape(QtWidgets.QFrame.HLine)
|
|
718
|
+
self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
719
|
+
self.line_3.setObjectName("line_3")
|
|
720
|
+
self.label_48 = QtWidgets.QLabel(self.tab_star)
|
|
721
|
+
self.label_48.setGeometry(QtCore.QRect(40, 356, 331, 16))
|
|
722
|
+
font = QtGui.QFont()
|
|
723
|
+
font.setBold(True)
|
|
724
|
+
self.label_48.setFont(font)
|
|
725
|
+
self.label_48.setObjectName("label_48")
|
|
726
|
+
self.line_4 = QtWidgets.QFrame(self.tab_star)
|
|
727
|
+
self.line_4.setGeometry(QtCore.QRect(30, 560, 531, 16))
|
|
728
|
+
self.line_4.setFrameShape(QtWidgets.QFrame.HLine)
|
|
729
|
+
self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
730
|
+
self.line_4.setObjectName("line_4")
|
|
731
|
+
self.label_49 = QtWidgets.QLabel(self.tab_star)
|
|
732
|
+
self.label_49.setGeometry(QtCore.QRect(40, 580, 81, 16))
|
|
733
|
+
font = QtGui.QFont()
|
|
734
|
+
font.setBold(True)
|
|
735
|
+
self.label_49.setFont(font)
|
|
736
|
+
self.label_49.setObjectName("label_49")
|
|
737
|
+
self.label_license = QtWidgets.QLabel(self.tab_star)
|
|
738
|
+
self.label_license.setGeometry(QtCore.QRect(40, 610, 521, 91))
|
|
739
|
+
self.label_license.setObjectName("label_license")
|
|
740
|
+
self.layoutWidget = QtWidgets.QWidget(self.tab_star)
|
|
741
|
+
self.layoutWidget.setGeometry(QtCore.QRect(40, 290, 511, 33))
|
|
742
|
+
self.layoutWidget.setObjectName("layoutWidget")
|
|
743
|
+
self.horizontalLayout_20 = QtWidgets.QHBoxLayout(self.layoutWidget)
|
|
744
|
+
self.horizontalLayout_20.setContentsMargins(0, 0, 0, 0)
|
|
745
|
+
self.horizontalLayout_20.setObjectName("horizontalLayout_20")
|
|
746
|
+
self.label_45 = QtWidgets.QLabel(self.layoutWidget)
|
|
747
|
+
self.label_45.setObjectName("label_45")
|
|
748
|
+
self.horizontalLayout_20.addWidget(self.label_45)
|
|
749
|
+
self.email_lineEdit = QtWidgets.QLineEdit(self.layoutWidget)
|
|
750
|
+
self.email_lineEdit.setObjectName("email_lineEdit")
|
|
751
|
+
self.horizontalLayout_20.addWidget(self.email_lineEdit)
|
|
752
|
+
self.fetch_trial_pushButton = QtWidgets.QPushButton(self.layoutWidget)
|
|
753
|
+
self.fetch_trial_pushButton.setObjectName("fetch_trial_pushButton")
|
|
754
|
+
self.horizontalLayout_20.addWidget(self.fetch_trial_pushButton)
|
|
755
|
+
self.tabWidget.addTab(self.tab_star, "")
|
|
684
756
|
self.horizontalLayout_12.addWidget(self.tabWidget)
|
|
685
757
|
self.verticalLayout_6 = QtWidgets.QVBoxLayout()
|
|
686
758
|
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
|
@@ -703,12 +775,13 @@ class Ui_MainWindow(object):
|
|
|
703
775
|
_translate = QtCore.QCoreApplication.translate
|
|
704
776
|
MainWindow.setWindowTitle(_translate("MainWindow", "数据导入工具"))
|
|
705
777
|
self.groupBox_2.setTitle(_translate("MainWindow", "数据源设置"))
|
|
706
|
-
self.pytdx_radioButton.setText(_translate("MainWindow", "使用Pytdx
|
|
778
|
+
self.pytdx_radioButton.setText(_translate("MainWindow", "使用Pytdx下载数据"))
|
|
707
779
|
self.label_16.setText(_translate("MainWindow", "同时使用"))
|
|
708
780
|
self.label_17.setText(_translate("MainWindow", "个通达信服务器进行下载"))
|
|
709
781
|
self.tdx_radioButton.setText(_translate("MainWindow", "使用通达信盘后数据(不支持分笔、分时数据,需要配置安装路径)"))
|
|
710
|
-
self.label_2.setText(_translate("MainWindow", "通达信安装目录:"))
|
|
711
782
|
self.select_tdx_dir_pushButton.setText(_translate("MainWindow", "选择"))
|
|
783
|
+
self.label_2.setText(_translate("MainWindow", "通达信安装目录:"))
|
|
784
|
+
self.qmt_radioButton.setText(_translate("MainWindow", "使用 qmt 数据下载(需要 miniqmt)(屏蔽,qmt下载数据太慢,且不稳定)"))
|
|
712
785
|
self.groupBox_7.setTitle(_translate("MainWindow", "导入设置"))
|
|
713
786
|
self.import_weight_checkBox.setText(_translate("MainWindow", "下载权息数据"))
|
|
714
787
|
self.import_stock_checkBox.setText(_translate("MainWindow", "股票"))
|
|
@@ -827,4 +900,12 @@ class Ui_MainWindow(object):
|
|
|
827
900
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'SimSun\';\"><br /></p>\n"
|
|
828
901
|
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\'; font-weight:696; color:#0000ff;\">3、此处采集为网络采集,更推荐直接运行安装目录下gui子目录下的 start_qmt.py ,使用miniqmt 实时服务。该程序独立运行,不用关闭,和这里的采集效果一样。注意:miniqmt需要QMT交易端配合,且在同一机器上执行。</span></p></body></html>"))
|
|
829
902
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "行情采集服务"))
|
|
903
|
+
self.label_46.setText(_translate("MainWindow", "<html><head/><body><p>Hikyuu 作为长期持续维护的开源项目,<span style=\" font-weight:700;\">专注于量化交易领域的核心技术构建,涵盖交易模型开发、极速计算引擎、高效回测框架及实盘拓展能力</span>,定位为量化交易的基础设施级计算引擎,为量化交易爱好者和专业提供高性能底层架构支持。随着社区规模扩大,项目持续迭代及技术支持事务逐渐分散了作者在策略研究上的精力。为保障项目的专注度与可持续性,现推出 "VIP计划",通过提供部分VIP功能作为回馈,构建良性的项目发展生态。诚挚期待社区伙伴的支持,您的参与都将直接助力 Hikyuu 的技术创新,共同推动量化交易基础设施的迭代升级。</p><p>VIP功能以插件的方式提供,采用独立授权许可,完全在 hikyuu 之外,对喜欢自行编译扩展的朋友没有影响。因插件许可授权需要采集硬件信息,如有疑虑只要不申请试用许可和正式许可授权,不会触发硬件信息采集。</p><p><span style=\" font-weight:700;\">正式许可授权除资金支持外,亦可通过其他方式获取,详情参见:</span><a href=\"https://gitee.com/fasiondog/hikyuu/blob/master/vip-plan.md\"><span style=\" font-weight:700; text-decoration: underline; color:#3586ff;\">VIP计划</span></a><span style=\" font-weight:700;\"> 中 "如何获取免费授权和延长授权时间" 章节,已提供的VIP功能亦在其中,可自行查看,感谢大家的支持!</span></p></body></html>"))
|
|
904
|
+
self.label_47.setText(_translate("MainWindow", "申请试用许可(30天试用)"))
|
|
905
|
+
self.label_48.setText(_translate("MainWindow", "加入知识星球,获取星球许可(可同时在3台设备上使用)"))
|
|
906
|
+
self.label_49.setText(_translate("MainWindow", "当前授权信息"))
|
|
907
|
+
self.label_license.setText(_translate("MainWindow", "TextLabel"))
|
|
908
|
+
self.label_45.setText(_translate("MainWindow", "电子邮件地址:"))
|
|
909
|
+
self.fetch_trial_pushButton.setText(_translate("MainWindow", "申请试用许可"))
|
|
910
|
+
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_star), _translate("MainWindow", "项目VIP"))
|
|
830
911
|
self.label_41.setText(_translate("MainWindow", "执行日志"))
|