hikyuu 2.6.8.5__py3-none-win_amd64.whl → 2.6.9__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. hikyuu/__init__.py +5 -11
  2. hikyuu/__init__.pyi +37 -12
  3. hikyuu/analysis/__init__.pyi +26 -0
  4. hikyuu/analysis/analysis.pyi +27 -1
  5. hikyuu/core.py +2 -0
  6. hikyuu/core.pyi +28 -2
  7. hikyuu/cpp/arrow.dll +0 -0
  8. hikyuu/cpp/boost_date_time-mt.dll +0 -0
  9. hikyuu/cpp/boost_serialization-mt.dll +0 -0
  10. hikyuu/cpp/boost_system-mt.dll +0 -0
  11. hikyuu/cpp/boost_wserialization-mt.dll +0 -0
  12. hikyuu/cpp/core310.pyd +0 -0
  13. hikyuu/cpp/core310.pyi +446 -9
  14. hikyuu/cpp/core311.pyd +0 -0
  15. hikyuu/cpp/core311.pyi +446 -9
  16. hikyuu/cpp/core312.pyd +0 -0
  17. hikyuu/cpp/core312.pyi +446 -9
  18. hikyuu/cpp/core313.pyd +0 -0
  19. hikyuu/cpp/core313.pyi +446 -9
  20. hikyuu/cpp/core39.pyd +0 -0
  21. hikyuu/cpp/core39.pyi +446 -9
  22. hikyuu/cpp/hikyuu.dll +0 -0
  23. hikyuu/cpp/hikyuu.lib +0 -0
  24. hikyuu/cpp/i18n/zh_CN/hikyuu.mo +0 -0
  25. hikyuu/cpp/msvcp140-a118642f3ae8774fb9dc223e15c4a52e.dll +0 -0
  26. hikyuu/cpp/parquet.dll +0 -0
  27. hikyuu/cpp/sqlite3.dll +0 -0
  28. hikyuu/data/clickhouse_upgrade/createdb.sql +105 -105
  29. hikyuu/data/common.py +3 -3
  30. hikyuu/data/common_clickhouse.py +1 -1
  31. hikyuu/data/download_block.py +318 -0
  32. hikyuu/data/em_block_to_clickhouse.py +26 -74
  33. hikyuu/data/em_block_to_mysql.py +25 -75
  34. hikyuu/data/em_block_to_sqlite.py +26 -78
  35. hikyuu/data/hku_config_template.py +3 -3
  36. hikyuu/data/pytdx_to_clickhouse.py +15 -11
  37. hikyuu/data/pytdx_to_h5.py +6 -2
  38. hikyuu/data/pytdx_to_mysql.py +5 -1
  39. hikyuu/data/pytdx_weight_to_clickhouse.py +1 -1
  40. hikyuu/data/pytdx_weight_to_mysql.py +1 -1
  41. hikyuu/data/pytdx_weight_to_sqlite.py +1 -1
  42. hikyuu/data/zh_bond10_to_clickhouse.py +1 -1
  43. hikyuu/draw/drawplot/bokeh_draw.pyi +33 -8
  44. hikyuu/draw/drawplot/echarts_draw.pyi +33 -8
  45. hikyuu/draw/drawplot/matplotlib_draw.py +4 -74
  46. hikyuu/draw/drawplot/matplotlib_draw.pyi +33 -8
  47. hikyuu/examples/notebook/Demo/Demo1.ipynb +48 -33
  48. hikyuu/extend.py +0 -1
  49. hikyuu/extend.pyi +30 -5
  50. hikyuu/fetcher/stock/zh_block_em.py +50 -18
  51. hikyuu/gui/HikyuuTDX.py +81 -30
  52. hikyuu/gui/data/CollectSpotThread.py +1 -1
  53. hikyuu/gui/data/EscapetimeThread.py +8 -14
  54. hikyuu/gui/data/ImportBlockInfoTask.py +3 -10
  55. hikyuu/gui/data/MainWindow.py +1168 -715
  56. hikyuu/gui/data/SchedImportThread.py +2 -2
  57. hikyuu/gui/data/UsePytdxImportToH5Thread.py +3 -3
  58. hikyuu/gui/data/UseQmtImportToH5Thread.py +2 -2
  59. hikyuu/gui/data/UseTdxImportToH5Thread.py +3 -3
  60. hikyuu/gui/data/tool.py +32 -25
  61. hikyuu/gui/dataserver.py +5 -3
  62. hikyuu/hub.pyi +6 -6
  63. hikyuu/include/hikyuu/DataType.h +4 -16
  64. hikyuu/include/hikyuu/KData.h +6 -3
  65. hikyuu/include/hikyuu/KDataPrivatedBufferImp.h +1 -1
  66. hikyuu/include/hikyuu/KDataSharedBufferImp.h +1 -1
  67. hikyuu/include/hikyuu/KQuery.h +2 -2
  68. hikyuu/include/hikyuu/Stock.h +3 -0
  69. hikyuu/include/hikyuu/StockManager.h +13 -3
  70. hikyuu/include/hikyuu/data_driver/BaseInfoDriver.h +8 -0
  71. hikyuu/include/hikyuu/data_driver/BlockInfoDriver.h +6 -0
  72. hikyuu/include/hikyuu/data_driver/KDataDriver.h +26 -1
  73. hikyuu/include/hikyuu/data_driver/base_info/mysql/MySQLBaseInfoDriver.h +1 -1
  74. hikyuu/include/hikyuu/data_driver/base_info/sqlite/SQLiteBaseInfoDriver.h +1 -1
  75. hikyuu/include/hikyuu/data_driver/block_info/mysql/MySQLBlockInfoDriver.h +2 -1
  76. hikyuu/include/hikyuu/data_driver/block_info/qianlong/QLBlockInfoDriver.h +2 -1
  77. hikyuu/include/hikyuu/data_driver/block_info/sqlite/SQLiteBlockInfoDriver.h +2 -1
  78. hikyuu/include/hikyuu/data_driver/kdata/DoNothingKDataDriver.h +1 -1
  79. hikyuu/include/hikyuu/data_driver/kdata/cvs/KDataTempCsvDriver.h +1 -1
  80. hikyuu/include/hikyuu/data_driver/kdata/hdf5/H5KDataDriver.h +1 -1
  81. hikyuu/include/hikyuu/data_driver/kdata/mysql/MySQLKDataDriver.h +1 -1
  82. hikyuu/include/hikyuu/data_driver/kdata/sqlite/SQLiteKDataDriver.h +1 -1
  83. hikyuu/include/hikyuu/data_driver/kdata/tdx/TdxKDataDriver.h +1 -1
  84. hikyuu/include/hikyuu/hikyuu.h +1 -1
  85. hikyuu/include/hikyuu/indicator/build_in.h +1 -0
  86. hikyuu/include/hikyuu/indicator/crt/CYCLE.h +4 -4
  87. hikyuu/include/hikyuu/indicator/crt/HSL.h +2 -2
  88. hikyuu/include/hikyuu/indicator/crt/QUANTILE_TRUNC.h +30 -0
  89. hikyuu/include/hikyuu/indicator/crt/TURNOVER.h +1 -0
  90. hikyuu/include/hikyuu/indicator/crt/ZSCORE.h +2 -2
  91. hikyuu/include/hikyuu/indicator/imp/IQuantileTrunc.h +25 -0
  92. hikyuu/include/hikyuu/misc.h +38 -0
  93. hikyuu/include/hikyuu/plugin/dataserver.h +2 -1
  94. hikyuu/include/hikyuu/plugin/extind.h +37 -0
  95. hikyuu/include/hikyuu/plugin/interface/DataServerPluginInterface.h +2 -2
  96. hikyuu/include/hikyuu/plugin/interface/ExtendIndicatorsPluginInterface.h +12 -0
  97. hikyuu/include/hikyuu/strategy/RunSystemInStrategy.h +3 -0
  98. hikyuu/include/hikyuu/trade_manage/Performance.h +4 -4
  99. hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +10 -1
  100. hikyuu/include/hikyuu/trade_sys/moneymanager/imp/FixedCapitalFundsMM.h +0 -4
  101. hikyuu/include/hikyuu/trade_sys/multifactor/MultiFactorBase.h +36 -3
  102. hikyuu/include/hikyuu/trade_sys/multifactor/NormalizeBase.h +125 -0
  103. hikyuu/include/hikyuu/trade_sys/multifactor/ScoresFilterBase.h +125 -0
  104. hikyuu/include/hikyuu/trade_sys/multifactor/build_in.h +3 -0
  105. hikyuu/include/hikyuu/trade_sys/multifactor/buildin_norm.h +36 -0
  106. hikyuu/include/hikyuu/trade_sys/multifactor/buildin_scfilter.h +51 -0
  107. hikyuu/include/hikyuu/trade_sys/multifactor/filter/GroupSCFilter.h +24 -0
  108. hikyuu/include/hikyuu/trade_sys/multifactor/filter/IgnoreLessOrEqualValueSCFilter.h +24 -0
  109. hikyuu/include/hikyuu/trade_sys/multifactor/filter/IgnoreNanSCFilter.h +24 -0
  110. hikyuu/include/hikyuu/trade_sys/multifactor/filter/MinAmountPercentSCFilter.h +25 -0
  111. hikyuu/include/hikyuu/trade_sys/multifactor/filter/PriceSCFilter.h +24 -0
  112. hikyuu/include/hikyuu/trade_sys/multifactor/filter/TopNSCFilter.h +24 -0
  113. hikyuu/include/hikyuu/trade_sys/multifactor/filter/__init__.py +1 -0
  114. hikyuu/include/hikyuu/trade_sys/multifactor/imp/EqualWeightMultiFactor.h +1 -1
  115. hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICIRMultiFactor.h +1 -1
  116. hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICMultiFactor.h +1 -1
  117. hikyuu/include/hikyuu/trade_sys/multifactor/imp/WeightMultiFactor.h +1 -1
  118. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormMinMax.h +23 -0
  119. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormQuantile.h +28 -0
  120. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormQuantileUniform.h +28 -0
  121. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormZScore.h +25 -0
  122. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/__init__.py +1 -0
  123. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/quantile_trunc.h +16 -0
  124. hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +7 -0
  125. hikyuu/include/hikyuu/trade_sys/portfolio/imp/SimplePortfolio.h +7 -0
  126. hikyuu/include/hikyuu/trade_sys/portfolio/imp/WithoutAFPortfolio.h +7 -0
  127. hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +49 -0
  128. hikyuu/include/hikyuu/trade_sys/selector/build_in.h +1 -0
  129. hikyuu/include/hikyuu/trade_sys/selector/crt/SE_MultiFactor2.h +40 -0
  130. hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector.h +0 -3
  131. hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector2.h +49 -0
  132. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorSelector.h +1 -1
  133. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorValueSelector.h +1 -1
  134. hikyuu/include/hikyuu/trade_sys/signal/imp/BandSignal2.h +0 -4
  135. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/AddValueSignal.h +2 -2
  136. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/DivValueSignal.h +2 -2
  137. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/MulValueSignal.h +2 -2
  138. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorSignal.h +1 -1
  139. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorValueSignal.h +4 -4
  140. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/SubValueSignal.h +2 -2
  141. hikyuu/include/hikyuu/trade_sys/system/System.h +14 -1
  142. hikyuu/include/hikyuu/utilities/SpendTimer.h +17 -7
  143. hikyuu/include/hikyuu/utilities/arithmetic.h +45 -0
  144. hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +1 -1
  145. hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +1 -1
  146. hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h +1 -1
  147. hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.h +1 -1
  148. hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +4 -1
  149. hikyuu/include/hikyuu/version.h +4 -4
  150. hikyuu/plugin/backtest.dll +0 -0
  151. hikyuu/plugin/clickhousedriver.dll +0 -0
  152. hikyuu/plugin/dataserver.dll +0 -0
  153. hikyuu/plugin/device.dll +0 -0
  154. hikyuu/plugin/extind.dll +0 -0
  155. hikyuu/plugin/hkuextra.dll +0 -0
  156. hikyuu/plugin/hkuviews.dll +0 -0
  157. hikyuu/plugin/import2hdf5.dll +0 -0
  158. hikyuu/plugin/tmreport.dll +0 -0
  159. hikyuu/trade_manage/__init__.pyi +33 -8
  160. hikyuu/trade_manage/trade.pyi +33 -8
  161. hikyuu/util/__init__.pyi +2 -2
  162. hikyuu/util/singleton.pyi +1 -1
  163. {hikyuu-2.6.8.5.dist-info → hikyuu-2.6.9.dist-info}/METADATA +13 -14
  164. {hikyuu-2.6.8.5.dist-info → hikyuu-2.6.9.dist-info}/RECORD +167 -149
  165. {hikyuu-2.6.8.5.dist-info → hikyuu-2.6.9.dist-info}/top_level.txt +2 -1
  166. hikyuu/data_driver/__init__.py +0 -49
  167. hikyuu/data_driver/jqdata_data_driver.py +0 -277
  168. hikyuu/data_driver/pytdx_data_driver.py +0 -292
  169. hikyuu/fetcher/stock/zh_stock_a_huatai.py +0 -51
  170. hikyuu/fetcher/stock/zh_stock_a_pytdx.py +0 -129
  171. hikyuu/gui/data/CollectToMemThread.py +0 -123
  172. hikyuu/gui/data/CollectToMySQLThread.py +0 -178
  173. hikyuu/gui/start_huatai_insight.py +0 -510
  174. hikyuu/tools/update_block_info.py +0 -168
  175. {hikyuu-2.6.8.5.dist-info → hikyuu-2.6.9.dist-info}/WHEEL +0 -0
  176. {hikyuu-2.6.8.5.dist-info → hikyuu-2.6.9.dist-info}/entry_points.txt +0 -0
