hikyuu 2.7.0__py3-none-manylinux2014_aarch64.whl → 2.7.3__py3-none-manylinux2014_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. hikyuu/__init__.py +25 -7
  2. hikyuu/__init__.pyi +23 -12
  3. hikyuu/analysis/__init__.pyi +6 -1
  4. hikyuu/analysis/analysis.pyi +7 -2
  5. hikyuu/core.pyi +8 -3
  6. hikyuu/cpp/core310.pyi +94 -24
  7. hikyuu/cpp/core310.so +0 -0
  8. hikyuu/cpp/core311.pyi +94 -24
  9. hikyuu/cpp/core311.so +0 -0
  10. hikyuu/cpp/core312.pyi +94 -24
  11. hikyuu/cpp/core312.so +0 -0
  12. hikyuu/cpp/core313.pyi +94 -24
  13. hikyuu/cpp/core313.so +0 -0
  14. hikyuu/cpp/i18n/zh_CN/hikyuu.mo +0 -0
  15. hikyuu/cpp/i18n/zh_CN/hikyuu_plugin.mo +0 -0
  16. hikyuu/cpp/libboost_atomic.so +0 -0
  17. hikyuu/cpp/libboost_atomic.so.1.90.0 +0 -0
  18. hikyuu/cpp/{libboost_charconv-mt.so → libboost_charconv.so} +0 -0
  19. hikyuu/cpp/{libboost_charconv-mt.so.1.88.0 → libboost_charconv.so.1.90.0} +0 -0
  20. hikyuu/cpp/libboost_chrono.so +0 -0
  21. hikyuu/cpp/libboost_chrono.so.1.90.0 +0 -0
  22. hikyuu/cpp/libboost_container.so +0 -0
  23. hikyuu/cpp/libboost_container.so.1.90.0 +0 -0
  24. hikyuu/cpp/libboost_date_time.so +0 -0
  25. hikyuu/cpp/libboost_date_time.so.1.90.0 +0 -0
  26. hikyuu/cpp/libboost_locale.so +0 -0
  27. hikyuu/cpp/libboost_locale.so.1.90.0 +0 -0
  28. hikyuu/cpp/libboost_random.so +0 -0
  29. hikyuu/cpp/libboost_random.so.1.90.0 +0 -0
  30. hikyuu/cpp/libboost_serialization.so +0 -0
  31. hikyuu/cpp/libboost_serialization.so.1.90.0 +0 -0
  32. hikyuu/cpp/libboost_thread.so +0 -0
  33. hikyuu/cpp/libboost_thread.so.1.90.0 +0 -0
  34. hikyuu/cpp/libboost_wserialization.so +0 -0
  35. hikyuu/cpp/libboost_wserialization.so.1.90.0 +0 -0
  36. hikyuu/cpp/libhikyuu.so +0 -0
  37. hikyuu/cpp/libsqlite3.so +0 -0
  38. hikyuu/data/clickhouse_upgrade/0001.sql +2 -0
  39. hikyuu/data/common_clickhouse.py +1 -3
  40. hikyuu/data/download_block.py +1 -1
  41. hikyuu/data/hku_config_template.py +30 -3
  42. hikyuu/data/mysql_upgrade/0029.sql +2 -0
  43. hikyuu/data/pytdx_to_clickhouse.py +86 -32
  44. hikyuu/data/pytdx_to_h5.py +73 -28
  45. hikyuu/data/pytdx_to_mysql.py +65 -21
  46. hikyuu/data/pytdx_weight_to_clickhouse.py +2 -0
  47. hikyuu/data/pytdx_weight_to_mysql.py +2 -0
  48. hikyuu/data/pytdx_weight_to_sqlite.py +2 -0
  49. hikyuu/data/sqlite_upgrade/0029.sql +4 -0
  50. hikyuu/data/tdx_to_clickhouse.py +2 -2
  51. hikyuu/data/tdx_to_h5.py +11 -11
  52. hikyuu/data/tdx_to_mysql.py +2 -2
  53. hikyuu/draw/drawplot/bokeh_draw.pyi +14 -7
  54. hikyuu/draw/drawplot/echarts_draw.pyi +14 -7
  55. hikyuu/draw/drawplot/matplotlib_draw.py +8 -2
  56. hikyuu/draw/drawplot/matplotlib_draw.pyi +14 -7
  57. hikyuu/extend.pyi +8 -3
  58. hikyuu/gui/HikyuuTDX.py +42 -3
  59. hikyuu/gui/data/MainWindow.py +189 -129
  60. hikyuu/hub.pyi +6 -6
  61. hikyuu/include/hikyuu/StockManager.h +17 -2
  62. hikyuu/include/hikyuu/StrategyContext.h +4 -4
  63. hikyuu/include/hikyuu/data_driver/BaseInfoDriver.h +2 -1
  64. hikyuu/include/hikyuu/data_driver/KDataDriver.h +2 -4
  65. hikyuu/include/hikyuu/data_driver/kdata/mysql/MySQLKDataDriver.h +5 -1
  66. hikyuu/include/hikyuu/data_driver/kdata/sqlite/SQLiteKDataDriver.h +1 -1
  67. hikyuu/include/hikyuu/global/sysinfo.h +24 -5
  68. hikyuu/include/hikyuu/indicator/IndicatorImp.h +1 -1
  69. hikyuu/include/hikyuu/plugin/KDataToClickHouseImporter.h +40 -0
  70. hikyuu/include/hikyuu/plugin/KDataToMySQLImporter.h +40 -0
  71. hikyuu/include/hikyuu/plugin/checkdata.h +20 -0
  72. hikyuu/include/hikyuu/plugin/extind.h +3 -0
  73. hikyuu/include/hikyuu/plugin/hkuextra.h +2 -0
  74. hikyuu/include/hikyuu/plugin/interface/CheckDataPluginInterface.h +25 -0
  75. hikyuu/include/hikyuu/plugin/interface/HkuExtraPluginInterface.h +2 -0
  76. hikyuu/include/hikyuu/plugin/interface/ImportKDataToClickHousePluginInterface.h +44 -0
  77. hikyuu/include/hikyuu/plugin/interface/ImportKDataToMySQLPluginInterface.h +42 -0
  78. hikyuu/include/hikyuu/plugin/interface/plugins.h +6 -0
  79. hikyuu/include/hikyuu/python/convert_any.h +9 -6
  80. hikyuu/include/hikyuu/python/pybind_utils.h +1 -1
  81. hikyuu/include/hikyuu/strategy/Strategy.h +1 -1
  82. hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +0 -1
  83. hikyuu/include/hikyuu/trade_manage/TradeRecord.h +2 -1
  84. hikyuu/include/hikyuu/trade_sys/allocatefunds/AllocateFundsBase.h +0 -1
  85. hikyuu/include/hikyuu/trade_sys/allocatefunds/build_in.h +1 -0
  86. hikyuu/include/hikyuu/trade_sys/allocatefunds/crt/AF_FixedAmount.h +26 -0
  87. hikyuu/include/hikyuu/trade_sys/allocatefunds/imp/FixAmountFunds.h +18 -0
  88. hikyuu/include/hikyuu/trade_sys/condition/ConditionBase.h +0 -1
  89. hikyuu/include/hikyuu/trade_sys/environment/EnvironmentBase.h +0 -1
  90. hikyuu/include/hikyuu/trade_sys/moneymanager/MoneyManagerBase.h +0 -1
  91. hikyuu/include/hikyuu/trade_sys/multifactor/MultiFactorBase.h +0 -1
  92. hikyuu/include/hikyuu/trade_sys/multifactor/NormalizeBase.h +0 -1
  93. hikyuu/include/hikyuu/trade_sys/multifactor/ScoresFilterBase.h +0 -1
  94. hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +13 -13
  95. hikyuu/include/hikyuu/trade_sys/profitgoal/ProfitGoalBase.h +9 -11
  96. hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +0 -1
  97. hikyuu/include/hikyuu/trade_sys/signal/SignalBase.h +0 -1
  98. hikyuu/include/hikyuu/trade_sys/slippage/SlippageBase.h +0 -1
  99. hikyuu/include/hikyuu/trade_sys/stoploss/StoplossBase.h +0 -1
  100. hikyuu/include/hikyuu/trade_sys/system/System.h +1 -2
  101. hikyuu/include/hikyuu/utilities/Log.h +6 -7
  102. hikyuu/include/hikyuu/utilities/Parameter.h +17 -0
  103. hikyuu/include/hikyuu/utilities/config.h +28 -0
  104. hikyuu/include/hikyuu/utilities/plugin/PluginBase.h +17 -2
  105. hikyuu/include/hikyuu/utilities/plugin/PluginManager.h +41 -22
  106. hikyuu/include/hikyuu/utilities/thread/GlobalStealThreadPool.h +1 -2
  107. hikyuu/include/hikyuu/utilities/thread/GlobalThreadPool.h +1 -1
  108. hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +286 -0
  109. hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +1 -0
  110. hikyuu/include/hikyuu/utilities/thread/StealThreadPool.h +297 -0
  111. hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +1 -0
  112. hikyuu/include/hikyuu/utilities/thread/WorkStealQueue.h +9 -8
  113. hikyuu/include/hikyuu/utilities/thread/algorithm.h +64 -14
  114. hikyuu/include/hikyuu/version.h +4 -4
  115. hikyuu/plugin/libbacktest.so +0 -0
  116. hikyuu/plugin/libcheckdata.so +0 -0
  117. hikyuu/plugin/libclickhousedriver.so +0 -0
  118. hikyuu/plugin/libdataserver.so +0 -0
  119. hikyuu/plugin/libdataserver_parquet.so +0 -0
  120. hikyuu/plugin/libdevice.so +0 -0
  121. hikyuu/plugin/libextind.so +0 -0
  122. hikyuu/plugin/libhkuextra.so +0 -0
  123. hikyuu/plugin/libimport2ch.so +0 -0
  124. hikyuu/plugin/libimport2hdf5.so +0 -0
  125. hikyuu/plugin/libimport2mysql.so +0 -0
  126. hikyuu/plugin/libtmreport.so +0 -0
  127. hikyuu/trade_manage/__init__.pyi +12 -7
  128. hikyuu/trade_manage/trade.pyi +12 -7
  129. hikyuu/trade_sys/trade_sys.py +54 -5
  130. hikyuu/util/__init__.pyi +1 -1
  131. hikyuu/util/singleton.pyi +1 -1
  132. {hikyuu-2.7.0.dist-info → hikyuu-2.7.3.dist-info}/METADATA +10 -4
  133. {hikyuu-2.7.0.dist-info → hikyuu-2.7.3.dist-info}/RECORD +136 -114
  134. hikyuu/cpp/libboost_chrono-mt.so +0 -0
  135. hikyuu/cpp/libboost_chrono-mt.so.1.88.0 +0 -0
  136. hikyuu/cpp/libboost_date_time-mt.so +0 -0
  137. hikyuu/cpp/libboost_date_time-mt.so.1.88.0 +0 -0
  138. hikyuu/cpp/libboost_serialization-mt.so +0 -0
  139. hikyuu/cpp/libboost_serialization-mt.so.1.88.0 +0 -0
  140. hikyuu/cpp/libboost_system-mt.so +0 -0
  141. hikyuu/cpp/libboost_system-mt.so.1.88.0 +0 -0
  142. hikyuu/cpp/libboost_thread-mt.so +0 -0
  143. hikyuu/cpp/libboost_thread-mt.so.1.88.0 +0 -0
  144. hikyuu/cpp/libboost_wserialization-mt.so +0 -0
  145. hikyuu/cpp/libboost_wserialization-mt.so.1.88.0 +0 -0
  146. hikyuu/data/pytdx_to_taos.py +0 -736
  147. {hikyuu-2.7.0.dist-info → hikyuu-2.7.3.dist-info}/WHEEL +0 -0
  148. {hikyuu-2.7.0.dist-info → hikyuu-2.7.3.dist-info}/entry_points.txt +0 -0
  149. {hikyuu-2.7.0.dist-info → hikyuu-2.7.3.dist-info}/top_level.txt +0 -0
