hikyuu 2.1.3__cp310-none-win_amd64.whl → 2.1.5__cp310-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/core310.pyd +0 -0
- hikyuu/cpp/hikyuu.dll +0 -0
- hikyuu/cpp/sqlite3.dll +0 -0
- hikyuu/data/em_block_to_mysql.py +45 -31
- hikyuu/data/em_block_to_sqlite.py +48 -33
- hikyuu/data/mysql_upgrade/0020.sql +4 -0
- hikyuu/data/mysql_upgrade/0021.sql +4 -0
- hikyuu/data/mysql_upgrade/0022.sql +5 -0
- hikyuu/data/pytdx_to_h5.py +21 -15
- hikyuu/data/pytdx_to_mysql.py +20 -2
- hikyuu/data/pytdx_weight_to_mysql.py +1 -1
- hikyuu/data/pytdx_weight_to_sqlite.py +1 -1
- hikyuu/data/sqlite_upgrade/0021.sql +6 -0
- hikyuu/data/sqlite_upgrade/0022.sql +6 -0
- hikyuu/data/sqlite_upgrade/0023.sql +7 -0
- hikyuu/fetcher/stock/zh_stock_a_pytdx.py +57 -9
- hikyuu/fetcher/stock/zh_stock_a_qmt.py +3 -3
- hikyuu/fetcher/stock/zh_stock_a_sina_qq.py +15 -5
- hikyuu/gui/HikyuuTDX.py +1 -1
- hikyuu/gui/data/ImportWeightToSqliteTask.py +18 -27
- hikyuu/gui/data/UsePytdxImportToH5Thread.py +17 -6
- hikyuu/gui/data/UseTdxImportToH5Thread.py +30 -6
- hikyuu/gui/spot_server.py +3 -1
- hikyuu/gui/start_qmt.py +99 -13
- hikyuu/include/hikyuu/KQuery.h +5 -2
- hikyuu/include/hikyuu/KRecord.h +1 -1
- hikyuu/include/hikyuu/Stock.h +1 -1
- hikyuu/include/hikyuu/StockManager.h +26 -20
- hikyuu/include/hikyuu/StrategyContext.h +66 -25
- hikyuu/include/hikyuu/data_driver/BaseInfoDriver.h +1 -0
- hikyuu/include/hikyuu/doc.h +1 -1
- hikyuu/include/hikyuu/global/GlobalSpotAgent.h +5 -2
- hikyuu/include/hikyuu/global/agent/SpotAgent.h +28 -6
- hikyuu/include/hikyuu/hikyuu.h +13 -0
- hikyuu/include/hikyuu/indicator/crt/AMA.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/CORR.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/DMA.h +1 -7
- hikyuu/include/hikyuu/indicator/crt/ICIR.h +1 -0
- hikyuu/include/hikyuu/indicator/crt/SMA.h +1 -1
- hikyuu/include/hikyuu/indicator/crt/SPEARMAN.h +1 -1
- hikyuu/include/hikyuu/indicator/imp/IDma.h +47 -0
- hikyuu/include/hikyuu/strategy/BrokerTradeManager.h +1 -2
- hikyuu/include/hikyuu/strategy/Strategy.h +15 -4
- hikyuu/include/hikyuu/trade_manage/OrderBrokerBase.h +3 -0
- hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +1 -2
- hikyuu/include/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.h +0 -1
- hikyuu/include/hikyuu/trade_sys/condition/ConditionBase.h +1 -0
- hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +1 -0
- hikyuu/include/hikyuu/trade_sys/selector/imp/FixedSelector.h +1 -1
- hikyuu/include/hikyuu/trade_sys/selector/imp/OperatorSelector.h +11 -2
- hikyuu/include/hikyuu/trade_sys/selector/imp/OperatorValueSelector.h +19 -2
- hikyuu/include/hikyuu/utilities/Parameter.h +1 -1
- hikyuu/include/hikyuu/utilities/TimerManager.h +2 -2
- hikyuu/include/hikyuu/utilities/arithmetic.h +4 -4
- hikyuu/include/hikyuu/utilities/base64.h +1 -2
- hikyuu/include/hikyuu/utilities/mo/moFileReader.h +2 -2
- hikyuu/include/hikyuu/utilities/node/NodeMessage.h +1 -3
- hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +6 -7
- hikyuu/include/hikyuu/version.h +4 -4
- hikyuu/interactive.py +55 -135
- {hikyuu-2.1.3.dist-info → hikyuu-2.1.5.dist-info}/METADATA +1 -1
- {hikyuu-2.1.3.dist-info → hikyuu-2.1.5.dist-info}/RECORD +66 -61
- hikyuu/include/hikyuu/global/GlobalTaskGroup.h +0 -44
- hikyuu/puppet.py +0 -297
- {hikyuu-2.1.3.dist-info → hikyuu-2.1.5.dist-info}/LICENSE +0 -0
- {hikyuu-2.1.3.dist-info → hikyuu-2.1.5.dist-info}/WHEEL +0 -0
- {hikyuu-2.1.3.dist-info → hikyuu-2.1.5.dist-info}/entry_points.txt +0 -0
- {hikyuu-2.1.3.dist-info → hikyuu-2.1.5.dist-info}/top_level.txt +0 -0
|
@@ -84,14 +84,8 @@ class UsePytdxImportToH5Thread(QThread):
|
|
|
84
84
|
def init_task(self):
|
|
85
85
|
config = self.config
|
|
86
86
|
dest_dir = config['hdf5']['dir']
|
|
87
|
-
sqlite_file_name = dest_dir + "/stock.db"
|
|
88
87
|
|
|
89
88
|
self.tasks = []
|
|
90
|
-
if self.config.getboolean('weight', 'enable', fallback=False):
|
|
91
|
-
self.tasks.append(
|
|
92
|
-
ImportWeightToSqliteTask(self.log_queue, self.queue,
|
|
93
|
-
self.config, dest_dir))
|
|
94
|
-
|
|
95
89
|
if self.config.getboolean('finance', 'enable', fallback=True):
|
|
96
90
|
self.tasks.append(
|
|
97
91
|
ImportHistoryFinanceTask(self.log_queue, self.queue, self.config, dest_dir))
|
|
@@ -112,6 +106,8 @@ class UsePytdxImportToH5Thread(QThread):
|
|
|
112
106
|
task_count += market_count
|
|
113
107
|
if self.config.getboolean('ktype', 'time', fallback=False):
|
|
114
108
|
task_count += market_count
|
|
109
|
+
if self.config.getboolean('weight', 'enable', fallback=False):
|
|
110
|
+
task_count += (market_count*2)
|
|
115
111
|
|
|
116
112
|
self.logger.info('搜索通达信服务器')
|
|
117
113
|
self.send_message(['INFO', '搜索通达信服务器'])
|
|
@@ -210,6 +206,19 @@ class UsePytdxImportToH5Thread(QThread):
|
|
|
210
206
|
start_date.month * 1000000 + start_date.day * 10000))
|
|
211
207
|
cur_host += 1
|
|
212
208
|
|
|
209
|
+
if self.config.getboolean('weight', 'enable', fallback=False):
|
|
210
|
+
for market in g_market_list:
|
|
211
|
+
self.tasks.append(
|
|
212
|
+
ImportWeightToSqliteTask(self.log_queue, self.queue,
|
|
213
|
+
self.config, dest_dir, market, 'weight', use_hosts[cur_host][0],
|
|
214
|
+
use_hosts[cur_host][1]))
|
|
215
|
+
cur_host += 1
|
|
216
|
+
self.tasks.append(
|
|
217
|
+
ImportWeightToSqliteTask(self.log_queue, self.queue,
|
|
218
|
+
self.config, dest_dir, market, 'finance', use_hosts[cur_host][0],
|
|
219
|
+
use_hosts[cur_host][1]))
|
|
220
|
+
cur_host += 1
|
|
221
|
+
|
|
213
222
|
def run(self):
|
|
214
223
|
try:
|
|
215
224
|
self.init_task()
|
|
@@ -298,6 +307,8 @@ class UsePytdxImportToH5Thread(QThread):
|
|
|
298
307
|
self.send_message([taskname, ktype])
|
|
299
308
|
elif taskname == 'IMPORT_ZH_BOND10':
|
|
300
309
|
self.send_message([taskname, ktype])
|
|
310
|
+
elif taskname == 'IMPORT_WEIGHT':
|
|
311
|
+
pass
|
|
301
312
|
else:
|
|
302
313
|
self.send_message([taskname, 'FINISHED'])
|
|
303
314
|
continue
|
|
@@ -30,7 +30,10 @@ from hikyuu.gui.data.ImportTdxToH5Task import ImportTdxToH5Task
|
|
|
30
30
|
from hikyuu.gui.data.ImportWeightToSqliteTask import ImportWeightToSqliteTask
|
|
31
31
|
from hikyuu.gui.data.ImportHistoryFinanceTask import ImportHistoryFinanceTask
|
|
32
32
|
|
|
33
|
+
from pytdx.hq import TdxHq_API
|
|
34
|
+
from hikyuu.data.common import g_market_list
|
|
33
35
|
from hikyuu.data.common_sqlite3 import create_database
|
|
36
|
+
from hikyuu.data.common_pytdx import search_best_tdx
|
|
34
37
|
from hikyuu.data.tdx_to_h5 import tdx_import_stock_name_from_file
|
|
35
38
|
from hikyuu.util import *
|
|
36
39
|
|
|
@@ -57,18 +60,39 @@ class UseTdxImportToH5Thread(QThread):
|
|
|
57
60
|
self.quotations.append('stock')
|
|
58
61
|
if self.config['quotation']['fund']:
|
|
59
62
|
self.quotations.append('fund')
|
|
60
|
-
#if self.config['quotation']['future']:
|
|
63
|
+
# if self.config['quotation']['future']:
|
|
61
64
|
# self.quotations.append('future')
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
#if self.config['quotation']['bond']:
|
|
66
|
+
# 通达信盘后没有债券数据。另外,如果用Pytdx下载债券数据,
|
|
67
|
+
# 每个债券本身的数据很少但债券种类太多占用空间和时间太多,用途较少不再考虑导入
|
|
68
|
+
# if self.config['quotation']['bond']:
|
|
66
69
|
# self.quotations.append('bond')
|
|
67
70
|
|
|
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])
|
|
74
|
+
|
|
68
75
|
self.queue = Queue()
|
|
69
76
|
self.tasks = []
|
|
77
|
+
|
|
78
|
+
cur_host = 0
|
|
70
79
|
if self.config.getboolean('weight', 'enable', fallback=False):
|
|
71
|
-
|
|
80
|
+
for market in g_market_list:
|
|
81
|
+
self.tasks.append(
|
|
82
|
+
ImportWeightToSqliteTask(self.log_queue, self.queue,
|
|
83
|
+
self.config, dest_dir, market, 'weight', hosts[cur_host][2],
|
|
84
|
+
hosts[cur_host][3]))
|
|
85
|
+
cur_host += 1
|
|
86
|
+
if cur_host >= len(hosts):
|
|
87
|
+
cur_host = 0
|
|
88
|
+
self.tasks.append(
|
|
89
|
+
ImportWeightToSqliteTask(self.log_queue, self.queue,
|
|
90
|
+
self.config, dest_dir, market, 'finance', hosts[cur_host][2],
|
|
91
|
+
hosts[cur_host][3]))
|
|
92
|
+
cur_host += 1
|
|
93
|
+
if cur_host >= len(hosts):
|
|
94
|
+
cur_host = 0
|
|
95
|
+
|
|
72
96
|
if self.config.getboolean('finance', 'enable', fallback=True):
|
|
73
97
|
self.tasks.append(ImportHistoryFinanceTask(self.log_queue, self.queue, self.config, dest_dir))
|
|
74
98
|
if self.config.getboolean('ktype', 'day', fallback=False):
|
|
@@ -115,7 +139,7 @@ class UseTdxImportToH5Thread(QThread):
|
|
|
115
139
|
dest_dir = self.config['hdf5']['dir']
|
|
116
140
|
hdf5_import_progress = {'SH': {'DAY': 0, '1MIN': 0, '5MIN': 0}, 'SZ': {'DAY': 0, '1MIN': 0, '5MIN': 0}}
|
|
117
141
|
|
|
118
|
-
|
|
142
|
+
# 正在导入代码表
|
|
119
143
|
self.send_message(['START_IMPORT_CODE'])
|
|
120
144
|
|
|
121
145
|
connect = sqlite3.connect(dest_dir + "/stock.db")
|
hikyuu/gui/spot_server.py
CHANGED
|
@@ -271,7 +271,9 @@ def collect(server, use_proxy, source, seconds, phase1, phase2, ignore_weekend):
|
|
|
271
271
|
|
|
272
272
|
sm = StockManager.instance()
|
|
273
273
|
if source == 'qmt':
|
|
274
|
-
stk_list = [s for s in sm if s.valid
|
|
274
|
+
stk_list = [s for s in sm if s.valid and s.type in (
|
|
275
|
+
constant.STOCKTYPE_A, constant.STOCKTYPE_INDEX, constant.STOCKTYPE_ETF,
|
|
276
|
+
constant.STOCKTYPE_GEM, constant.STOCKTYPE_START, constant.STOCKTYPE_A_BJ)]
|
|
275
277
|
else:
|
|
276
278
|
stk_list = [
|
|
277
279
|
stk.market_code.lower() for stk in sm if stk.valid and stk.type in
|
hikyuu/gui/start_qmt.py
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
from hikyuu.fetcher.stock.zh_stock_a_qmt import parse_one_result_qmt
|
|
5
|
+
from hikyuu.fetcher.stock.zh_stock_a_qmt import parse_one_result_qmt, get_spot
|
|
6
6
|
from hikyuu.gui.spot_server import release_nng_senders, start_send_spot, end_send_spot, send_spot
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def callback(datas):
|
|
10
10
|
records = []
|
|
11
11
|
for stock_code, data in datas.items():
|
|
12
|
-
# print(stock_code, data)
|
|
13
12
|
records.append(parse_one_result_qmt(stock_code, data))
|
|
13
|
+
# print(len(records))
|
|
14
14
|
|
|
15
15
|
if records:
|
|
16
16
|
start_send_spot()
|
|
@@ -19,18 +19,104 @@ def callback(datas):
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
if __name__ == "__main__":
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
import os
|
|
23
|
+
import configparser
|
|
24
|
+
|
|
25
|
+
from hikyuu.data.hku_config_template import generate_default_config
|
|
26
|
+
from hikyuu import *
|
|
27
|
+
|
|
28
|
+
config_file = os.path.expanduser('~') + "/.hikyuu/hikyuu.ini"
|
|
29
|
+
if not os.path.exists(config_file):
|
|
30
|
+
# 创建默认配置
|
|
31
|
+
hku_info("创建默认配置文件")
|
|
32
|
+
generate_default_config()
|
|
33
|
+
|
|
34
|
+
ini = configparser.ConfigParser()
|
|
35
|
+
ini.read(config_file, encoding='utf-8')
|
|
36
|
+
hku_param = Parameter()
|
|
37
|
+
hku_param["tmpdir"] = ini.get('hikyuu', 'tmpdir')
|
|
38
|
+
hku_param["datadir"] = ini.get('hikyuu', 'datadir')
|
|
39
|
+
if ini.has_option('hikyuu', 'quotation_server'):
|
|
40
|
+
hku_param["quotation_server"] = ini['hikyuu']['quotation_server']
|
|
41
|
+
|
|
42
|
+
# 不加载历史财务信息及权息数据
|
|
43
|
+
hku_param["load_history_finance"] = False
|
|
44
|
+
hku_param["load_stock_weight"] = False
|
|
45
|
+
|
|
46
|
+
base_param = Parameter()
|
|
47
|
+
base_info_config = ini.options('baseinfo')
|
|
48
|
+
for p in base_info_config:
|
|
49
|
+
base_param[p] = ini.get('baseinfo', p)
|
|
50
|
+
|
|
51
|
+
block_param = Parameter()
|
|
52
|
+
block_config = ini.options('block')
|
|
53
|
+
for p in block_config:
|
|
54
|
+
block_param[p] = ini.get('block', p)
|
|
55
|
+
|
|
56
|
+
# 不使用配置文件中的预加载参数
|
|
57
|
+
preload_param = Parameter()
|
|
58
|
+
if p in Query.get_all_ktype():
|
|
59
|
+
preload_param[p] = False
|
|
24
60
|
|
|
25
|
-
|
|
26
|
-
|
|
61
|
+
kdata_param = Parameter()
|
|
62
|
+
kdata_config = ini.options('kdata')
|
|
63
|
+
for p in kdata_config:
|
|
64
|
+
if p == "convert":
|
|
65
|
+
kdata_param[p] = ini.getboolean('kdata', p)
|
|
66
|
+
continue
|
|
67
|
+
kdata_param[p] = ini.get('kdata', p)
|
|
27
68
|
|
|
69
|
+
context = StrategyContext(["all"])
|
|
70
|
+
context.ktype_list = ["day"]
|
|
71
|
+
|
|
72
|
+
sm.init(base_param, block_param, kdata_param, preload_param, hku_param, context)
|
|
73
|
+
|
|
74
|
+
# 后续希望每次先主动获取一次全部的tick, 这里需要等待所有数据加载完毕,以便保证全部证券收到第一次tick通知
|
|
75
|
+
hku_info("waiting all data loaded ...")
|
|
76
|
+
while not sm.data_ready:
|
|
77
|
+
import time
|
|
78
|
+
time.sleep(100)
|
|
79
|
+
|
|
80
|
+
stk_list = [s for s in sm if s.valid and s.type in (
|
|
81
|
+
constant.STOCKTYPE_A, constant.STOCKTYPE_INDEX, constant.STOCKTYPE_ETF,
|
|
82
|
+
constant.STOCKTYPE_GEM, constant.STOCKTYPE_START, constant.STOCKTYPE_A_BJ)]
|
|
83
|
+
|
|
84
|
+
hku_info("start xtquant")
|
|
85
|
+
code_list = [f'{s.code}.{s.market}' for s in stk_list]
|
|
86
|
+
from xtquant import xtdata
|
|
28
87
|
xtdata.subscribe_whole_quote(code_list, callback)
|
|
29
88
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
89
|
+
# 每日 9:30 时,主动读取行情一次,以便 hikyuu 生成当日首个分钟线
|
|
90
|
+
while True:
|
|
91
|
+
try:
|
|
92
|
+
today = Datetime.today()
|
|
93
|
+
if today.day_of_week() not in (0, 6) and not sm.is_holiday(today):
|
|
94
|
+
hku_info("get full tick ...")
|
|
95
|
+
start_send_spot()
|
|
96
|
+
records = get_spot(stk_list, None, None, send_spot)
|
|
97
|
+
end_send_spot()
|
|
98
|
+
now = Datetime.now()
|
|
99
|
+
today_open = today + TimeDelta(0, 9, 30)
|
|
100
|
+
if now < today_open:
|
|
101
|
+
delta = today_open - Datetime.now()
|
|
102
|
+
else:
|
|
103
|
+
delta = today_open + Days(1) - Datetime.now()
|
|
104
|
+
hku_info(f"start timer: {delta}s")
|
|
105
|
+
time.sleep(delta.total_seconds())
|
|
106
|
+
except KeyboardInterrupt:
|
|
107
|
+
print("Ctrl-C 终止")
|
|
108
|
+
break
|
|
109
|
+
except Exception as e:
|
|
110
|
+
hku_error(e)
|
|
111
|
+
time.sleep(10)
|
|
112
|
+
|
|
113
|
+
release_nng_senders()
|
|
114
|
+
|
|
115
|
+
# try:
|
|
116
|
+
# xtdata.run()
|
|
117
|
+
# except Exception as e:
|
|
118
|
+
# hku_error(e)
|
|
119
|
+
# finally:
|
|
120
|
+
# # 退出释放资源
|
|
121
|
+
# release_nng_senders()
|
|
122
|
+
# exit(0)
|
hikyuu/include/hikyuu/KQuery.h
CHANGED
|
@@ -70,10 +70,13 @@ public:
|
|
|
70
70
|
// static const string INVALID_KTYPE;
|
|
71
71
|
|
|
72
72
|
/** 获取所有的 KType */
|
|
73
|
-
static vector<
|
|
73
|
+
static const vector<KType>& getAllKType();
|
|
74
74
|
|
|
75
75
|
static int32_t getKTypeInMin(KType);
|
|
76
76
|
|
|
77
|
+
/** 判断是否为有效 ktype */
|
|
78
|
+
static bool isKType(const string& ktype);
|
|
79
|
+
|
|
77
80
|
/**
|
|
78
81
|
* 复权类型
|
|
79
82
|
* @note 日线以上,如周线/月线不支持复权
|
|
@@ -93,7 +96,7 @@ public:
|
|
|
93
96
|
m_end(Null<int64_t>()),
|
|
94
97
|
m_queryType(INDEX),
|
|
95
98
|
m_dataType(DAY),
|
|
96
|
-
m_recoverType(NO_RECOVER){};
|
|
99
|
+
m_recoverType(NO_RECOVER) {};
|
|
97
100
|
|
|
98
101
|
/**
|
|
99
102
|
* K线查询,范围[start, end)
|
hikyuu/include/hikyuu/KRecord.h
CHANGED
hikyuu/include/hikyuu/Stock.h
CHANGED
|
@@ -162,7 +162,7 @@ public:
|
|
|
162
162
|
*/
|
|
163
163
|
bool getIndexRange(const KQuery& query, size_t& out_start, size_t& out_end) const;
|
|
164
164
|
|
|
165
|
-
/** 获取指定索引的K
|
|
165
|
+
/** 获取指定索引的K线数据记录,pos 无效时返回 Null<KRecord> */
|
|
166
166
|
KRecord getKRecord(size_t pos, const KQuery::KType& dataType = KQuery::DAY) const;
|
|
167
167
|
|
|
168
168
|
/** 根据数据类型(日线/周线等),获取指定日期的KRecord */
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
#include <mutex>
|
|
12
12
|
#include <thread>
|
|
13
|
-
#include "utilities/Parameter.h"
|
|
14
|
-
#include "
|
|
13
|
+
#include "hikyuu/utilities/Parameter.h"
|
|
14
|
+
#include "hikyuu/utilities/thread/thread.h"
|
|
15
|
+
#include "hikyuu/data_driver/DataDriverFactory.h"
|
|
15
16
|
#include "Block.h"
|
|
16
17
|
#include "MarketInfo.h"
|
|
17
18
|
#include "StockTypeInfo.h"
|
|
@@ -21,9 +22,6 @@ namespace hku {
|
|
|
21
22
|
|
|
22
23
|
typedef vector<string> MarketList;
|
|
23
24
|
|
|
24
|
-
Parameter default_preload_param();
|
|
25
|
-
Parameter default_other_param();
|
|
26
|
-
|
|
27
25
|
/**
|
|
28
26
|
* 证券信息统一管理类
|
|
29
27
|
* @ingroup StockManage
|
|
@@ -47,8 +45,8 @@ public:
|
|
|
47
45
|
* @param context 策略上下文
|
|
48
46
|
*/
|
|
49
47
|
void init(const Parameter& baseInfoParam, const Parameter& blockParam,
|
|
50
|
-
const Parameter& kdataParam, const Parameter& preloadParam
|
|
51
|
-
const Parameter& hikyuuParam
|
|
48
|
+
const Parameter& kdataParam, const Parameter& preloadParam,
|
|
49
|
+
const Parameter& hikyuuParam,
|
|
52
50
|
const StrategyContext& context = StrategyContext({"all"}));
|
|
53
51
|
|
|
54
52
|
/** 重新加载 */
|
|
@@ -90,6 +88,9 @@ public:
|
|
|
90
88
|
/** 获取证券数量 */
|
|
91
89
|
size_t size() const;
|
|
92
90
|
|
|
91
|
+
/** 是否所有数据准备完毕 */
|
|
92
|
+
bool dataReady() const;
|
|
93
|
+
|
|
93
94
|
/**
|
|
94
95
|
* 根据"市场简称证券代码"获取对应的证券实例
|
|
95
96
|
* @param querystr 格式:“市场简称证券代码”,如"sh000001"
|
|
@@ -218,6 +219,11 @@ public:
|
|
|
218
219
|
return m_thread_id;
|
|
219
220
|
}
|
|
220
221
|
|
|
222
|
+
/** 仅由程序退出使使用!!! */
|
|
223
|
+
ThreadPool* getLoadTaskGroup() {
|
|
224
|
+
return m_load_tg.get();
|
|
225
|
+
}
|
|
226
|
+
|
|
221
227
|
public:
|
|
222
228
|
typedef StockMapIterator const_iterator;
|
|
223
229
|
const_iterator begin() const {
|
|
@@ -228,8 +234,8 @@ public:
|
|
|
228
234
|
}
|
|
229
235
|
|
|
230
236
|
private:
|
|
231
|
-
/*
|
|
232
|
-
void
|
|
237
|
+
/* 加载全部数据 */
|
|
238
|
+
void loadData();
|
|
233
239
|
|
|
234
240
|
/* 加载 K线数据至缓存 */
|
|
235
241
|
void loadAllKData();
|
|
@@ -255,15 +261,13 @@ private:
|
|
|
255
261
|
/** 加载历史财经字段索引 */
|
|
256
262
|
void loadHistoryFinanceField();
|
|
257
263
|
|
|
258
|
-
/** 加载历史财务数据 */
|
|
259
|
-
void loadHistoryFinance();
|
|
260
|
-
|
|
261
264
|
private:
|
|
262
265
|
StockManager();
|
|
263
266
|
|
|
264
267
|
private:
|
|
265
268
|
static StockManager* m_sm;
|
|
266
269
|
std::atomic_bool m_initializing;
|
|
270
|
+
std::atomic_bool m_data_ready; // 用于指示是否所有数据准备完毕
|
|
267
271
|
std::thread::id m_thread_id; // 记录线程id,用于判断Stratege是以独立进程方式还是线程方式运行
|
|
268
272
|
string m_tmpdir;
|
|
269
273
|
string m_datadir;
|
|
@@ -271,18 +275,18 @@ private:
|
|
|
271
275
|
BlockInfoDriverPtr m_blockDriver;
|
|
272
276
|
|
|
273
277
|
StockMapIterator::stock_map_t m_stockDict; // SH000001 -> stock
|
|
274
|
-
std::
|
|
278
|
+
std::shared_mutex* m_stockDict_mutex;
|
|
275
279
|
|
|
276
280
|
typedef unordered_map<string, MarketInfo> MarketInfoMap;
|
|
277
281
|
mutable MarketInfoMap m_marketInfoDict;
|
|
278
|
-
std::
|
|
282
|
+
std::shared_mutex* m_marketInfoDict_mutex;
|
|
279
283
|
|
|
280
284
|
typedef unordered_map<uint32_t, StockTypeInfo> StockTypeInfoMap;
|
|
281
285
|
mutable StockTypeInfoMap m_stockTypeInfo;
|
|
282
|
-
std::
|
|
286
|
+
std::shared_mutex* m_stockTypeInfo_mutex;
|
|
283
287
|
|
|
284
288
|
std::unordered_set<Datetime> m_holidays; // 节假日
|
|
285
|
-
std::
|
|
289
|
+
std::shared_mutex* m_holidays_mutex;
|
|
286
290
|
|
|
287
291
|
ZhBond10List m_zh_bond10; // 10年期中国国债收益率数据
|
|
288
292
|
|
|
@@ -295,18 +299,20 @@ private:
|
|
|
295
299
|
Parameter m_preloadParam;
|
|
296
300
|
Parameter m_hikyuuParam;
|
|
297
301
|
StrategyContext m_context;
|
|
302
|
+
|
|
303
|
+
std::unique_ptr<ThreadPool> m_load_tg; // 异步数据加载辅助线程组
|
|
298
304
|
};
|
|
299
305
|
|
|
300
306
|
inline size_t StockManager::size() const {
|
|
301
307
|
return m_stockDict.size();
|
|
302
308
|
}
|
|
303
309
|
|
|
304
|
-
inline
|
|
305
|
-
return
|
|
310
|
+
inline bool StockManager::dataReady() const {
|
|
311
|
+
return m_data_ready;
|
|
306
312
|
}
|
|
307
313
|
|
|
308
|
-
inline
|
|
309
|
-
return
|
|
314
|
+
inline Stock StockManager::operator[](const string& query) const {
|
|
315
|
+
return getStock(query);
|
|
310
316
|
}
|
|
311
317
|
|
|
312
318
|
inline const Parameter& StockManager::getBaseInfoDriverParameter() const {
|
|
@@ -12,55 +12,96 @@
|
|
|
12
12
|
|
|
13
13
|
namespace hku {
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* 策略上下文,定义策略执行时包含的证券/K线级别信息
|
|
17
|
+
* @ingroup Strategy
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
15
20
|
class HKU_API StrategyContext {
|
|
16
21
|
public:
|
|
17
|
-
StrategyContext()
|
|
18
|
-
StrategyContext(const StrategyContext&) = default;
|
|
19
|
-
|
|
20
|
-
explicit StrategyContext(const vector<string>& stockCodeList)
|
|
21
|
-
: m_stockCodeList(stockCodeList) {}
|
|
22
|
-
explicit StrategyContext(vector<string>&& stockCodeList)
|
|
23
|
-
: m_stockCodeList(std::move(stockCodeList)) {}
|
|
24
|
-
|
|
25
|
-
StrategyContext(const vector<string>& stockCodeList, const vector<KQuery::KType>& ktypeList)
|
|
26
|
-
: m_stockCodeList(stockCodeList), m_ktypeList(ktypeList) {}
|
|
27
|
-
|
|
22
|
+
StrategyContext() = default;
|
|
28
23
|
virtual ~StrategyContext() = default;
|
|
29
24
|
|
|
25
|
+
/**
|
|
26
|
+
* 构造函数
|
|
27
|
+
* @note 未指定 ktypelist 时,默认按预加载参数加载全部
|
|
28
|
+
* @param stockCodeList 指定的证券代码列表,如:如:{"sz000001", "sz000002"}
|
|
29
|
+
*/
|
|
30
|
+
explicit StrategyContext(const vector<string>& stockCodeList);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 构造函数
|
|
34
|
+
* @note 证券列表中如果包含 ("ALL") 则表示全部证券;
|
|
35
|
+
* 指定K线类型列表同时影响着K线数据的优先加载顺序,靠前的将优先加载。同时受系统配置中预加载参数影响!
|
|
36
|
+
* @param stockCodeList 指定的证券代码列表,如:{"sh000001", "sz000001"}
|
|
37
|
+
* @param ktypeList 指定的 K线数据列表,如:{"day", "min"}
|
|
38
|
+
*/
|
|
39
|
+
StrategyContext(const vector<string>& stockCodeList, const vector<KQuery::KType>& ktypeList);
|
|
40
|
+
|
|
41
|
+
// 自定义移动构造与赋值会引起 python 中无法正常退出
|
|
42
|
+
// StrategyContext(const StrategyContext&) = default;
|
|
43
|
+
// StrategyContext(StrategyContext&& rv) = delete;
|
|
44
|
+
// StrategyContext& operator=(const StrategyContext&) = default;
|
|
45
|
+
// StrategyContext& operator=(StrategyContext&&) = delete;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 是否为加载全部证券,只要 stockCodeList 包含 "ALL"(不区分大小写) ,即认为加载全部
|
|
49
|
+
* @return true
|
|
50
|
+
* @return false
|
|
51
|
+
*/
|
|
30
52
|
bool isAll() const noexcept;
|
|
31
53
|
|
|
32
|
-
bool
|
|
54
|
+
bool empty() const noexcept {
|
|
55
|
+
return m_stockCodeList.empty();
|
|
56
|
+
}
|
|
33
57
|
|
|
34
58
|
Datetime startDatetime() const noexcept {
|
|
35
59
|
return m_startDatetime;
|
|
36
60
|
}
|
|
37
61
|
|
|
38
|
-
void
|
|
39
|
-
|
|
40
|
-
m_startDatetime = d;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
void setStockCodeList(vector<string>&& stockList) {
|
|
44
|
-
m_stockCodeList = std::move(stockList);
|
|
62
|
+
void setStockCodeList(const vector<string>& stockList) {
|
|
63
|
+
_removeDuplicateCode(stockList);
|
|
45
64
|
}
|
|
46
65
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const vector<string>& getStockCodeList() const {
|
|
66
|
+
const vector<string>& getStockCodeList() const noexcept {
|
|
50
67
|
return m_stockCodeList;
|
|
51
68
|
}
|
|
52
69
|
|
|
53
|
-
void setKTypeList(const vector<KQuery::KType>& ktypeList)
|
|
70
|
+
void setKTypeList(const vector<KQuery::KType>& ktypeList) {
|
|
71
|
+
_checkAndRemoveDuplicateKType(ktypeList);
|
|
72
|
+
}
|
|
54
73
|
|
|
55
|
-
|
|
56
|
-
const vector<KQuery::KType>& getKTypeList() const {
|
|
74
|
+
const vector<KQuery::KType>& getKTypeList() const noexcept {
|
|
57
75
|
return m_ktypeList;
|
|
58
76
|
}
|
|
59
77
|
|
|
78
|
+
/**
|
|
79
|
+
* 隐含的默认必须被加载的证券列表
|
|
80
|
+
* @note 影响交易日历判断、和某些常被作为默认比较基准的证券,通常被作为某些函数的默认值
|
|
81
|
+
*/
|
|
82
|
+
const vector<string>& getMustLoadStockCodeList() const noexcept {
|
|
83
|
+
return m_mustLoad;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 返回所有需要加载的证券列表(含指定的证券列表和默认包含必须加载的证券列表)
|
|
88
|
+
* @return vector<string>
|
|
89
|
+
*/
|
|
90
|
+
vector<string> getAllNeedLoadStockCodeList() const noexcept;
|
|
91
|
+
|
|
92
|
+
string str() const;
|
|
93
|
+
|
|
94
|
+
private:
|
|
95
|
+
void _removeDuplicateCode(const vector<string>& stockCodeList);
|
|
96
|
+
void _checkAndRemoveDuplicateKType(const vector<KQuery::KType>& ktypeList);
|
|
97
|
+
|
|
60
98
|
private:
|
|
61
99
|
Datetime m_startDatetime{19901219};
|
|
100
|
+
vector<string> m_mustLoad{"sh000001", "sh000300"}; // 默认必须加载的 stock
|
|
62
101
|
vector<string> m_stockCodeList;
|
|
63
102
|
vector<KQuery::KType> m_ktypeList;
|
|
64
103
|
};
|
|
65
104
|
|
|
105
|
+
HKU_API std::ostream& operator<<(std::ostream& os, const StrategyContext& context);
|
|
106
|
+
|
|
66
107
|
} // namespace hku
|
|
@@ -123,6 +123,7 @@ public:
|
|
|
123
123
|
* @param market 市场简称
|
|
124
124
|
* @param code 证券代码
|
|
125
125
|
* @param start 财务报告发布起始日期
|
|
126
|
+
* @param end 查询结束日期
|
|
126
127
|
* @return vector<float> [[财务报告发布日期(ymd), 字段1, 字段2, ...], ...]
|
|
127
128
|
*/
|
|
128
129
|
virtual vector<HistoryFinanceInfo> getHistoryFinance(const string& market, const string& code,
|
hikyuu/include/hikyuu/doc.h
CHANGED
|
@@ -13,9 +13,12 @@ namespace hku {
|
|
|
13
13
|
/**
|
|
14
14
|
* 启动 Spot 数据接收代理,如果之前已经处于运行状态,将抛出异常
|
|
15
15
|
* @param print 打印接收数据进展
|
|
16
|
+
* @param worker_num 接收数据后处理时的工作任务组线程数
|
|
17
|
+
* @param addr 服务端地址,为空表示使用 hikyuu 配置文件中的行情服务器地址
|
|
16
18
|
* @ingroup Agent
|
|
17
19
|
*/
|
|
18
|
-
void HKU_API startSpotAgent(bool print = true
|
|
20
|
+
void HKU_API startSpotAgent(bool print = true, size_t worker_num = 1,
|
|
21
|
+
const string& addr = string());
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
24
|
* 终止 Spot 数据接收代理
|
|
@@ -25,6 +28,6 @@ void HKU_API stopSpotAgent();
|
|
|
25
28
|
|
|
26
29
|
SpotAgent* getGlobalSpotAgent();
|
|
27
30
|
|
|
28
|
-
void releaseGlobalSpotAgent();
|
|
31
|
+
void HKU_API releaseGlobalSpotAgent();
|
|
29
32
|
|
|
30
33
|
} // namespace hku
|
|
@@ -43,12 +43,31 @@ public:
|
|
|
43
43
|
return !m_stop;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
void setWorkerNum(size_t worker_num) {
|
|
47
|
+
m_work_num = worker_num;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
size_t getWorkerNum() const {
|
|
51
|
+
return m_work_num;
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
/** 设置是否打印数据接收进展情况,主要用于在交互环境下关闭打印 */
|
|
47
55
|
void setPrintFlag(bool print) {
|
|
48
|
-
std::lock_guard<std::mutex> lock(m_mutex);
|
|
49
56
|
m_print = print;
|
|
50
57
|
}
|
|
51
58
|
|
|
59
|
+
bool getPrintFlag() const {
|
|
60
|
+
return m_print;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void setServerAddr(const string& addr) {
|
|
64
|
+
m_server_addr = addr;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const string& getServerAddr() const {
|
|
68
|
+
return m_server_addr;
|
|
69
|
+
}
|
|
70
|
+
|
|
52
71
|
/**
|
|
53
72
|
* 增加收到 Spot 数据时的处理函数
|
|
54
73
|
* @note 仅能在停止状态时执行此操作,否则将抛出异常
|
|
@@ -106,15 +125,18 @@ private:
|
|
|
106
125
|
enum STATUS m_status = WAITING; // 当前内部状态
|
|
107
126
|
std::atomic_bool m_stop = true; // 结束代理工作标识
|
|
108
127
|
|
|
109
|
-
int m_revTimeout = 100;
|
|
110
|
-
size_t m_batch_count = 0;
|
|
111
|
-
std::thread m_receiveThread;
|
|
112
|
-
ThreadPool m_tg;
|
|
128
|
+
int m_revTimeout = 100; // 连接数据服务超时时长(毫秒)
|
|
129
|
+
size_t m_batch_count = 0; // 记录本次批次接收的数据数量
|
|
130
|
+
std::thread m_receiveThread; // 数据接收线程
|
|
131
|
+
std::unique_ptr<ThreadPool> m_tg; // 数据处理任务线程池
|
|
132
|
+
size_t m_work_num = 1; // 数据处理任务线程池线程数
|
|
113
133
|
vector<std::future<void>> m_process_task_list;
|
|
114
134
|
|
|
135
|
+
bool m_print = true; // 是否打印连接信息
|
|
136
|
+
string m_server_addr; // 服务器地址
|
|
137
|
+
|
|
115
138
|
// 下面属性被修改时需要加锁,以便可以使用多线程方式运行 strategy
|
|
116
139
|
std::mutex m_mutex;
|
|
117
|
-
bool m_print = true; // 是否打印接收进度,防止的交互模式的影响
|
|
118
140
|
list<std::function<void(const SpotRecord&)>> m_processList; // 已注册的 spot 处理函数列表
|
|
119
141
|
list<std::function<void(Datetime)>> m_postProcessList; // 已注册的批次后处理函数列表
|
|
120
142
|
};
|