hikyuu 2.2.3__py3-none-win_amd64.whl → 2.2.4__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/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/core311.pyd +0 -0
- hikyuu/cpp/core312.pyd +0 -0
- hikyuu/cpp/core313.pyd +0 -0
- hikyuu/cpp/core38.pyd +0 -0
- hikyuu/cpp/core39.pyd +0 -0
- hikyuu/cpp/hikyuu.dll +0 -0
- hikyuu/cpp/hikyuu.lib +0 -0
- hikyuu/data/mysql_upgrade/0024.sql +2 -0
- hikyuu/draw/drawplot/matplotlib_draw.py +6 -1
- hikyuu/examples/notebook/Demo/Demo1.ipynb +85 -84
- hikyuu/gui/HikyuuTDX.py +16 -15
- hikyuu/gui/data/MainWindow.py +14 -11
- hikyuu/hub.py +3 -3
- hikyuu/include/hikyuu/DataType.h +3 -1
- hikyuu/include/hikyuu/StockManager.h +10 -0
- hikyuu/include/hikyuu/data_driver/BlockInfoDriver.h +15 -1
- hikyuu/include/hikyuu/data_driver/block_info/mysql/MySQLBlockInfoDriver.h +8 -1
- hikyuu/include/hikyuu/data_driver/block_info/qianlong/QLBlockInfoDriver.h +3 -1
- hikyuu/include/hikyuu/data_driver/block_info/sqlite/SQLiteBlockInfoDriver.h +8 -1
- hikyuu/include/hikyuu/trade_manage/OrderBrokerBase.h +25 -0
- hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +0 -4
- hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/PerformanceOptimalSelector.h +1 -1
- hikyuu/include/hikyuu/utilities/Parameter.h +2 -2
- hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +1 -0
- hikyuu/include/hikyuu/version.h +4 -4
- hikyuu/test/Datetime.py +12 -12
- hikyuu/test/Indicator.py +36 -36
- hikyuu/test/KData.py +11 -11
- hikyuu/test/Stock.py +10 -10
- {hikyuu-2.2.3.dist-info → hikyuu-2.2.4.dist-info}/METADATA +24 -1
- {hikyuu-2.2.3.dist-info → hikyuu-2.2.4.dist-info}/RECORD +39 -40
- hikyuu/sqlite3.dll +0 -0
- hikyuu/vcruntime140.dll +0 -0
- hikyuu/vcruntime140_1.dll +0 -0
- {hikyuu-2.2.3.dist-info → hikyuu-2.2.4.dist-info}/LICENSE +0 -0
- {hikyuu-2.2.3.dist-info → hikyuu-2.2.4.dist-info}/WHEEL +0 -0
- {hikyuu-2.2.3.dist-info → hikyuu-2.2.4.dist-info}/entry_points.txt +0 -0
- {hikyuu-2.2.3.dist-info → hikyuu-2.2.4.dist-info}/top_level.txt +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
|
|
19
|
+
from PyQt5.QtGui import QIcon, QTextCursor, QFont, QPalette
|
|
20
20
|
|
|
21
21
|
import mysql.connector
|
|
22
22
|
from mysql.connector import errorcode
|
|
@@ -50,11 +50,12 @@ class EmittingStream(QObject):
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
53
|
-
def __init__(self, parent=None, capture_output=False
|
|
53
|
+
def __init__(self, parent=None, capture_output=False):
|
|
54
54
|
super(MyMainWindow, self).__init__(parent)
|
|
55
55
|
self._capture_output = capture_output # 捕获Python stdout 输出
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
palette = QApplication.instance().palette()
|
|
57
|
+
# 获取文字默认颜色
|
|
58
|
+
self._text_color = palette.color(QPalette.WindowText).name()
|
|
58
59
|
self.setupUi(self)
|
|
59
60
|
self.initUI()
|
|
60
61
|
self.initLogger()
|
|
@@ -711,6 +712,14 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
711
712
|
QMessageBox.about(self, "错误", str(e))
|
|
712
713
|
return
|
|
713
714
|
|
|
715
|
+
now = hikyuu.Datetime.now()
|
|
716
|
+
today = hikyuu.Datetime.today()
|
|
717
|
+
if now.day_of_week() not in (0, 6) and hikyuu.TimeDelta(0, 8, 30) < now - today < hikyuu.TimeDelta(0, 15, 45):
|
|
718
|
+
reply = QMessageBox.question(self, '警告', '交易日8:30-15:45分之间导入数据将导致盘后数据错误,是否仍要继续执行导入?',
|
|
719
|
+
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
|
|
720
|
+
if reply == QMessageBox.No:
|
|
721
|
+
return
|
|
722
|
+
|
|
714
723
|
self.import_running = True
|
|
715
724
|
self.start_import_pushButton.setEnabled(False)
|
|
716
725
|
self.reset_progress_bar()
|
|
@@ -797,11 +806,7 @@ def start():
|
|
|
797
806
|
logging.getLogger("requests").setLevel(logging.WARNING)
|
|
798
807
|
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
799
808
|
app = QApplication(sys.argv)
|
|
800
|
-
|
|
801
|
-
if use_dark_style:
|
|
802
|
-
import qdarkstyle
|
|
803
|
-
app.setStyleSheet(qdarkstyle.load_stylesheet(qt_api='pyqt5'))
|
|
804
|
-
myWin = MyMainWindow(capture_output=True, use_dark_style=use_dark_style)
|
|
809
|
+
myWin = MyMainWindow(capture_output=True)
|
|
805
810
|
myWin.show()
|
|
806
811
|
sys.exit(app.exec())
|
|
807
812
|
|
|
@@ -822,18 +827,14 @@ if __name__ == "__main__":
|
|
|
822
827
|
f.setPixelSize(12)
|
|
823
828
|
app.setFont(f)
|
|
824
829
|
|
|
825
|
-
use_dark_style = False # 使用暗黑主题
|
|
826
|
-
if use_dark_style:
|
|
827
|
-
import qdarkstyle
|
|
828
|
-
app.setStyleSheet(qdarkstyle.load_stylesheet(qt_api='pyqt5'))
|
|
829
830
|
if (len(sys.argv) > 1 and sys.argv[1] == '0'):
|
|
830
831
|
FORMAT = '%(asctime)-15s [%(levelname)s]: %(message)s [%(name)s::%(funcName)s]'
|
|
831
832
|
logging.basicConfig(format=FORMAT, level=logging.INFO, handlers=[
|
|
832
833
|
logging.StreamHandler(),
|
|
833
834
|
])
|
|
834
|
-
myWin = MyMainWindow(capture_output=False
|
|
835
|
+
myWin = MyMainWindow(capture_output=False)
|
|
835
836
|
else:
|
|
836
|
-
myWin = MyMainWindow(capture_output=True
|
|
837
|
+
myWin = MyMainWindow(capture_output=True)
|
|
837
838
|
|
|
838
839
|
myWin.show()
|
|
839
840
|
sys.exit(app.exec())
|
hikyuu/gui/data/MainWindow.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Form implementation generated from reading ui file 'MainWindow.ui'
|
|
4
4
|
#
|
|
5
|
-
# Created by: PyQt5 UI code generator 5.15.
|
|
5
|
+
# Created by: PyQt5 UI code generator 5.15.10
|
|
6
6
|
#
|
|
7
7
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
|
8
8
|
# run again. Do not edit this file unless you know what you are doing.
|
|
@@ -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(1131,
|
|
17
|
+
MainWindow.resize(1131, 690)
|
|
18
18
|
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
|
19
19
|
self.centralwidget.setObjectName("centralwidget")
|
|
20
20
|
self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.centralwidget)
|
|
@@ -165,7 +165,7 @@ class Ui_MainWindow(object):
|
|
|
165
165
|
self.label_6.setObjectName("label_6")
|
|
166
166
|
self.gridLayout_4.addWidget(self.label_6, 3, 0, 1, 1)
|
|
167
167
|
self.min5_start_dateEdit = QtWidgets.QDateEdit(self.groupBox_7)
|
|
168
|
-
self.min5_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(
|
|
168
|
+
self.min5_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(1989, 12, 31), QtCore.QTime(0, 0, 0)))
|
|
169
169
|
self.min5_start_dateEdit.setCalendarPopup(True)
|
|
170
170
|
self.min5_start_dateEdit.setObjectName("min5_start_dateEdit")
|
|
171
171
|
self.gridLayout_4.addWidget(self.min5_start_dateEdit, 1, 1, 1, 1)
|
|
@@ -174,9 +174,6 @@ class Ui_MainWindow(object):
|
|
|
174
174
|
self.min_start_dateEdit.setObjectName("min_start_dateEdit")
|
|
175
175
|
self.gridLayout_4.addWidget(self.min_start_dateEdit, 2, 1, 1, 1)
|
|
176
176
|
self.label_3 = QtWidgets.QLabel(self.groupBox_7)
|
|
177
|
-
font = QtGui.QFont()
|
|
178
|
-
font.setPointSize(9)
|
|
179
|
-
self.label_3.setFont(font)
|
|
180
177
|
self.label_3.setObjectName("label_3")
|
|
181
178
|
self.gridLayout_4.addWidget(self.label_3, 0, 0, 1, 1)
|
|
182
179
|
self.label_10 = QtWidgets.QLabel(self.groupBox_7)
|
|
@@ -190,7 +187,7 @@ class Ui_MainWindow(object):
|
|
|
190
187
|
self.trans_start_dateEdit.setObjectName("trans_start_dateEdit")
|
|
191
188
|
self.gridLayout_4.addWidget(self.trans_start_dateEdit, 3, 1, 1, 1)
|
|
192
189
|
self.day_start_dateEdit = QtWidgets.QDateEdit(self.groupBox_7)
|
|
193
|
-
self.day_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(
|
|
190
|
+
self.day_start_dateEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(1989, 12, 31), QtCore.QTime(0, 0, 0)))
|
|
194
191
|
self.day_start_dateEdit.setCalendarPopup(True)
|
|
195
192
|
self.day_start_dateEdit.setObjectName("day_start_dateEdit")
|
|
196
193
|
self.gridLayout_4.addWidget(self.day_start_dateEdit, 0, 1, 1, 1)
|
|
@@ -751,9 +748,12 @@ class Ui_MainWindow(object):
|
|
|
751
748
|
self.label_12.setText(_translate("MainWindow", "导入5分钟线:"))
|
|
752
749
|
self.label_9.setText(_translate("MainWindow", "导入权息数据:"))
|
|
753
750
|
self.import_detail_textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
|
754
|
-
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
|
751
|
+
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
|
|
755
752
|
"p, li { white-space: pre-wrap; }\n"
|
|
756
|
-
"
|
|
753
|
+
"hr { height: 1px; border-width: 0; }\n"
|
|
754
|
+
"li.unchecked::marker { content: \"\\2610\"; }\n"
|
|
755
|
+
"li.checked::marker { content: \"\\2612\"; }\n"
|
|
756
|
+
"</style></head><body style=\" font-family:\'Microsoft YaHei UI\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
|
757
757
|
"<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\';\">导入上证日线记录:</span></p>\n"
|
|
758
758
|
"<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\';\">导入深证日线记录:</span></p>\n"
|
|
759
759
|
"<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\';\">导入上证5分钟线记录:</span></p>\n"
|
|
@@ -808,9 +808,12 @@ class Ui_MainWindow(object):
|
|
|
808
808
|
self.label_38.setText(_translate("MainWindow", "-"))
|
|
809
809
|
self.collect_use_zhima_checkBox.setText(_translate("MainWindow", "使用芝麻代理"))
|
|
810
810
|
self.textBrowser.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
|
811
|
-
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
|
811
|
+
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n"
|
|
812
812
|
"p, li { white-space: pre-wrap; }\n"
|
|
813
|
-
"
|
|
813
|
+
"hr { height: 1px; border-width: 0; }\n"
|
|
814
|
+
"li.unchecked::marker { content: \"\\2610\"; }\n"
|
|
815
|
+
"li.checked::marker { content: \"\\2612\"; }\n"
|
|
816
|
+
"</style></head><body style=\" font-family:\'Microsoft YaHei UI\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
|
814
817
|
"<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\';\">注:</span></p>\n"
|
|
815
818
|
"<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-size:10pt; font-weight:600; color:#ff0000;\">1、行情采集服务仅对预加载数据有效</span><span style=\" font-family:\'SimSun\';\">,在行情采集服务运行期间,hikyuu.interactive运行时将自动连接采集服务获取行情数据,并更新预加载的内容数据。</span></p>\n"
|
|
816
819
|
"<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"
|
hikyuu/hub.py
CHANGED
|
@@ -206,7 +206,7 @@ class HubManager(metaclass=SingletonType):
|
|
|
206
206
|
# 检查并下载 hikyuu 默认策略仓库, hikyuu_hub 避免导入时模块和 hikyuu 重名
|
|
207
207
|
hikyuu_hub_path = self._session.query(HubModel.local).filter(HubModel.name == 'default').first()
|
|
208
208
|
if hikyuu_hub_path is None:
|
|
209
|
-
self.add_remote_hub('default', 'https://gitee.com/fasiondog/hikyuu_hub.git', '
|
|
209
|
+
self.add_remote_hub('default', 'https://gitee.com/fasiondog/hikyuu_hub.git', 'main')
|
|
210
210
|
|
|
211
211
|
def download_remote_hub(self, local_dir, url, branch):
|
|
212
212
|
print('正在下载 hikyuu 策略仓库至:"{}"'.format(local_dir))
|
|
@@ -222,7 +222,7 @@ class HubManager(metaclass=SingletonType):
|
|
|
222
222
|
print('下载完毕')
|
|
223
223
|
|
|
224
224
|
@dbsession
|
|
225
|
-
def add_remote_hub(self, name, url, branch='
|
|
225
|
+
def add_remote_hub(self, name, url, branch='main'):
|
|
226
226
|
"""增加远程策略仓库
|
|
227
227
|
|
|
228
228
|
:param str name: 本地仓库名称(自行起名)
|
|
@@ -502,7 +502,7 @@ class HubManager(metaclass=SingletonType):
|
|
|
502
502
|
return hub_model.name
|
|
503
503
|
|
|
504
504
|
|
|
505
|
-
def add_remote_hub(name, url, branch='
|
|
505
|
+
def add_remote_hub(name, url, branch='main'):
|
|
506
506
|
"""增加远程策略仓库
|
|
507
507
|
|
|
508
508
|
:param str name: 本地仓库名称(自行起名)
|
hikyuu/include/hikyuu/DataType.h
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
#define NOMINMAX
|
|
18
18
|
#endif
|
|
19
19
|
|
|
20
|
+
#include "config.h"
|
|
20
21
|
#include <boost/config.hpp>
|
|
21
22
|
|
|
22
23
|
#include <stdio.h>
|
|
@@ -28,8 +29,9 @@
|
|
|
28
29
|
// #include <vector>
|
|
29
30
|
#include <map>
|
|
30
31
|
#include <unordered_map>
|
|
32
|
+
#include <set>
|
|
33
|
+
#include <unordered_set>
|
|
31
34
|
|
|
32
|
-
#include "config.h"
|
|
33
35
|
#include "utilities/Log.h"
|
|
34
36
|
#include "utilities/osdef.h"
|
|
35
37
|
#include "utilities/cppdef.h"
|
|
@@ -129,6 +129,16 @@ public:
|
|
|
129
129
|
*/
|
|
130
130
|
Block getBlock(const string& category, const string& name);
|
|
131
131
|
|
|
132
|
+
void addBlock(const Block& blk) {
|
|
133
|
+
saveBlock(blk);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void saveBlock(const Block& blk);
|
|
137
|
+
void removeBlock(const string& category, const string& name);
|
|
138
|
+
void removeBlock(const Block& blk) {
|
|
139
|
+
removeBlock(blk.category(), blk.name());
|
|
140
|
+
}
|
|
141
|
+
|
|
132
142
|
/**
|
|
133
143
|
* 获取指定分类的板块列表
|
|
134
144
|
* @param category 板块分类
|
|
@@ -23,7 +23,7 @@ class HKU_API BlockInfoDriver {
|
|
|
23
23
|
|
|
24
24
|
public:
|
|
25
25
|
BlockInfoDriver(const string& name);
|
|
26
|
-
virtual ~BlockInfoDriver(){};
|
|
26
|
+
virtual ~BlockInfoDriver() {};
|
|
27
27
|
|
|
28
28
|
/** 获取驱动名称 */
|
|
29
29
|
const string& name() const;
|
|
@@ -74,6 +74,20 @@ public:
|
|
|
74
74
|
*/
|
|
75
75
|
virtual BlockList getBlockList() = 0;
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* 保存指定的板块
|
|
79
|
+
* @note 如果已存在同名板块,则覆盖;如果板块分类或名称存在修改,需要手工在修改前删除原板块
|
|
80
|
+
* @param block
|
|
81
|
+
*/
|
|
82
|
+
virtual void save(const Block& block) = 0;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 删除指定的板块
|
|
86
|
+
* @param category 板块分类
|
|
87
|
+
* @param name 板块名称
|
|
88
|
+
*/
|
|
89
|
+
virtual void remove(const string& category, const string& name) = 0;
|
|
90
|
+
|
|
77
91
|
private:
|
|
78
92
|
bool checkType();
|
|
79
93
|
|
|
@@ -7,13 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <mutex>
|
|
10
11
|
#include "../../BlockInfoDriver.h"
|
|
11
12
|
|
|
12
13
|
namespace hku {
|
|
13
14
|
|
|
14
15
|
class MySQLBlockInfoDriver : public BlockInfoDriver {
|
|
15
16
|
public:
|
|
16
|
-
MySQLBlockInfoDriver() : BlockInfoDriver("mysql"){};
|
|
17
|
+
MySQLBlockInfoDriver() : BlockInfoDriver("mysql") {};
|
|
17
18
|
virtual ~MySQLBlockInfoDriver();
|
|
18
19
|
|
|
19
20
|
virtual void load() override;
|
|
@@ -21,9 +22,15 @@ public:
|
|
|
21
22
|
virtual Block getBlock(const string&, const string&) override;
|
|
22
23
|
virtual BlockList getBlockList(const string& category) override;
|
|
23
24
|
virtual BlockList getBlockList() override;
|
|
25
|
+
virtual void save(const Block& block) override;
|
|
26
|
+
virtual void remove(const string& category, const string& name) override;
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
DBConnectPtr getConnect();
|
|
24
30
|
|
|
25
31
|
private:
|
|
26
32
|
unordered_map<string, unordered_map<string, Block>> m_buffer;
|
|
33
|
+
std::shared_mutex m_buffer_mutex;
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
} // namespace hku
|
|
@@ -15,13 +15,15 @@ namespace hku {
|
|
|
15
15
|
|
|
16
16
|
class QLBlockInfoDriver : public BlockInfoDriver {
|
|
17
17
|
public:
|
|
18
|
-
QLBlockInfoDriver() : BlockInfoDriver("qianlong"){};
|
|
18
|
+
QLBlockInfoDriver() : BlockInfoDriver("qianlong") {};
|
|
19
19
|
virtual ~QLBlockInfoDriver();
|
|
20
20
|
|
|
21
21
|
virtual bool _init() override;
|
|
22
22
|
virtual Block getBlock(const string&, const string&) override;
|
|
23
23
|
virtual BlockList getBlockList(const string& category) override;
|
|
24
24
|
virtual BlockList getBlockList() override;
|
|
25
|
+
virtual void save(const Block& block) override;
|
|
26
|
+
virtual void remove(const string& category, const string& name) override;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
} /* namespace hku */
|
|
@@ -7,13 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <mutex>
|
|
10
11
|
#include "../../BlockInfoDriver.h"
|
|
11
12
|
|
|
12
13
|
namespace hku {
|
|
13
14
|
|
|
14
15
|
class SQLiteBlockInfoDriver : public BlockInfoDriver {
|
|
15
16
|
public:
|
|
16
|
-
SQLiteBlockInfoDriver() : BlockInfoDriver("sqlite3"){};
|
|
17
|
+
SQLiteBlockInfoDriver() : BlockInfoDriver("sqlite3") {};
|
|
17
18
|
virtual ~SQLiteBlockInfoDriver();
|
|
18
19
|
|
|
19
20
|
virtual void load() override;
|
|
@@ -21,9 +22,15 @@ public:
|
|
|
21
22
|
virtual Block getBlock(const string&, const string&) override;
|
|
22
23
|
virtual BlockList getBlockList(const string& category) override;
|
|
23
24
|
virtual BlockList getBlockList() override;
|
|
25
|
+
virtual void save(const Block& block) override;
|
|
26
|
+
virtual void remove(const string& category, const string& name) override;
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
DBConnectPtr getConnect();
|
|
24
30
|
|
|
25
31
|
private:
|
|
26
32
|
unordered_map<string, unordered_map<string, Block>> m_buffer;
|
|
33
|
+
std::shared_mutex m_buffer_mutex;
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
} // namespace hku
|
|
@@ -147,8 +147,33 @@ public:
|
|
|
147
147
|
|
|
148
148
|
protected:
|
|
149
149
|
string m_name;
|
|
150
|
+
|
|
151
|
+
//============================================
|
|
152
|
+
// 序列化支持
|
|
153
|
+
//============================================
|
|
154
|
+
#if HKU_SUPPORT_SERIALIZATION
|
|
155
|
+
private:
|
|
156
|
+
friend class boost::serialization::access;
|
|
157
|
+
template <class Archive>
|
|
158
|
+
void save(Archive& ar, const unsigned int version) const {
|
|
159
|
+
ar& BOOST_SERIALIZATION_NVP(m_name);
|
|
160
|
+
ar& BOOST_SERIALIZATION_NVP(m_params);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
template <class Archive>
|
|
164
|
+
void load(Archive& ar, const unsigned int version) {
|
|
165
|
+
ar& BOOST_SERIALIZATION_NVP(m_name);
|
|
166
|
+
ar& BOOST_SERIALIZATION_NVP(m_params);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
|
170
|
+
#endif /* HKU_SUPPORT_SERIALIZATION */
|
|
150
171
|
};
|
|
151
172
|
|
|
173
|
+
#if HKU_SUPPORT_SERIALIZATION
|
|
174
|
+
BOOST_SERIALIZATION_ASSUME_ABSTRACT(OrderBrokerBase)
|
|
175
|
+
#endif
|
|
176
|
+
|
|
152
177
|
/**
|
|
153
178
|
* 客户程序应使用此类型进行实际操作
|
|
154
179
|
* @ingroup OrderBroker
|
|
@@ -737,10 +737,6 @@ private:
|
|
|
737
737
|
#endif /* HKU_SUPPORT_SERIALIZATION */
|
|
738
738
|
};
|
|
739
739
|
|
|
740
|
-
#if HKU_SUPPORT_SERIALIZATION
|
|
741
|
-
BOOST_SERIALIZATION_ASSUME_ABSTRACT(TradeManagerBase)
|
|
742
|
-
#endif
|
|
743
|
-
|
|
744
740
|
inline void TradeManagerBase::baseCheckParam(const string& name) const {
|
|
745
741
|
if ("precision" == name) {
|
|
746
742
|
int precision = getParam<int>("precision");
|
|
@@ -22,7 +22,7 @@ public:
|
|
|
22
22
|
virtual void _checkParam(const string& name) const override;
|
|
23
23
|
virtual void calculate(const SystemList& pf_realSysList, const KQuery& query) override;
|
|
24
24
|
|
|
25
|
-
virtual SystemWeightList getSelected(Datetime date);
|
|
25
|
+
virtual SystemWeightList getSelected(Datetime date) override;
|
|
26
26
|
virtual SelectorPtr _clone() override;
|
|
27
27
|
virtual void _reset() override;
|
|
28
28
|
|
|
@@ -463,7 +463,7 @@ void Parameter::set(const string& name, const ValueType& value) {
|
|
|
463
463
|
return;
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
if (m_params[name].type()
|
|
466
|
+
if (strcmp(m_params[name].type().name(), typeid(ValueType).name()) != 0) {
|
|
467
467
|
if ((m_params[name].type() == typeid(int) || m_params[name].type() == typeid(int64_t)) &&
|
|
468
468
|
(typeid(ValueType) == typeid(int) || typeid(ValueType) == typeid(int64_t))) {
|
|
469
469
|
// 忽略,允许设定
|
|
@@ -494,7 +494,7 @@ inline void Parameter::set(const string& name, const boost::any& value) {
|
|
|
494
494
|
return;
|
|
495
495
|
}
|
|
496
496
|
|
|
497
|
-
if (m_params[name].type()
|
|
497
|
+
if (strcmp(m_params[name].type().name(), value.type().name()) != 0) {
|
|
498
498
|
throw std::logic_error("Mismatching type! need type " +
|
|
499
499
|
string(m_params[name].type().name()) + " but value type is " +
|
|
500
500
|
string(value.type().name()));
|
hikyuu/include/hikyuu/version.h
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
#define HKU_VERSION_H
|
|
13
13
|
|
|
14
14
|
// clang-format off
|
|
15
|
-
#define HKU_VERSION "2.2.
|
|
15
|
+
#define HKU_VERSION "2.2.4"
|
|
16
16
|
#define HKU_VERSION_MAJOR 2
|
|
17
17
|
#define HKU_VERSION_MINOR 2
|
|
18
|
-
#define HKU_VERSION_ALTER
|
|
19
|
-
#define HKU_VERSION_BUILD
|
|
18
|
+
#define HKU_VERSION_ALTER 4
|
|
19
|
+
#define HKU_VERSION_BUILD 202412082122
|
|
20
20
|
#define HKU_VERSION_MODE "RELEASE"
|
|
21
|
-
#define HKU_VERSION_GIT "2.2.
|
|
21
|
+
#define HKU_VERSION_GIT "2.2.4 master.2fafc6fb (RELEASE)"
|
|
22
22
|
// clang-format on
|
|
23
23
|
|
|
24
24
|
#endif /* HKU_VERSION_H */
|
hikyuu/test/Datetime.py
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
# -*- coding: utf8 -*-
|
|
3
3
|
# cp936
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# ===============================================================================
|
|
6
6
|
# 作者:fasiondog
|
|
7
7
|
# 历史:1)20120927, Added by fasiondog
|
|
8
|
-
|
|
8
|
+
# ===============================================================================
|
|
9
9
|
|
|
10
10
|
import unittest
|
|
11
11
|
|
|
@@ -24,16 +24,16 @@ class DatetimeTest(unittest.TestCase):
|
|
|
24
24
|
self.assertEqual(Datetime(140001010000), Datetime.min())
|
|
25
25
|
self.assertEqual(Datetime(999912310000), Datetime.max())
|
|
26
26
|
|
|
27
|
-
self.
|
|
28
|
-
self.
|
|
29
|
-
self.
|
|
30
|
-
self.
|
|
31
|
-
self.
|
|
32
|
-
self.
|
|
33
|
-
self.
|
|
34
|
-
self.
|
|
35
|
-
self.
|
|
36
|
-
self.
|
|
27
|
+
self.assertEqual(d, Datetime(201209272301))
|
|
28
|
+
self.assertNotEqual(d, Datetime(200101010000))
|
|
29
|
+
self.assertGreaterEqual(d, Datetime(201209272301))
|
|
30
|
+
self.assertTrue(d >= Datetime(201209272259))
|
|
31
|
+
self.assertTrue(d <= Datetime(201209272301))
|
|
32
|
+
self.assertTrue(d <= Datetime(201209272302))
|
|
33
|
+
self.assertTrue(not (d > Datetime(201209272301)))
|
|
34
|
+
self.assertTrue(d > Datetime(201209272259))
|
|
35
|
+
self.assertTrue(not (d < Datetime(201209272301)))
|
|
36
|
+
self.assertTrue(d < Datetime(201209272302))
|
|
37
37
|
|
|
38
38
|
d = Datetime(200101010159)
|
|
39
39
|
self.assertEqual(str(d), "2001-01-01 01:59:00")
|
hikyuu/test/Indicator.py
CHANGED
|
@@ -48,10 +48,10 @@ class IndicatorTest(unittest.TestCase):
|
|
|
48
48
|
self.assertEqual(m.name, "AddIndicator")
|
|
49
49
|
self.assertEqual(len(m), 4)
|
|
50
50
|
self.assertEqual(m.empty(), False)
|
|
51
|
-
self.
|
|
52
|
-
self.
|
|
53
|
-
self.
|
|
54
|
-
self.
|
|
51
|
+
self.assertTrue(abs(m[0] - 1) < 0.0001)
|
|
52
|
+
self.assertTrue(abs(m[1] - 2) < 0.0001)
|
|
53
|
+
self.assertTrue(abs(m[2] - 3) < 0.0001)
|
|
54
|
+
self.assertTrue(abs(m[3] - 4) < 0.0001)
|
|
55
55
|
|
|
56
56
|
b = toPriceList([1, 2, 3, 4])
|
|
57
57
|
x = PRICELIST(b)
|
|
@@ -59,10 +59,10 @@ class IndicatorTest(unittest.TestCase):
|
|
|
59
59
|
m = m(x)
|
|
60
60
|
self.assertEqual(len(m), 4)
|
|
61
61
|
self.assertEqual(m.empty(), False)
|
|
62
|
-
self.
|
|
63
|
-
self.
|
|
64
|
-
self.
|
|
65
|
-
self.
|
|
62
|
+
self.assertTrue(abs(m[0] - 2) < 0.0001)
|
|
63
|
+
self.assertTrue(abs(m[1] - 3) < 0.0001)
|
|
64
|
+
self.assertTrue(abs(m[2] - 4) < 0.0001)
|
|
65
|
+
self.assertTrue(abs(m[3] - 5) < 0.0001)
|
|
66
66
|
|
|
67
67
|
def test_operator(self):
|
|
68
68
|
a = toPriceList([0, 1, 2, 3, 5])
|
|
@@ -76,16 +76,16 @@ class IndicatorTest(unittest.TestCase):
|
|
|
76
76
|
self.assertEqual(a[3], 7)
|
|
77
77
|
|
|
78
78
|
a = x1 + 1.1
|
|
79
|
-
self.
|
|
80
|
-
self.
|
|
81
|
-
self.
|
|
82
|
-
self.
|
|
79
|
+
self.assertTrue(abs(a[0] - 1.1) < 0.0001)
|
|
80
|
+
self.assertTrue(abs(a[1] - 2.1) < 0.0001)
|
|
81
|
+
self.assertTrue(abs(a[2] - 3.1) < 0.0001)
|
|
82
|
+
self.assertTrue(abs(a[3] - 4.1) < 0.0001)
|
|
83
83
|
|
|
84
84
|
a = 2.1 + x1
|
|
85
|
-
self.
|
|
86
|
-
self.
|
|
87
|
-
self.
|
|
88
|
-
self.
|
|
85
|
+
self.assertTrue(abs(a[0] - 2.1) < 0.0001)
|
|
86
|
+
self.assertTrue(abs(a[1] - 3.1) < 0.0001)
|
|
87
|
+
self.assertTrue(abs(a[2] - 4.1) < 0.0001)
|
|
88
|
+
self.assertTrue(abs(a[3] - 5.1) < 0.0001)
|
|
89
89
|
|
|
90
90
|
a = x2 - x1
|
|
91
91
|
self.assertEqual(a[0], 1)
|
|
@@ -124,10 +124,10 @@ class IndicatorTest(unittest.TestCase):
|
|
|
124
124
|
self.assertEqual(a[3], 6)
|
|
125
125
|
|
|
126
126
|
a = x2 / x1
|
|
127
|
-
self.
|
|
127
|
+
self.assertTrue(isinf(a[0]))
|
|
128
128
|
self.assertEqual(a[1], 2)
|
|
129
129
|
self.assertEqual(a[2], 1.5)
|
|
130
|
-
self.
|
|
130
|
+
self.assertTrue(abs(a[3] - 4.0 / 3.0) < 0.0001)
|
|
131
131
|
|
|
132
132
|
a = x1 / 0.5
|
|
133
133
|
self.assertEqual(a[0], 0)
|
|
@@ -136,10 +136,10 @@ class IndicatorTest(unittest.TestCase):
|
|
|
136
136
|
self.assertEqual(a[3], 6)
|
|
137
137
|
|
|
138
138
|
a = 2. / x1
|
|
139
|
-
self.
|
|
139
|
+
self.assertTrue(isinf(a[0]))
|
|
140
140
|
self.assertEqual(a[1], 2.0)
|
|
141
141
|
self.assertEqual(a[2], 1.)
|
|
142
|
-
self.
|
|
142
|
+
self.assertTrue(abs(a[3] - 2.0/3.0) < 0.0001)
|
|
143
143
|
|
|
144
144
|
a = x1 > x2
|
|
145
145
|
self.assertEqual(a[0], 0 > 1)
|
|
@@ -180,19 +180,19 @@ class IndicatorTest(unittest.TestCase):
|
|
|
180
180
|
self.assertEqual(a.empty(), False)
|
|
181
181
|
self.assertEqual(v.empty(), False)
|
|
182
182
|
|
|
183
|
-
self.
|
|
184
|
-
self.
|
|
185
|
-
self.
|
|
186
|
-
self.
|
|
187
|
-
self.
|
|
188
|
-
self.
|
|
183
|
+
self.assertTrue(abs(o[0] - 96.05) < 0.0001)
|
|
184
|
+
self.assertTrue(abs(h[0] - 99.98) < 0.0001)
|
|
185
|
+
self.assertTrue(abs(l[0] - 95.79) < 0.0001)
|
|
186
|
+
self.assertTrue(abs(c[0] - 99.98) < 0.0001)
|
|
187
|
+
self.assertTrue(abs(a[0] - 49.4) < 0.0001)
|
|
188
|
+
self.assertTrue(abs(v[0] - 1260) < 0.0001)
|
|
189
189
|
|
|
190
|
-
self.
|
|
191
|
-
self.
|
|
192
|
-
self.
|
|
193
|
-
self.
|
|
194
|
-
self.
|
|
195
|
-
self.
|
|
190
|
+
self.assertTrue(abs(o[1] - 104.3) < 0.0001)
|
|
191
|
+
self.assertTrue(abs(h[1] - 104.39) < 0.0001)
|
|
192
|
+
self.assertTrue(abs(l[1] - 99.98) < 0.0001)
|
|
193
|
+
self.assertTrue(abs(c[1] - 104.39) < 0.0001)
|
|
194
|
+
self.assertTrue(abs(a[1] - 8.4) < 0.0001)
|
|
195
|
+
self.assertTrue(abs(v[1] - 197) < 0.0001)
|
|
196
196
|
|
|
197
197
|
def test_MA(self):
|
|
198
198
|
a = toPriceList([0, 1, 2, 3])
|
|
@@ -200,10 +200,10 @@ class IndicatorTest(unittest.TestCase):
|
|
|
200
200
|
m = MA(x, 2)
|
|
201
201
|
self.assertEqual(len(m), 4)
|
|
202
202
|
self.assertEqual(m.discard, 0)
|
|
203
|
-
self.
|
|
204
|
-
self.
|
|
205
|
-
self.
|
|
206
|
-
self.
|
|
203
|
+
self.assertTrue(abs(m[0] - 0.0) < 0.0001)
|
|
204
|
+
self.assertTrue(abs(m[1] - 0.5) < 0.0001)
|
|
205
|
+
self.assertTrue(abs(m[2] - 1.5) < 0.0001)
|
|
206
|
+
self.assertTrue(abs(m[3] - 2.5) < 0.0001)
|
|
207
207
|
|
|
208
208
|
def test_pickle(self):
|
|
209
209
|
if not constant.pickle_support:
|
hikyuu/test/KData.py
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
# -*- coding: utf8 -*-
|
|
3
3
|
# gb18030
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# ===============================================================================
|
|
6
6
|
# 作者:fasiondog
|
|
7
7
|
# 历史:1)20130220, Added by fasiondog
|
|
8
|
-
|
|
8
|
+
# ===============================================================================
|
|
9
9
|
|
|
10
10
|
import unittest
|
|
11
11
|
|
|
@@ -33,14 +33,14 @@ class KDataTest(unittest.TestCase):
|
|
|
33
33
|
self.assertEqual(k.end_pos, 10)
|
|
34
34
|
self.assertEqual(k.last_pos, 9)
|
|
35
35
|
self.assertEqual(k[0].datetime, Datetime(199012190000))
|
|
36
|
-
self.
|
|
37
|
-
self.
|
|
38
|
-
self.
|
|
39
|
-
self.
|
|
40
|
-
self.
|
|
41
|
-
self.
|
|
42
|
-
self.
|
|
43
|
-
self.
|
|
36
|
+
self.assertTrue(abs(k[0].open - 96.05) < 0.0001)
|
|
37
|
+
self.assertTrue(abs(k[0].high - 99.980) < 0.0001)
|
|
38
|
+
self.assertTrue(abs(k[0].low - 95.79) < 0.0001)
|
|
39
|
+
self.assertTrue(abs(k[0].close - 99.98) < 0.0001)
|
|
40
|
+
self.assertTrue(abs(k[0].amount - 49.4) < 0.0001)
|
|
41
|
+
self.assertTrue(abs(k[0].volume - 1260) < 0.0001)
|
|
42
|
+
self.assertTrue(abs(k[1].open - 104.3) < 0.0001)
|
|
43
|
+
self.assertTrue(abs(k[9].open - 127.61) < 0.0001)
|
|
44
44
|
|
|
45
45
|
def test_pickle(self):
|
|
46
46
|
if not constant.pickle_support:
|
|
@@ -61,4 +61,4 @@ class KDataTest(unittest.TestCase):
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def suite():
|
|
64
|
-
return unittest.TestLoader().loadTestsFromTestCase(KDataTest)
|
|
64
|
+
return unittest.TestLoader().loadTestsFromTestCase(KDataTest)
|