@@ -1,736 +0,0 @@
1
- #!/usr/bin/python
2
- # -*- coding: utf8 -*-
3
- #
4
- # Create on: 2025-06-13
5
- # Author: fasiondog
6
-
7
- import sys
8
- import math
9
- import datetime
10
- from pytdx.hq import TDXParams
11
-
12
- from hikyuu.util.mylog import hku_error, hku_debug
13
-
14
- from hikyuu import Datetime, UTCOffset, Days
15
- from hikyuu.data.common import *
16
- from hikyuu.data.common_pytdx import to_pytdx_market, pytdx_get_day_trans
17
- from hikyuu.data.common_taos import (
18
- create_database,
19
- get_marketid,
20
- get_codepre_list,
21
- get_stock_list,
22
- get_table,
23
- get_lastdatetime,
24
- get_last_krecord,
25
- update_extern_data,
26
- )
27
-
28
-
29
- def ProgressBar(cur, total):
30
- percent = "{:.0%}".format(cur / total)
31
- sys.stdout.write("\r")
32
- sys.stdout.write("[%-50s] %s" % ("=" * int(math.floor(cur * 50 / total)), percent))
33
- sys.stdout.flush()
34
-
35
-
36
- @hku_catch(ret=0, trace=True)
37
- def import_index_name(connect):
38
- """
39
- 导入所有指数代码表
40
-
41
- :param connect: taos 连接对象
42
- :return: 指数个数
43
- """
44
- index_list = get_index_code_name_list()
45
- if not index_list:
46
- return 0
47
-
48
- cur = connect.cursor()
49
- cur.execute(
50
- "select cast(stockid as bigint), market, code from hku_base.n_stock where type={}".format(
51
- STOCKTYPE.INDEX
52
- )
53
- )
54
- a = [v for v in cur]
55
- oldStockDict = {}
56
- for oldstock in a:
57
- oldstockid = oldstock[0]
58
- oldcode = f"{oldstock[1]}{oldstock[2]}"
59
- oldStockDict[oldcode] = oldstockid
60
-
61
- today = datetime.date.today()
62
- today = today.year * 10000 + today.month * 100 + today.day
63
- now_id = int(datetime.datetime.now().timestamp() * 1000)
64
- count = 0
65
- for index in index_list:
66
- market_code = index["market_code"].upper()
67
- stockid = oldStockDict[market_code] if market_code in oldStockDict else now_id + count
68
- # print(stockid)
69
-
70
- market = market_code[:2].upper()
71
- sql = (
72
- "insert into hku_base.n_stock (stockid, market, code, name, type, valid, startDate, endDate) \
73
- values (%s, '%s', '%s', '%s', %s, %s, %s, %s)"
74
- % (
75
- stockid,
76
- market,
77
- index["market_code"][2:],
78
- index["name"], # .encode('utf8').decode('utf8', 'ignore'),
79
- STOCKTYPE.INDEX,
80
- 1,
81
- today,
82
- 99999999,
83
- )
84
- )
85
- count += 1
86
- cur.execute(sql)
87
- cur.close()
88
- return len(index_list)
89
-
90
-
91
- @hku_catch(ret=0, trace=True)
92
- def import_stock_name(connect, api, market, quotations=None):
93
- """更新每只股票的名称、当前是否有效性、起始日期及结束日期
94
- 如果导入的代码表中不存在对应的代码,则认为该股已失效
95
-
96
- :param connect: sqlite3实例
97
- :param api: pytdx接口,必须在函数外进行连接
98
- :param market: 'SH' | 'SZ'
99
- :param quotations: 待导入的行情类别,空为导入全部 'stock' | 'fund' | 'bond' | None
100
- """
101
- cur = connect.cursor()
102
-
103
- deSet = set() # 记录退市证券
104
- if market == MARKET.SH:
105
- df = ak.stock_info_sh_delist()
106
- l = df[['公司代码', '公司简称']].to_dict(orient='records') if not df .empty else []
107
- for stock in l:
108
- code = str(stock['公司代码'])
109
- deSet.add(code)
110
- elif market == MARKET.SZ:
111
- for t in ['暂停上市公司', '终止上市公司']:
112
- df = ak.stock_info_sz_delist(t)
113
- l = df[['证券代码', '证券简称']].to_dict(orient='records') if not df.empty else []
114
- for stock in l:
115
- code = str(stock['证券代码'])
116
- deSet.add(code)
117
-
118
- newStockDict = {}
119
- stk_list = get_stk_code_name_list(market)
120
- if not stk_list:
121
- hku_error("获取 {} 股票代码表失败", market)
122
- return 0
123
-
124
- if not quotations or "fund" in [v.lower() for v in quotations]:
125
- stk_list.extend(get_fund_code_name_list(market))
126
- for stock in stk_list:
127
- code = str(stock["code"])
128
- if code not in deSet:
129
- newStockDict[code] = stock["name"]
130
-
131
- marketid = get_marketid(connect, market)
132
-
133
- stktype_list = get_stktype_list(quotations)
134
- stktype_list = list(stktype_list)
135
- stktype_list.remove(STOCKTYPE.INDEX) # 移除指数类型
136
- stktype_list = tuple(stktype_list)
137
- cur.execute(
138
- "select cast(stockid as bigint), market, code, name, type, valid, startDate, endDate from hku_base.n_stock where market='{}' and type in {}".format(
139
- market.upper(), stktype_list
140
- )
141
- )
142
- a = [v for v in cur]
143
- oldStockDict = {}
144
- for oldstock in a:
145
- oldstockid, oldmarket, oldcode, oldname, oldtype, oldvalid, oldstartDate, oldendDate = oldstock
146
- oldStockDict[oldcode] = oldstockid
147
-
148
- # 新的代码表中无此股票,则置为无效
149
- if (oldvalid == 1) and ((oldcode not in newStockDict) or oldcode in deSet):
150
- cur.execute(
151
- f"insert into hku_base.n_stock (stockid, market, code, name, type, valid, startDate, endDate) values ({oldstockid}, '{oldmarket}', '{oldcode}', '{oldname}', {oldtype}, 0, {oldstartDate}, {oldendDate})"
152
- )
153
-
154
- # 股票名称发生变化,更新股票名称;如果原无效,则置为有效
155
- if oldcode in newStockDict:
156
- if oldname != newStockDict[oldcode]:
157
- cur.execute(
158
- f"insert into hku_base.n_stock (stockid, market, code, name, type, valid, startDate, endDate) values ({oldstockid}, '{oldmarket}', '{oldcode}', '{newStockDict[oldcode]}', {oldtype}, {oldvalid}, {oldstartDate}, {oldendDate})")
159
- if oldvalid == 0:
160
- cur.execute(
161
- f"insert into hku_base.n_stock (stockid, market, code, name, type, valid, startDate, endDate) values ({oldstockid}, '{oldmarket}', '{oldcode}', '{oldname}', {oldtype}, 1, {oldstartDate}, 99999999)")
162
-
163
- # 处理新出现的股票
164
- codepre_list = get_codepre_list(connect, marketid, quotations)
165
-
166
- today = datetime.date.today()
167
- today = today.year * 10000 + today.month * 100 + today.day
168
- now_id = int(datetime.datetime.now().timestamp() * 1000)
169
- count = 0
170
- for code in newStockDict:
171
- if code not in oldStockDict:
172
- for codepre in codepre_list:
173
- length = len(codepre[0])
174
- if code[:length] == codepre[0]:
175
- # print(market, code, newStockDict[code], codepre)
176
- sql = (
177
- "insert into `hku_base`.`n_stock` (stockid, market, code, name, type, valid, startDate, endDate) \
178
- values (%s, '%s', '%s', '%s', %s, %s, %s, %s)"
179
- % (
180
- now_id + count,
181
- market,
182
- code,
183
- newStockDict[code],
184
- codepre[1],
185
- 1,
186
- today,
187
- 99999999,
188
- )
189
- )
190
- cur.execute(sql)
191
- count += 1
192
- break
193
-
194
- # print('%s新增股票数:%i' % (market.upper(), count))
195
- cur.close()
196
- return count
197
-
198
-
199
- def guess_day_n_step(last_datetime):
200
- last_date = int(last_datetime // 10000)
201
- today = datetime.date.today()
202
-
203
- last_y = last_date // 10000
204
- n = int((today.year - last_y + 1) * 250 // 800)
205
-
206
- step = 800
207
- if n < 1:
208
- last_m = last_date // 100 - last_y * 100
209
- last_d = last_date - (last_y * 10000 + last_m * 100)
210
- step = (today - datetime.date(last_y, last_m, last_d)).days + 1
211
- if step > 800:
212
- n = 1
213
- step = 800
214
-
215
- return (n, step)
216
-
217
-
218
- def guess_1min_n_step(last_datetime):
219
- last_date = int(last_datetime // 10000)
220
- today = datetime.date.today()
221
-
222
- last_y = last_date // 10000
223
- last_m = last_date // 100 - last_y * 100
224
- last_d = last_date - (last_y * 10000 + last_m * 100)
225
-
226
- n = int(((today - datetime.date(last_y, last_m, last_d)).days * 240 + 1) // 800)
227
- step = 800
228
- if n < 1:
229
- step = (today - datetime.date(last_y, last_m, last_d)).days * 240 + 1
230
- elif n > 99:
231
- n = 99
232
-
233
- return (n, step)
234
-
235
-
236
- def guess_5min_n_step(last_datetime):
237
- last_date = int(last_datetime // 10000)
238
- today = datetime.date.today()
239
-
240
- last_y = last_date // 10000
241
- last_m = last_date // 100 - last_y * 100
242
- last_d = last_date - (last_y * 10000 + last_m * 100)
243
-
244
- n = int(((today - datetime.date(last_y, last_m, last_d)).days * 48 + 1) // 800)
245
- step = 800
246
- if n < 1:
247
- step = (today - datetime.date(last_y, last_m, last_d)).days * 48 + 1
248
- elif n > 99:
249
- n = 99
250
-
251
- return (n, step)
252
-
253
-
254
- def import_one_stock_data(
255
- connect, api, market, ktype, stock_record, startDate=199012191500
256
- ):
257
- market = market.upper()
258
- pytdx_market = to_pytdx_market(market)
259
-
260
- # stockid, market, code, name, type, valid, startDate, endDate
261
- stockid, market, code, name, stktype, valid, stk_startDate, stk_endDate = stock_record
262
- hku_debug("{}{}".format(market, code))
263
- table = get_table(connect, market, code, ktype)
264
-
265
- last_krecord = get_last_krecord(connect, table)
266
- last_datetime = startDate if last_krecord is None else last_krecord[0].ymdhm
267
-
268
- today = datetime.date.today()
269
- if ktype == "DAY":
270
- nktype = "day"
271
- n, step = guess_day_n_step(last_datetime)
272
- pytdx_kline_type = TDXParams.KLINE_TYPE_RI_K
273
- today_datetime = (today.year * 10000 + today.month * 100 + today.day) * 10000
274
-
275
- elif ktype == "1MIN":
276
- nktype = "min"
277
- n, step = guess_1min_n_step(last_datetime)
278
- pytdx_kline_type = TDXParams.KLINE_TYPE_1MIN
279
- today_datetime = (
280
- today.year * 10000 + today.month * 100 + today.day
281
- ) * 10000 + 1500
282
-
283
- elif ktype == "5MIN":
284
- nktype = "min5"
285
- n, step = guess_5min_n_step(last_datetime)
286
- pytdx_kline_type = TDXParams.KLINE_TYPE_5MIN
287
- today_datetime = (
288
- today.year * 10000 + today.month * 100 + today.day
289
- ) * 10000 + 1500
290
- else:
291
- return 0
292
-
293
- if today_datetime <= last_datetime:
294
- return 0
295
-
296
- get_bars = (
297
- api.get_index_bars if stktype == STOCKTYPE.INDEX else api.get_security_bars
298
- )
299
-
300
- if last_krecord is not None:
301
- if ktype == 'DAY':
302
- days = (Datetime.today() - last_krecord[0]).days
303
- num = days + 1
304
- elif ktype == '1MIN':
305
- days = (Datetime.today() - last_krecord[0].start_of_day()).days
306
- num = days*240+1
307
- elif ktype == '5MIN':
308
- days = (Datetime.today() - last_krecord[0].start_of_day()).days
309
- num = days*48+1
310
- if num >= 1:
311
- bars = get_bars(pytdx_kline_type, pytdx_market, code, 0, num)
312
- if not bars:
313
- return 0
314
- bar = bars[-1]
315
- if ktype == 'DAY':
316
- bardate = Datetime(bar["year"], bar["month"], bar["day"])
317
- else:
318
- bardate = Datetime(bar["year"], bar["month"], bar["day"], bar['hour'], bar['minute'])
319
- if last_krecord[0] == bardate:
320
- if abs(last_krecord[1] - bar["open"]) / last_krecord[1] > 0.02:
321
- hku_error(
322
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[1]}, bar: {bar['open']}")
323
- return 0
324
- if abs(last_krecord[2] - bar["high"]) / last_krecord[2] > 0.02:
325
- hku_error(
326
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[2]}, bar: {bar['high']}")
327
- return 0
328
- if abs(last_krecord[3] - bar["low"]) / last_krecord[3] > 0.02:
329
- hku_error(
330
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[3]}, bar: {bar['low']}")
331
- return 0
332
- if abs(last_krecord[4] - bar["close"]) / last_krecord[4] > 0.02:
333
- hku_error(
334
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[4]}, bar: {bar['close']}")
335
- return 0
336
- if ktype == 'DAY' and last_krecord[5] != 0.0 and abs(last_krecord[5] - bar["amount"]*0.001) / last_krecord[5] > 0.1:
337
- hku_error(
338
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[5]}, bar: {bar['amount']*0.001}")
339
- return 0
340
- if ktype == 'DAY' and last_krecord[5] != 0.0 and abs(last_krecord[6] - bar["vol"]) / last_krecord[6] > 0.1:
341
- hku_error(
342
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[6]}, bar: {bar['vol']}")
343
- return 0
344
-
345
- buf = []
346
- while n >= 0:
347
- bar_list = get_bars(pytdx_kline_type, pytdx_market, code, n * 800, step)
348
- n -= 1
349
- if bar_list is None:
350
- # print(code, "invalid!!")
351
- continue
352
-
353
- for bar in bar_list:
354
- try:
355
- if ktype == "DAY":
356
- tmp = datetime.date(bar["year"], bar["month"], bar["day"])
357
- bar_datetime = (tmp.year * 10000 + tmp.month * 100 + tmp.day) * 10000
358
- else:
359
- tmp = datetime.datetime(bar["year"], bar["month"], bar["day"], bar['hour'], bar['minute'])
360
- bar_datetime = (tmp.year * 10000 + tmp.month * 100 + tmp.day) * \
361
- 10000 + bar["hour"] * 100 + bar["minute"]
362
- except Exception as e:
363
- hku_error("Failed translate datetime: {}, from {}! {}".format(bar, api.ip, e))
364
- continue
365
-
366
- if last_krecord is not None and bar_datetime == last_datetime:
367
- if abs(last_krecord[1] - bar["open"]) / last_krecord[1] > 0.02:
368
- hku_error(
369
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[1]}, bar: {bar['open']}")
370
- return 0
371
- if abs(last_krecord[2] - bar["high"]) / last_krecord[2] > 0.02:
372
- hku_error(
373
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[2]}, bar: {bar['high']}")
374
- return 0
375
- if abs(last_krecord[3] - bar["low"]) / last_krecord[3] > 0.02:
376
- hku_error(
377
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[3]}, bar: {bar['low']}")
378
- return 0
379
- if abs(last_krecord[4] - bar["close"]) / last_krecord[4] > 0.02:
380
- hku_error(
381
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[4]}, bar: {bar['close']}")
382
- return 0
383
- if ktype == 'DAY' and last_krecord[5] != 0.0 and abs(last_krecord[5] - bar["amount"]*0.001) / last_krecord[5] > 0.1:
384
- hku_error(
385
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[5]}, bar: {bar['amount']*0.001}")
386
- return 0
387
- if ktype == 'DAY' and last_krecord[5] != 0.0 and abs(last_krecord[6] - bar["vol"]) / last_krecord[6] > 0.1:
388
- hku_error(
389
- f"fetch data from tdx error! {bardate} {ktype} {market}{code} last_krecord: {last_krecord[6]}, bar: {bar['vol']}")
390
- return 0
391
- continue
392
-
393
- if (
394
- today_datetime >= bar_datetime > last_datetime
395
- and bar["high"] >= bar["open"] >= bar["low"] > 0
396
- and bar["high"] >= bar["close"] >= bar["low"] > 0
397
- and bar["vol"] >= 0
398
- and bar["amount"] >= 0
399
- ):
400
- try:
401
- buf.append(
402
- (
403
- bar_datetime,
404
- bar["open"],
405
- bar["high"],
406
- bar["low"],
407
- bar["close"],
408
- bar["amount"] * 0.001,
409
- bar["vol"]
410
- # bar['vol'] if stktype == 2 else round(bar['vol'] * 0.01)
411
- )
412
- )
413
- except Exception as e:
414
- hku_error("Can't trans record({}), {}".format(bar, e))
415
- last_datetime = bar_datetime
416
-
417
- if len(buf) > 0:
418
- cur = connect.cursor()
419
- rawsql = f"INSERT INTO {table} using {nktype}_data.kdata TAGS ('{market.upper()}', '{code}') VALUES "
420
- sql = rawsql
421
- for i, r in enumerate(buf):
422
- sql += f"({(Datetime(r[0])-UTCOffset()).timestamp()}, {r[1]}, {r[2]}, {r[3]}, {r[4]}, {r[5]}, {r[6]})"
423
- if i > 0 and i % 8000 == 0:
424
- cur.execute(sql)
425
- sql = rawsql
426
- if sql != rawsql:
427
- cur.execute(sql)
428
-
429
- if ktype == "DAY":
430
- # 更新基础信息数据库中股票对应的起止日期及其有效标志
431
- # stockid, market, code, name, type, valid, startDate, endDate
432
- cur.execute(f"select FIRST(date) from {table}")
433
- a = [v for v in cur]
434
- first_date = Datetime(a[0][0]).ymd
435
- sql = f"INSERT INTO hku_base.n_stock (stockid, market, code, name, type, valid, startDate, endDate) VALUES ({stockid}, '{market.upper()}', '{code}', '{name}', {stktype}, 1, {first_date}, {stk_endDate})"
436
- # print(sql)
437
- cur.execute(sql)
438
-
439
- # 记录最新更新日期
440
- if (
441
- (code == "000001" and market == MARKET.SH)
442
- or (code == "399001" and market == MARKET.SZ)
443
- or (code == "830799" and market == MARKET.BJ)
444
- ):
445
- cur.execute(f"select cast(id as bigint) from hku_base.n_market where market='{market.upper()}'")
446
- a = [v for v in cur]
447
- id = a[0][0]
448
- sql = f"INSERT INTO hku_base.n_market (id, lastdate) VALUES ({id}, {buf[-1][0]//10000})"
449
- # print(sql)
450
- cur.execute(sql)
451
- cur.close()
452
-
453
- return len(buf)
454
-
455
-
456
- @hku_catch(trace=True, re_raise=True)
457
- def import_data(
458
- connect,
459
- market,
460
- ktype,
461
- quotations,
462
- api,
463
- dest_dir=None,
464
- startDate=199012190000,
465
- progress=ProgressBar,
466
- ):
467
- """导入通达信指定盘后数据路径中的K线数据。注:只导入基础信息数据库中存在的股票。
468
-
469
- :param connect : sqlit3链接
470
- :param market : 'SH' | 'SZ'
471
- :param ktype : 'DAY' | '1MIN' | '5MIN'
472
- :param quotations: 'stock' | 'fund' | 'bond'
473
- :param src_dir : 盘后K线数据路径,如上证5分钟线:D:\\Tdx\\vipdoc\\sh\\fzline
474
- :param dest_dir : HDF5数据文件所在目录
475
- :param progress : 进度显示函数
476
- :return: 导入记录数
477
- """
478
- add_record_count = 0
479
- market = market.upper()
480
-
481
- # stockid, marketid, code, name, type, valid, startDate, endDate
482
- stock_list = get_stock_list(connect, market, quotations)
483
-
484
- total = len(stock_list)
485
- for i, stock in enumerate(stock_list):
486
- if stock[5] == 0 or len(stock[2]) != 6:
487
- if progress:
488
- progress(i, total)
489
- continue
490
-
491
- this_count = import_one_stock_data(
492
- connect, api, market, ktype, stock, startDate
493
- )
494
- add_record_count += this_count
495
- if this_count > 0:
496
- if ktype == "DAY":
497
- update_extern_data(connect, market.upper(), stock[2], "DAY")
498
- elif ktype == "5MIN":
499
- update_extern_data(connect, market.upper(), stock[2], "5MIN")
500
-
501
- if progress:
502
- progress(i, total)
503
-
504
- connect.commit()
505
- return add_record_count
506
-
507
-
508
- @hku_catch(trace=True)
509
- def import_on_stock_trans(connect, api, market, stock_record, max_days):
510
- market = market.upper()
511
- pytdx_market = to_pytdx_market(market)
512
-
513
- # stockid, marketid, code, name, type, valid, startDate, endDate
514
- stockid, marketid, code, name, stktype, valid = stock_record[:6]
515
- hku_debug("{}{}".format(market, code))
516
- table = get_table(connect, market, code, 'transdata')
517
- last_datetime = get_lastdatetime(connect, table)
518
-
519
- today = Datetime.today()
520
- if last_datetime is not None:
521
- # yyyymmddHHMMSS
522
- last_date = last_datetime.start_of_day()
523
- need_days = (today - last_date).days
524
- else:
525
- need_days = max_days
526
-
527
- date_list = []
528
- for i in range(need_days):
529
- cur_date = today - Days(i)
530
- if cur_date.day_of_week not in (0, 6):
531
- date_list.append(cur_date.ymd)
532
- date_list.reverse()
533
-
534
- trans_buf = []
535
- for cur_date in date_list:
536
- buf = pytdx_get_day_trans(api, pytdx_market, code, cur_date)
537
- if not buf:
538
- continue
539
-
540
- second = 2
541
- pre_minute = 900
542
-
543
- for record in buf:
544
- try:
545
- minute = int(record["time"][0:2]) * 100 + int(record["time"][3:])
546
- if minute != pre_minute:
547
- second = 0 if minute == 1500 else 2
548
- pre_minute = minute
549
- else:
550
- second += 3
551
- if second > 59:
552
- continue
553
-
554
- trans_buf.append(
555
- (
556
- cur_date * 1000000 + minute * 100 + second,
557
- record["price"],
558
- record["vol"],
559
- record["buyorsell"],
560
- )
561
- )
562
- except Exception as e:
563
- hku_error("Failed trans to record! {}", e)
564
-
565
- if trans_buf:
566
- cur = connect.cursor()
567
- rawsql = f"INSERT INTO {table} using transdata_data.transdata TAGS ('{market.upper()}', '{code}') VALUES "
568
- sql = rawsql
569
- for i, r in enumerate(trans_buf):
570
- sql += f"({(Datetime(r[0])-UTCOffset()).timestamp()}, {r[1]}, {r[2]}, {r[3]})"
571
- if i > 0 and i % 15000 == 0:
572
- cur.execute(sql)
573
- sql = rawsql
574
- if sql != rawsql:
575
- cur.execute(sql)
576
- cur.close()
577
- return len(trans_buf)
578
-
579
-
580
- def import_trans(
581
- connect, market, quotations, api, dest_dir=None, max_days=30, progress=ProgressBar
582
- ):
583
- add_record_count = 0
584
- market = market.upper()
585
-
586
- stock_list = get_stock_list(connect, market, quotations)
587
- total = len(stock_list)
588
- a_stktype_list = get_a_stktype_list()
589
- for i, stock in enumerate(stock_list):
590
- # stockid, marketid, code, name, type, valid, startDate, endDate
591
- if stock[5] == 0 or len(stock[2]) != 6 or stock[4] not in a_stktype_list:
592
- if progress:
593
- progress(i, total)
594
- continue
595
-
596
- this_count = import_on_stock_trans(connect, api, market, stock, max_days)
597
- add_record_count += this_count
598
- if progress:
599
- progress(i, total)
600
-
601
- return add_record_count
602
-
603
-
604
- @hku_catch(trace=True)
605
- def import_on_stock_time(connect, api, market, stock_record, max_days):
606
- market = market.upper()
607
- pytdx_market = to_pytdx_market(market)
608
-
609
- # stockid, marketid, code, name, type, valid, startDate, endDate
610
- stockid, marketid, code, name, stktype, valid = stock_record[:6]
611
- hku_debug("{}{}".format(market, code))
612
- table = get_table(connect, market, code, 'timeline')
613
- last_datetime = get_lastdatetime(connect, table)
614
-
615
- today = Datetime.today()
616
- if last_datetime is not None:
617
- # yyyymmddHHMM
618
- last_date = last_datetime.start_of_day()
619
- need_days = (today - last_date).days
620
- else:
621
- need_days = max_days
622
-
623
- date_list = []
624
- for i in range(need_days):
625
- cur_date = today - Days(i)
626
- if cur_date.day_of_week() not in (0, 6):
627
- date_list.append(cur_date.ymd)
628
- date_list.reverse()
629
-
630
- time_buf = []
631
- for cur_date in date_list:
632
- buf = api.get_history_minute_time_data(pytdx_market, code, cur_date)
633
- if buf is None or len(buf) != 240:
634
- # print(cur_date, "获取的分时线长度不为240!", stock_record[1], stock_record[2])
635
- continue
636
- this_date = cur_date * 10000
637
- time = 930
638
- for record in buf:
639
- if time == 960:
640
- time = 1000
641
- elif time == 1060:
642
- time = 1100
643
- elif time == 1130:
644
- time = 1300
645
- elif time == 1360:
646
- time = 1400
647
- try:
648
- time_buf.append((this_date + time, record['price'], record['vol']))
649
- time += 1
650
- except Exception as e:
651
- hku_error("Failed trans record {}! {}".format(record, e))
652
-
653
- if time_buf:
654
- cur = connect.cursor()
655
- rawsql = f"INSERT INTO {table} using timeline_data.timeline TAGS ('{market.upper()}', '{code}') VALUES "
656
- sql = rawsql
657
- for i, r in enumerate(time_buf):
658
- sql += f"({(Datetime(r[0])-UTCOffset()).timestamp()}, {r[1]}, {r[2]})"
659
- if i > 0 and i % 16000 == 0:
660
- cur.execute(sql)
661
- sql = rawsql
662
- if sql != rawsql:
663
- cur.execute(sql)
664
- cur.close()
665
-
666
- return len(time_buf)
667
-
668
-
669
- def import_time(connect, market, quotations, api, dest_dir=None, max_days=9000, progress=ProgressBar):
670
- add_record_count = 0
671
- market = market.upper()
672
-
673
- stock_list = get_stock_list(connect, market, quotations)
674
- total = len(stock_list)
675
- for i, stock in enumerate(stock_list):
676
- # stockid, marketid, code, name, type, valid, startDate, endDate
677
- if stock[5] == 0 or len(stock[2]) != 6:
678
- if progress:
679
- progress(i, total)
680
- continue
681
-
682
- this_count = import_on_stock_time(connect, api, market, stock, max_days)
683
- add_record_count += this_count
684
- if progress:
685
- progress(i, total)
686
-
687
- return add_record_count
688
-
689
-
690
- if __name__ == '__main__':
691
- import os
692
- from configparser import ConfigParser
693
- dev_config = ConfigParser()
694
- dev_config.read(os.path.expanduser("~") + '/workspace/dev.ini')
695
- db = 'taos54'
696
- user = dev_config.get(db, 'user')
697
- password = dev_config.get(db, 'pwd')
698
- host = dev_config.get(db, 'host')
699
- port = dev_config.getint(db, 'port')
700
-
701
- tdx_server = '180.101.48.170'
702
- tdx_port = 7709
703
-
704
- from pytdx.hq import TdxHq_API, TDXParams
705
-
706
- api = TdxHq_API()
707
- api.connect(tdx_server, tdx_port)
708
-
709
- from hikyuu.data.common_taos import get_taos
710
- connect = get_taos().connect(
711
- user=user, password=password, host=host, port=port)
712
-
713
- # import_index_name(connect)
714
-
715
- # import_stock_name(connect, None, MARKET.SH, None)
716
-
717
- quotations = ["stock", "fund"]
718
-
719
- stock_list = get_stock_list(connect, "SH", quotations)
720
- stock_record = None
721
- for r in stock_list:
722
- if r[2] == "000001":
723
- stock_record = r
724
- break
725
- print(stock_record)
726
-
727
- import_one_stock_data(connect, api, "SH", "5MIN", stock_record, startDate=199012191500)
728
-
729
- # print("\n导入上证日线数据")
730
- # add_count = import_data(connect, "SH", "DAY", quotations, api, progress=ProgressBar)
731
- # print("\n导入数量:", add_count)
732
-
733
- # import_time(connect, "SH", quotations, api, max_days=30)
734
-
735
- api.disconnect()
736
- connect.close()