@@ -1,129 +0,0 @@
1
- # coding:utf-8
2
- #
3
- # The MIT License (MIT)
4
- #
5
- # Created on: 2020-11-29
6
- # Author: fasiondog
7
-
8
- import datetime
9
- from concurrent import futures
10
- from pytdx.hq import TdxHq_API
11
- from hikyuu.data.common_pytdx import search_best_tdx
12
- from hikyuu import get_stock, constant
13
- from hikyuu.util import *
14
-
15
-
16
- @hku_catch(ret=None, callback=lambda quotes: hku_warn(quotes))
17
- def parse_one_result(quotes):
18
- result = {}
19
- hku_check_ignore(quotes, "Invalid input param!")
20
- try:
21
- result['datetime'] = datetime.datetime.combine(
22
- datetime.date.today(), datetime.time.fromisoformat(quotes['servertime'])
23
- )
24
- except:
25
- return None
26
-
27
- result['market'] = 'SH' if quotes['market'] == 1 else 'SZ'
28
- result['code'] = quotes['code']
29
- result['name'] = ''
30
- result['open'] = quotes['open'] # 今日开盘价
31
- result['yesterday_close'] = quotes['last_close'] # 昨日收盘价
32
- result['close'] = quotes['price'] # 当前价格
33
- result['high'] = quotes['high'] # 今日最高价
34
- result['low'] = quotes['low'] # 今日最低价
35
- result['bid'] = float(quotes['bid1']) # 竞买价,即“买一”报价
36
- result['ask'] = float(quotes['ask1']) # 竞卖价,即“卖一”报价
37
- # 指数 volumn 需要乘以 0.01
38
- stk = get_stock(f"{result['market']}{result['code']}")
39
- if not stk.is_null() and stk.type == constant.STOCKTYPE_INDEX:
40
- result['volume'] = float(quotes['vol']) * 0.01
41
- else:
42
- result['volume'] = float(quotes['vol']) # 成交的股票手数
43
- result['amount'] = round(quotes['amount'] * 0.0001, 2) # 成交金额,单位为“元”,若要以“万元”为成交金额的单位,需要把该值除以一万
44
-
45
- result['bid'] = [float(quotes['bid1']), float(quotes['bid2']), float(
46
- quotes['bid3']), float(quotes['bid4']), float(quotes['bid5'])]
47
- result['bid_amount'] = [float(quotes['bid_vol1']), float(quotes['bid_vol2']), float(
48
- quotes['bid_vol3']), float(quotes['bid_vol4']), float(quotes['bid_vol5'])]
49
- result['ask'] = [float(quotes['ask1']), float(quotes['ask2']), float(
50
- quotes['ask3']), float(quotes['ask4']), float(quotes['ask5'])]
51
- result['ask_amount'] = [float(quotes['ask_vol1']), float(quotes['ask_vol2']), float(
52
- quotes['ask_vol3']), float(quotes['ask_vol4']), float(quotes['ask_vol5'])]
53
- return result
54
-
55
-
56
- @hku_catch(ret=[], trace=True)
57
- def request_data(api, stklist, parse_one_result):
58
- """请求失败将抛出异常"""
59
- quotes_list = api.get_security_quotes(stklist)
60
- result = [parse_one_result(q) for q in quotes_list] if quotes_list is not None else []
61
- return [r for r in result if r is not None]
62
-
63
-
64
- @hku_catch(ret=([], []))
65
- def inner_get_spot(stocklist, ip, port, batch_func=None):
66
- api = TdxHq_API()
67
- hku_check(api.connect(ip, port), 'Failed connect tdx ({}:{})!'.format(ip, port))
68
-
69
- count = 0
70
- tmplist = []
71
- result = []
72
- max_size = 80
73
- err_list = []
74
- for stk in stocklist:
75
- tmplist.append((1 if stk.market == 'SH' else 0, stk.code))
76
- count += 1
77
- if count >= max_size:
78
- phase_result = request_data(api, tmplist, parse_one_result)
79
- if phase_result:
80
- result.extend(phase_result)
81
- if batch_func:
82
- batch_func(phase_result)
83
- else:
84
- err_list.extend(tmplist)
85
- count = 0
86
- tmplist = []
87
- if tmplist:
88
- phase_result = request_data(api, tmplist, parse_one_result)
89
- if phase_result:
90
- result.extend(phase_result)
91
- if batch_func:
92
- batch_func(phase_result)
93
- else:
94
- err_list.extend(tmplist)
95
- api.disconnect()
96
- return result, err_list
97
-
98
-
99
- @spend_time
100
- def get_spot(stocklist, ip, port, batch_func=None):
101
- hosts = search_best_tdx()
102
- hosts_cnt = len(hosts)
103
- num = len(stocklist) // hosts_cnt
104
- batchslist = []
105
- for i in range(hosts_cnt):
106
- batchslist.append([[stk for stk in stocklist[i*num: (i+1)*num]], hosts[i][2], hosts[i][3], batch_func])
107
- if len(stocklist) % hosts_cnt != 0:
108
- pos = num * hosts_cnt
109
- for i in range(hosts_cnt):
110
- batchslist[i][0].append(stocklist[pos])
111
- pos += 1
112
- if pos >= len(stocklist):
113
- break
114
-
115
- def do_inner(param):
116
- ret = inner_get_spot(param[0], param[1], param[2], param[3])
117
- return ret
118
-
119
- with futures.ThreadPoolExecutor() as executor:
120
- res = executor.map(do_inner, batchslist, timeout=10)
121
-
122
- result = []
123
- errors = []
124
- for batch_result in res:
125
- if batch_result[0]:
126
- result.extend(batch_result[0])
127
- if batch_result[1]:
128
- errors.extend(batch_result[1])
129
- return result, errors
@@ -1,123 +0,0 @@
1
- #!/usr/bin/python
2
- # -*- coding: utf8 -*-
3
- # cp936
4
- import logging
5
- import time
6
- import datetime
7
- from math import ceil
8
- from PyQt5.QtCore import QThread, QWaitCondition, QMutex
9
-
10
- from hikyuu import Datetime, TimeDelta, hikyuu_init, StockManager, constant
11
- from hikyuu.util import *
12
- from hikyuu.fetcher.stock.zh_stock_a_sina_qq import get_spot
13
- from hikyuu.data.sqlite_mem import SqliteMemDriver
14
-
15
-
16
- class CollectToMemThread(QThread):
17
- def __init__(self, config, hku_config_file, market='SH'):
18
- super(self.__class__, self).__init__()
19
- self.working = True
20
- self._config = config
21
- self.hku_config_file = hku_config_file
22
- self.market = market.lower()
23
- self.marketid = None
24
- self._interval = TimeDelta(seconds=config.getint('collect', 'interval', fallback=60 * 60))
25
- self._phase1_start_time = Datetime(
26
- datetime.datetime.combine(
27
- datetime.date.today(),
28
- datetime.time.fromisoformat((config.get('collect', 'phase1_start', fallback='09:05')))
29
- )
30
- )
31
- self._phase1_end_time = Datetime(
32
- datetime.datetime.combine(
33
- datetime.date.today(),
34
- datetime.time.fromisoformat((config.get('collect', 'phase1_end', fallback='09:05')))
35
- )
36
- )
37
- self._use_zhima_proxy = config.getboolean('collect', 'use_zhima_proxy', fallback=False)
38
-
39
- self.cond = QWaitCondition()
40
- self.mutex = QMutex()
41
-
42
- def stop(self):
43
- if self.working:
44
- self.working = False
45
- self.cond.wakeAll()
46
- self.wait()
47
-
48
- def __del__(self):
49
- self.stop()
50
-
51
- @hku_catch()
52
- def run(self):
53
- self.logger.info("{} 数据采集同步线程启动".format(self.market))
54
- self.db = SqliteMemDriver()
55
-
56
- hikyuu_init(self.hku_config_file, ignore_preload=True)
57
-
58
- stk_list = self.get_stock_list()
59
- hku_warn_if(not stk_list, "从数据库中获取的股票列表为空!", logger=self.logger)
60
- self.mutex.tryLock()
61
-
62
- end_delta = self._phase1_end_time - self._phase1_end_time.start_of_day()
63
- start_delta = self._phase1_start_time - self._phase1_start_time.start_of_day()
64
-
65
- start = Datetime.now()
66
- if self._phase1_start_time >= self._phase1_end_time:
67
- delta = TimeDelta(0)
68
- elif start >= self._phase1_end_time:
69
- delta = (self._phase1_start_time + TimeDelta(1) - start)
70
- elif start < self._phase1_start_time:
71
- delta = (self._phase1_start_time - start)
72
- else:
73
- delta = self._interval * ceil((start - self._phase1_start_time) / self._interval
74
- ) - (start - self._phase1_start_time)
75
-
76
- hku_info('{} 下次采集时间:{}', self.market, start + delta, logger=self.logger)
77
- delta = int(delta.total_milliseconds())
78
- while self.working and not self.cond.wait(self.mutex, int(delta)):
79
- last_time = Datetime.today() + end_delta
80
- start = Datetime.now()
81
- if start >= last_time:
82
- next_time = Datetime.today() + TimeDelta(1) + start_delta
83
- hku_info('{} 明日采集时间:{}', self.market, next_time, logger=self.logger)
84
- delta = next_time - start
85
- delta = int(delta.total_milliseconds())
86
- continue
87
- hku_trace("start:{}".format(start))
88
- self.collect(stk_list)
89
- end = Datetime.now()
90
- x = end - start
91
- if x + TimeDelta(seconds=1) < self._interval:
92
- delta = self._interval - x - TimeDelta(seconds=1)
93
- delta = int(delta.total_milliseconds())
94
- self.logger.info("{} {:<.2f} 秒后重新采集".format(self.market, delta / 1000))
95
- # self.sleep(delta)
96
-
97
- self.db.close()
98
- self.logger.info("{} 数据采集同步线程终止!".format(self.market))
99
-
100
- @hku_catch(retry=2, ret=[])
101
- def get_stock_list(self):
102
- sm = StockManager.instance()
103
- return [
104
- stk.market_code.lower() for stk in sm
105
- if stk.type in (constant.STOCKTYPE_A, constant.STOCKTYPE_INDEX,
106
- constant.STOCKTYPE_GEM, constant.STOCKTYPE_A_BJ) and stk.valid and stk.market.lower() == self.market.lower()
107
- ]
108
-
109
- def record_is_valid(self, record):
110
- return record['amount'] > 0.0 and record['volume'] > 0.0 \
111
- and record['high'] >= record['open'] >= record['low'] > 0.0 \
112
- and record['high'] >= record['close'] >= record['low']
113
-
114
- @hku_catch()
115
- def collect(self, stk_list):
116
- record_list = get_spot(stk_list, source='sina', use_proxy=self._use_zhima_proxy)
117
- hku_info("{} 网络获取数量:{}".format(self.market, len(record_list)))
118
- record_list = [r for r in record_list if self.record_is_valid(r)]
119
- self.db.insert_bars(self.market, record_list, 'day')
120
- self.db.insert_bars(self.market, record_list, 'min')
121
-
122
-
123
- class_logger(CollectToMemThread)
@@ -1,178 +0,0 @@
1
- #!/usr/bin/python
2
- # -*- coding: utf8 -*-
3
- # cp936
4
- import logging
5
- import time
6
- import datetime
7
- from math import ceil
8
- from PyQt5.QtCore import QThread, QWaitCondition, QMutex
9
-
10
- import mysql.connector
11
- from mysql.connector import errorcode
12
-
13
- from hikyuu import Datetime, TimeDelta
14
- from hikyuu.util import *
15
- from hikyuu.data.common_mysql import get_stock_list, get_marketid, get_table
16
- from hikyuu.fetcher.stock.zh_stock_a_sina_qq import get_spot
17
-
18
-
19
- class CollectToMySQLThread(QThread):
20
- def __init__(self, config, market='SH'):
21
- super(self.__class__, self).__init__()
22
- self.working = True
23
- self._config = config
24
- self.market = market.lower()
25
- self.marketid = None
26
- assert config.getboolean("mysql", "enable", fallback=False)
27
- self._db_config = {
28
- 'user': config['mysql']['usr'],
29
- 'password': config['mysql']['pwd'],
30
- 'host': config['mysql']['host'],
31
- 'port': config['mysql']['port']
32
- }
33
- self._connect = None
34
- self.quotations = [
35
- 'stock',
36
- ] # sina 不支持基金,qq支持,此处屏蔽基金
37
- # if config['quotation']['stock']:
38
- # self.quotations.append('stock')
39
- # if config['quotation']['fund']:
40
- # self.quotations.append('fund')
41
- # self.logger.info(self.quotations)
42
-
43
- self._interval = TimeDelta(seconds=config.getint('collect', 'interval', fallback=60 * 60))
44
- self._phase1_start_time = Datetime(
45
- datetime.datetime.combine(
46
- datetime.date.today(),
47
- datetime.time.fromisoformat((config.get('collect', 'phase1_start', fallback='09:05')))
48
- )
49
- )
50
- self._phase1_end_time = Datetime(
51
- datetime.datetime.combine(
52
- datetime.date.today(),
53
- datetime.time.fromisoformat((config.get('collect', 'phase1_end', fallback='09:05')))
54
- )
55
- )
56
- self._use_zhima_proxy = config.getboolean('collect', 'use_zhima_proxy', fallback=False)
57
-
58
- self.cond = QWaitCondition()
59
- self.mutex = QMutex()
60
-
61
- def stop(self):
62
- if self.working:
63
- self.working = False
64
- self.cond.wakeAll()
65
- self.wait()
66
- if self._connect is not None:
67
- hku_trace('关闭数据库连接', logger=self.logger)
68
- self._connect.close()
69
-
70
- def __del__(self):
71
- self.stop()
72
-
73
- @hku_catch()
74
- def run(self):
75
- self.logger.info("{} 数据采集同步线程启动".format(self.market))
76
- stk_list = self.get_stock_list()
77
- hku_warn_if(not stk_list, "从数据库中获取的股票列表为空!", logger=self.logger)
78
- self.mutex.tryLock()
79
-
80
- end_delta = self._phase1_end_time - self._phase1_end_time.start_of_day()
81
- start_delta = self._phase1_start_time - self._phase1_start_time.start_of_day()
82
-
83
- start = Datetime.now()
84
- if self._phase1_start_time >= self._phase1_end_time:
85
- delta = TimeDelta(0)
86
- elif start >= self._phase1_end_time:
87
- delta = (self._phase1_start_time + TimeDelta(1) - start)
88
- elif start < self._phase1_start_time:
89
- delta = (self._phase1_start_time - start)
90
- else:
91
- delta = self._interval * ceil((start - self._phase1_start_time) / self._interval
92
- ) - (start - self._phase1_start_time)
93
-
94
- hku_info('{} 下次采集时间:{}', self.market, start + delta, logger=self.logger)
95
- delta = int(delta.total_milliseconds())
96
- while self.working and not self.cond.wait(self.mutex, int(delta)):
97
- last_time = Datetime.today() + end_delta
98
- start = Datetime.now()
99
- if start >= last_time:
100
- next_time = Datetime.today() + TimeDelta(1) + start_delta
101
- hku_info('{} 明日采集时间:{}', self.market, next_time, logger=self.logger)
102
- delta = next_time - start
103
- delta = int(delta.total_milliseconds())
104
- continue
105
- hku_trace("start:{}".format(start))
106
- self.collect(stk_list)
107
- end = Datetime.now()
108
- x = end - start
109
- if x + TimeDelta(seconds=1) < self._interval:
110
- delta = self._interval - x - TimeDelta(seconds=1)
111
- delta = int(delta.total_milliseconds())
112
- self.logger.info("{} {:<.2f} 秒后重新采集".format(self.market, delta / 1000))
113
- # self.sleep(delta)
114
-
115
- self.logger.info("{} 数据采集同步线程终止!".format(self.market))
116
-
117
- def record_is_valid(self, record):
118
- return record['amount'] > 0.0 and record['volume'] > 0.0 \
119
- and record['high'] >= record['open'] >= record['low'] > 0.0 \
120
- and record['high'] >= record['close'] >= record['low']
121
-
122
- @hku_catch(ret=False)
123
- def process_one_record(self, record):
124
- if not self.record_is_valid(record):
125
- return (0, 0)
126
- connect = self.get_connect()
127
- current_date = Datetime(record['datetime'].date()).number
128
- table = get_table(connect, self.market, record['code'], 'day')
129
- sql = 'replace into {} (date, open, high, low, close, amount, count) \
130
- values ({}, {}, {}, {}, {}, {}, {})'.format(
131
- table, current_date, record['open'], record['high'], record['low'], record['close'], record['amount'],
132
- record['volume']
133
- )
134
- cur = connect.cursor()
135
- cur.execute(sql)
136
- cur.close()
137
- return
138
-
139
- @hku_catch()
140
- def collect(self, stk_list):
141
- record_list = get_spot(stk_list, source='sina', use_proxy=self._use_zhima_proxy)
142
- hku_info("{} 网络获取数量:{}".format(self.market, len(record_list)))
143
- connect = self.get_connect()
144
- if self.marketid == None:
145
- self.marketid = get_marketid(connect, self.market)
146
- update_count = 0
147
- for record in record_list:
148
- if not self.working:
149
- break
150
- if self.process_one_record(record):
151
- update_count += 1
152
- connect.commit()
153
- hku_info("{} 数据库更新记录数:{}".format(self.market, update_count))
154
-
155
- def get_connect(self):
156
- if self._connect:
157
- return self._connect
158
- try:
159
- self._connect = mysql.connector.connect(**self._db_config)
160
- except mysql.connector.Error as err:
161
- if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
162
- self.logger.error("MYSQL密码或用户名错误!")
163
- elif err.errno == errorcode.ER_BAD_DB_ERROR:
164
- self.logger.error("MySQL数据库不存在!")
165
- else:
166
- self.logger.error("连接数据库失败,{}".format(err.msg))
167
- except:
168
- self.logger.error("未知原因导致无法连接数据库!")
169
- return self._connect
170
-
171
- @hku_catch(retry=2, ret=[])
172
- def get_stock_list(self):
173
- connect = self.get_connect()
174
- stk_list = get_stock_list(connect, self.market, self.quotations)
175
- return ["{}{}".format(self.market.lower(), item[2]) for item in stk_list if item[3] == 1]
176
-
177
-
178
- class_logger(CollectToMySQLThread)