hikyuu 2.6.8.5__py3-none-win_amd64.whl → 2.7.0__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 (201) hide show
  1. hikyuu/__init__.py +31 -16
  2. hikyuu/__init__.pyi +610 -590
  3. hikyuu/analysis/__init__.pyi +584 -563
  4. hikyuu/analysis/analysis.pyi +585 -564
  5. hikyuu/core.py +2 -0
  6. hikyuu/core.pyi +586 -565
  7. hikyuu/cpp/__init__.pyi +2 -2
  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 +501 -104
  14. hikyuu/cpp/core311.pyd +0 -0
  15. hikyuu/cpp/core311.pyi +501 -104
  16. hikyuu/cpp/core312.pyd +0 -0
  17. hikyuu/cpp/core312.pyi +501 -104
  18. hikyuu/cpp/core313.pyd +0 -0
  19. hikyuu/cpp/core313.pyi +501 -104
  20. hikyuu/cpp/hikyuu.dll +0 -0
  21. hikyuu/cpp/hikyuu.lib +0 -0
  22. hikyuu/cpp/i18n/zh_CN/hikyuu.mo +0 -0
  23. hikyuu/data/clickhouse_upgrade/createdb.sql +105 -105
  24. hikyuu/data/common.py +3 -3
  25. hikyuu/data/common_clickhouse.py +1 -1
  26. hikyuu/data/download_block.py +351 -0
  27. hikyuu/data/em_block_to_clickhouse.py +26 -74
  28. hikyuu/data/em_block_to_mysql.py +25 -75
  29. hikyuu/data/em_block_to_sqlite.py +26 -78
  30. hikyuu/data/hku_config_template.py +3 -3
  31. hikyuu/data/pytdx_to_clickhouse.py +15 -11
  32. hikyuu/data/pytdx_to_h5.py +6 -2
  33. hikyuu/data/pytdx_to_mysql.py +5 -1
  34. hikyuu/data/pytdx_weight_to_clickhouse.py +1 -1
  35. hikyuu/data/pytdx_weight_to_mysql.py +1 -1
  36. hikyuu/data/pytdx_weight_to_sqlite.py +1 -1
  37. hikyuu/data/zh_bond10_to_clickhouse.py +1 -1
  38. hikyuu/draw/drawplot/__init__.pyi +8 -8
  39. hikyuu/draw/drawplot/bokeh_draw.pyi +600 -580
  40. hikyuu/draw/drawplot/common.pyi +1 -1
  41. hikyuu/draw/drawplot/echarts_draw.pyi +602 -582
  42. hikyuu/draw/drawplot/matplotlib_draw.py +4 -74
  43. hikyuu/draw/drawplot/matplotlib_draw.pyi +612 -592
  44. hikyuu/draw/elder.pyi +11 -11
  45. hikyuu/draw/kaufman.pyi +18 -18
  46. hikyuu/draw/volume.pyi +10 -10
  47. hikyuu/examples/notebook/Demo/Demo1.ipynb +48 -33
  48. hikyuu/extend.py +0 -8
  49. hikyuu/extend.pyi +594 -574
  50. hikyuu/fetcher/stock/zh_block_em.py +12 -40
  51. hikyuu/gui/HikyuuTDX.py +99 -31
  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 +1196 -717
  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/gui/images/liandongxiaopu.png +0 -0
  63. hikyuu/hub.pyi +6 -6
  64. hikyuu/include/hikyuu/DataType.h +4 -16
  65. hikyuu/include/hikyuu/KData.h +6 -3
  66. hikyuu/include/hikyuu/KDataPrivatedBufferImp.h +1 -1
  67. hikyuu/include/hikyuu/KDataSharedBufferImp.h +1 -1
  68. hikyuu/include/hikyuu/KQuery.h +2 -2
  69. hikyuu/include/hikyuu/Stock.h +4 -1
  70. hikyuu/include/hikyuu/StockManager.h +13 -3
  71. hikyuu/include/hikyuu/config.h +0 -3
  72. hikyuu/include/hikyuu/data_driver/BaseInfoDriver.h +8 -0
  73. hikyuu/include/hikyuu/data_driver/BlockInfoDriver.h +6 -0
  74. hikyuu/include/hikyuu/data_driver/KDataDriver.h +26 -1
  75. hikyuu/include/hikyuu/data_driver/base_info/mysql/MySQLBaseInfoDriver.h +1 -1
  76. hikyuu/include/hikyuu/data_driver/base_info/sqlite/SQLiteBaseInfoDriver.h +1 -1
  77. hikyuu/include/hikyuu/data_driver/block_info/mysql/MySQLBlockInfoDriver.h +2 -1
  78. hikyuu/include/hikyuu/data_driver/block_info/qianlong/QLBlockInfoDriver.h +2 -1
  79. hikyuu/include/hikyuu/data_driver/block_info/sqlite/SQLiteBlockInfoDriver.h +2 -1
  80. hikyuu/include/hikyuu/data_driver/kdata/DoNothingKDataDriver.h +1 -1
  81. hikyuu/include/hikyuu/data_driver/kdata/cvs/KDataTempCsvDriver.h +1 -1
  82. hikyuu/include/hikyuu/data_driver/kdata/hdf5/H5KDataDriver.h +1 -1
  83. hikyuu/include/hikyuu/data_driver/kdata/mysql/MySQLKDataDriver.h +1 -1
  84. hikyuu/include/hikyuu/data_driver/kdata/sqlite/SQLiteKDataDriver.h +1 -1
  85. hikyuu/include/hikyuu/data_driver/kdata/tdx/TdxKDataDriver.h +1 -1
  86. hikyuu/include/hikyuu/hikyuu.h +1 -1
  87. hikyuu/include/hikyuu/indicator/build_in.h +1 -0
  88. hikyuu/include/hikyuu/indicator/crt/CYCLE.h +4 -4
  89. hikyuu/include/hikyuu/indicator/crt/HSL.h +2 -2
  90. hikyuu/include/hikyuu/indicator/crt/QUANTILE_TRUNC.h +30 -0
  91. hikyuu/include/hikyuu/indicator/crt/TURNOVER.h +1 -0
  92. hikyuu/include/hikyuu/indicator/crt/ZSCORE.h +2 -2
  93. hikyuu/include/hikyuu/indicator/imp/IQuantileTrunc.h +25 -0
  94. hikyuu/include/hikyuu/misc.h +38 -0
  95. hikyuu/include/hikyuu/plugin/dataserver.h +2 -1
  96. hikyuu/include/hikyuu/plugin/device.h +10 -0
  97. hikyuu/include/hikyuu/plugin/extind.h +37 -0
  98. hikyuu/include/hikyuu/plugin/interface/DataServerPluginInterface.h +2 -2
  99. hikyuu/include/hikyuu/plugin/interface/DevicePluginInterface.h +2 -0
  100. hikyuu/include/hikyuu/plugin/interface/ExtendIndicatorsPluginInterface.h +12 -0
  101. hikyuu/include/hikyuu/plugin/interface/plugins.h +0 -5
  102. hikyuu/include/hikyuu/python/pybind_utils.h +0 -12
  103. hikyuu/include/hikyuu/strategy/RunSystemInStrategy.h +3 -0
  104. hikyuu/include/hikyuu/trade_manage/Performance.h +4 -4
  105. hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +10 -1
  106. hikyuu/include/hikyuu/trade_sys/moneymanager/imp/FixedCapitalFundsMM.h +0 -4
  107. hikyuu/include/hikyuu/trade_sys/multifactor/MultiFactorBase.h +36 -3
  108. hikyuu/include/hikyuu/trade_sys/multifactor/NormalizeBase.h +125 -0
  109. hikyuu/include/hikyuu/trade_sys/multifactor/ScoresFilterBase.h +125 -0
  110. hikyuu/include/hikyuu/trade_sys/multifactor/build_in.h +3 -0
  111. hikyuu/include/hikyuu/trade_sys/multifactor/buildin_norm.h +36 -0
  112. hikyuu/include/hikyuu/trade_sys/multifactor/buildin_scfilter.h +51 -0
  113. hikyuu/include/hikyuu/trade_sys/multifactor/filter/GroupSCFilter.h +24 -0
  114. hikyuu/include/hikyuu/trade_sys/multifactor/filter/IgnoreLessOrEqualValueSCFilter.h +24 -0
  115. hikyuu/include/hikyuu/trade_sys/multifactor/filter/IgnoreNanSCFilter.h +24 -0
  116. hikyuu/include/hikyuu/trade_sys/multifactor/filter/MinAmountPercentSCFilter.h +25 -0
  117. hikyuu/include/hikyuu/trade_sys/multifactor/filter/PriceSCFilter.h +24 -0
  118. hikyuu/include/hikyuu/trade_sys/multifactor/filter/TopNSCFilter.h +24 -0
  119. hikyuu/include/hikyuu/trade_sys/multifactor/imp/EqualWeightMultiFactor.h +1 -1
  120. hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICIRMultiFactor.h +1 -1
  121. hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICMultiFactor.h +1 -1
  122. hikyuu/include/hikyuu/trade_sys/multifactor/imp/WeightMultiFactor.h +1 -1
  123. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormMinMax.h +23 -0
  124. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormQuantile.h +28 -0
  125. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormQuantileUniform.h +28 -0
  126. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormZScore.h +25 -0
  127. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/__init__.py +1 -0
  128. hikyuu/include/hikyuu/trade_sys/multifactor/normalize/quantile_trunc.h +16 -0
  129. hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +7 -0
  130. hikyuu/include/hikyuu/trade_sys/portfolio/imp/SimplePortfolio.h +7 -0
  131. hikyuu/include/hikyuu/trade_sys/portfolio/imp/WithoutAFPortfolio.h +7 -0
  132. hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +49 -0
  133. hikyuu/include/hikyuu/trade_sys/selector/build_in.h +1 -0
  134. hikyuu/include/hikyuu/trade_sys/selector/crt/SE_MultiFactor2.h +40 -0
  135. hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector.h +0 -3
  136. hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector2.h +49 -0
  137. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorSelector.h +1 -1
  138. hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorValueSelector.h +1 -1
  139. hikyuu/include/hikyuu/trade_sys/signal/imp/BandSignal2.h +0 -4
  140. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/AddValueSignal.h +2 -2
  141. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/DivValueSignal.h +2 -2
  142. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/MulValueSignal.h +2 -2
  143. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorSignal.h +1 -1
  144. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorValueSignal.h +4 -4
  145. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/SubValueSignal.h +2 -2
  146. hikyuu/include/hikyuu/trade_sys/slippage/build_in.h +5 -1
  147. hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_LogNormal.h +22 -0
  148. hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_Normal.h +22 -0
  149. hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_TruncNormal.h +25 -0
  150. hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_Uniform.h +23 -0
  151. hikyuu/include/hikyuu/trade_sys/slippage/imp/LogNormalSlippage.h +28 -0
  152. hikyuu/include/hikyuu/trade_sys/slippage/imp/NormalSlippage.h +28 -0
  153. hikyuu/include/hikyuu/trade_sys/slippage/imp/TruncNormalSlippage.h +28 -0
  154. hikyuu/include/hikyuu/trade_sys/slippage/imp/UniformSlippage.h +24 -0
  155. hikyuu/include/hikyuu/trade_sys/system/System.h +14 -1
  156. hikyuu/include/hikyuu/utilities/SpendTimer.h +17 -7
  157. hikyuu/include/hikyuu/utilities/arithmetic.h +45 -0
  158. hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +1 -1
  159. hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +1 -1
  160. hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h +1 -1
  161. hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.h +1 -1
  162. hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +4 -1
  163. hikyuu/include/hikyuu/version.h +5 -5
  164. hikyuu/plugin/backtest.dll +0 -0
  165. hikyuu/plugin/clickhousedriver.dll +0 -0
  166. hikyuu/plugin/dataserver.dll +0 -0
  167. hikyuu/plugin/dataserver_parquet.dll +0 -0
  168. hikyuu/plugin/device.dll +0 -0
  169. hikyuu/plugin/extind.dll +0 -0
  170. hikyuu/plugin/hkuextra.dll +0 -0
  171. hikyuu/plugin/import2hdf5.dll +0 -0
  172. hikyuu/plugin/tmreport.dll +0 -0
  173. hikyuu/trade_manage/__init__.pyi +600 -580
  174. hikyuu/trade_manage/broker.pyi +3 -3
  175. hikyuu/trade_manage/broker_easytrader.pyi +1 -1
  176. hikyuu/trade_manage/trade.py +0 -2
  177. hikyuu/trade_manage/trade.pyi +600 -580
  178. hikyuu/util/__init__.pyi +2 -2
  179. hikyuu/util/singleton.pyi +1 -1
  180. {hikyuu-2.6.8.5.dist-info → hikyuu-2.7.0.dist-info}/METADATA +36 -33
  181. {hikyuu-2.6.8.5.dist-info → hikyuu-2.7.0.dist-info}/RECORD +185 -168
  182. {hikyuu-2.6.8.5.dist-info → hikyuu-2.7.0.dist-info}/top_level.txt +2 -2
  183. hikyuu/cpp/core39.pyd +0 -0
  184. hikyuu/cpp/core39.pyi +0 -14381
  185. hikyuu/data_driver/__init__.py +0 -49
  186. hikyuu/data_driver/jqdata_data_driver.py +0 -277
  187. hikyuu/data_driver/pytdx_data_driver.py +0 -292
  188. hikyuu/fetcher/stock/zh_stock_a_huatai.py +0 -51
  189. hikyuu/fetcher/stock/zh_stock_a_pytdx.py +0 -129
  190. hikyuu/gui/data/CollectToMemThread.py +0 -123
  191. hikyuu/gui/data/CollectToMySQLThread.py +0 -178
  192. hikyuu/gui/start_huatai_insight.py +0 -510
  193. hikyuu/include/hikyuu/plugin/hkuviews.h +0 -36
  194. hikyuu/include/hikyuu/plugin/interface/HkuViewsPluginInterface.h +0 -34
  195. hikyuu/include/hikyuu/views/arrow_common.h +0 -38
  196. hikyuu/include/hikyuu/views/arrow_views.h +0 -117
  197. hikyuu/plugin/hkuviews.dll +0 -0
  198. hikyuu/tools/update_block_info.py +0 -168
  199. /hikyuu/include/hikyuu/{views → trade_sys/multifactor/filter}/__init__.py +0 -0
  200. {hikyuu-2.6.8.5.dist-info → hikyuu-2.7.0.dist-info}/WHEEL +0 -0
  201. {hikyuu-2.6.8.5.dist-info → hikyuu-2.7.0.dist-info}/entry_points.txt +0 -0
@@ -17,7 +17,6 @@ from hikyuu.util import *
17
17
  em_num_per_page = 100
18
18
 
19
19
 
20
- @hku_catch(ret=[], trace=True)
21
20
  def get_hybk_names():
22
21
  """获取所有行业(板块代码,板块名称)列表"""
23
22
  url = "https://19.push2.eastmoney.com/api/qt/clist/get"
@@ -50,7 +49,6 @@ def get_hybk_names():
50
49
  return ret
51
50
 
52
51
 
53
- @hku_catch(ret=[], trace=True)
54
52
  def get_hybk_cons_code(blk_code):
55
53
  "获取指定行业板块成分代码列表"
56
54
  url = "http://30.push2.eastmoney.com/api/qt/clist/get"
@@ -83,16 +81,18 @@ def get_hybk_cons_code(blk_code):
83
81
  return ret
84
82
 
85
83
 
86
- @hku_catch(ret={}, trace=True)
87
84
  def get_all_hybk_info(code_market_dict, sep=""):
88
85
  """获取所有行业板块列表"""
89
86
  blk_list = get_hybk_names()
87
+ time.sleep(random.uniform(1, 3))
90
88
  ret = {}
91
- for blk in blk_list:
89
+ total = len(blk_list)
90
+ for i, blk in enumerate(blk_list):
92
91
  stk_codes = get_hybk_cons_code(blk[0])
93
- hku_info(f"获取行业板块{blk[1]}成分: {len(stk_codes)}")
92
+ hku_info(f"{i}|{total} 获取行业板块{blk[1]}成分: {len(stk_codes)}")
94
93
  ret[blk[1]] = [
95
94
  f"{code_market_dict[stk_code]}{sep}{stk_code}" for stk_code in stk_codes if stk_code in code_market_dict]
95
+ time.sleep(random.uniform(1, 3))
96
96
  return ret
97
97
 
98
98
 
@@ -431,21 +431,21 @@ def stock_board_concept_cons_em(symbol: str = "融资融券") -> pd.DataFrame:
431
431
  return temp_df
432
432
 
433
433
 
434
- @hku_catch(ret={}, trace=True)
435
434
  def get_all_gnbk_info(code_market_dict, sep=""):
436
435
  """获取所有概念版本列表"""
437
436
  blk_names = stock_board_concept_name_em()['板块名称']
438
437
  ret = {}
438
+ total = len(blk_names)
439
439
  for i, blk_name in enumerate(blk_names):
440
440
  stk_codes = stock_board_concept_cons_em(blk_name)
441
441
  stk_codes = stk_codes['代码'].to_list()
442
- hku_info(f"{i} 获取概念板块{blk_name}成分: {len(stk_codes)}")
442
+ hku_info(f"{i}|{total} 获取概念板块{blk_name}成分: {len(stk_codes)}")
443
443
  ret[blk_name] = [
444
444
  f"{code_market_dict[stk_code]}{sep}{stk_code}" for stk_code in stk_codes if stk_code in code_market_dict]
445
+ time.sleep(random.uniform(1, 3))
445
446
  return ret
446
447
 
447
448
 
448
- @hku_catch(ret=[], trace=True)
449
449
  def get_dybk_names():
450
450
  """获取所有地域板块名称列表"""
451
451
  url = "http://13.push2.eastmoney.com/api/qt/clist/get"
@@ -478,7 +478,6 @@ def get_dybk_names():
478
478
  return ret
479
479
 
480
480
 
481
- @hku_catch(ret={}, trace=True)
482
481
  def get_all_dybk_info(code_market_dict, sep=""):
483
482
  """获取所有地域板块列表"""
484
483
  blk_list = get_dybk_names()
@@ -499,10 +498,12 @@ def get_all_dybk_info(code_market_dict, sep=""):
499
498
  }
500
499
 
501
500
  ret = {}
502
- for v in blk_list:
501
+ total = len(blk_list)
502
+ for i, v in enumerate(blk_list):
503
503
  blk_code, blk_name = v[0], v[1]
504
504
  params["fs"] = f"b:{blk_code} f:!50"
505
505
  params["pn"] = 1
506
+ time.sleep(random.uniform(1, 3))
506
507
  r = requests.get(url, params=params, timeout=15)
507
508
  data = r.json()
508
509
  if data["data"] is None:
@@ -522,37 +523,8 @@ def get_all_dybk_info(code_market_dict, sep=""):
522
523
  ret[blk_name].extend(
523
524
  [f"{code_market_dict[v['f12']]}{sep}{v['f12']}" for v in stk_json if v["f12"] in code_market_dict])
524
525
  time.sleep(random.uniform(1, 3))
525
- hku_info(f'获取地域板块{blk_name}成分: {len(ret[blk_name])}')
526
-
527
- return ret
528
-
526
+ hku_info(f'{i}|{total} 获取地域板块{blk_name}成分: {len(ret[blk_name])}')
529
527
 
530
- @hku_catch(ret={}, trace=True)
531
- def get_all_zsbk_info(code_market_dict, sep=""):
532
- """获取所有指数成分股列表"""
533
- blk_info = ak.index_stock_info()
534
- blk_codes = blk_info["index_code"]
535
- blk_names = blk_info["display_name"]
536
- ret = {}
537
- total = len(blk_codes)
538
- for i in range(total):
539
- blk_name = blk_names[i]
540
- blk_code = blk_codes[i]
541
- # print(i, blk_name)
542
- # 沪深指数有重复,避免深指覆盖
543
- if blk_name in ret:
544
- continue
545
- try:
546
- stk_codes = ak.index_stock_cons_csindex(symbol=blk_code)
547
- stk_codes = stk_codes['成分券代码'].to_list()
548
- hku_info("{} 获取指数板块{}成分: {}", i, blk_name, len(stk_codes))
549
- ret[blk_name] = [
550
- f"{code_market_dict[stk_code]}{sep}{stk_code}" for stk_code in stk_codes if stk_code in code_market_dict]
551
- except KeyboardInterrupt:
552
- break
553
- except:
554
- # print("Failed!", blk_code, blk_name)
555
- pass
556
528
  return ret
557
529
 
558
530
 
hikyuu/gui/HikyuuTDX.py CHANGED
@@ -12,11 +12,10 @@ from logging.handlers import QueueListener
12
12
  # 优先加载,处理 VS 17.10 升级后依赖 dll 不兼容问题
13
13
  import hikyuu
14
14
 
15
- import PyQt5
16
-
17
- from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox
18
- from PyQt5.QtCore import pyqtSlot, QObject, pyqtSignal
19
- from PyQt5.QtGui import QIcon, QTextCursor, QFont, QPalette, QPixmap
15
+ # 替换PyQt5导入为PySide6
16
+ from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox
17
+ from PySide6.QtCore import Slot, QObject, Signal
18
+ from PySide6.QtGui import QIcon, QTextCursor, QFont, QPalette, QPixmap
20
19
 
21
20
  import mysql.connector
22
21
  from mysql.connector import errorcode
@@ -36,14 +35,15 @@ from hikyuu.gui.data.CollectSpotThread import CollectSpotThread
36
35
  from hikyuu.gui.data.SchedImportThread import SchedImportThread
37
36
  from hikyuu.gui.spot_server import release_nng_senders
38
37
 
39
- from hikyuu import can_upgrade, get_last_version, fetch_trial_license, view_license, is_valid_license
38
+ from hikyuu import (can_upgrade, get_last_version, fetch_trial_license,
39
+ view_license, is_valid_license, get_expire_date, Datetime, TimeDelta)
40
40
  from hikyuu.data import hku_config_template
41
41
  from hikyuu.util import *
42
42
 
43
43
 
44
44
  class EmittingStream(QObject):
45
45
  """输出重定向至QT"""
46
- textWritten = pyqtSignal(str)
46
+ textWritten = Signal(str)
47
47
 
48
48
  def write(self, text):
49
49
  self.textWritten.emit(str(text))
@@ -249,7 +249,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
249
249
  except:
250
250
  pass
251
251
 
252
- @pyqtSlot()
252
+ @Slot()
253
253
  def on_save_pushButton_clicked(self):
254
254
  try:
255
255
  self.saveConfig()
@@ -314,6 +314,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
314
314
  if os.path.exists(this_dir + '/importdata-gui.ini'):
315
315
  import_config.read(this_dir + '/importdata-gui.ini', encoding='utf-8')
316
316
 
317
+ self.use_download = 'pytdx'
317
318
  self._is_sched_import_running = False
318
319
  self._is_collect_running = False
319
320
  self._stream = None
@@ -333,7 +334,25 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
333
334
  icon = QIcon(f"{current_dir}/images/hikyuu_small.png")
334
335
  star_img = QPixmap(f"{current_dir}/images/star.png")
335
336
  self.label_44.setPixmap(star_img)
337
+ liandong_img = QPixmap(f"{current_dir}/images/liandongxiaopu.png")
338
+ self.label_56.setPixmap(liandong_img)
339
+
340
+ # 修改 label_46 的 HTML 文本,直接在 HTML 中设置字体大小
341
+
342
+ label_46_txt = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
343
+ <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
344
+ p, li { white-space: pre-wrap; }
345
+ hr { height: 1px; border-width: 0; }
346
+ li.unchecked::marker { content: "\2610"; }
347
+ li.checked::marker { content: "\2612"; }
348
+ </style></head><body style="font-weight:400; font-style:normal;">
349
+ <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span>Hikyuu </span><span style="font-weight:700;">专注于量化交易领域的核心技术构建,涵盖交易模型开发、极速计算引擎、高效回测框架及实盘拓展能力</span><span>,定位为量化交易计算引擎,为量化交易爱好者提供高性能底层架构支持。随着社区规模扩大,分散了作者在策略研究上的精力。为保障项目的可持续性,现对捐赠用户提供部分额外功能作为回馈,感谢社区伙伴的支持!</span></p>
350
+ <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span>捐赠功能以插件的方式提供,采用独立授权许可,完全在 hikyuu 之外,对喜欢自行编译扩展的朋友没有影响。因插件许可授权需要采集硬件信息,如有疑虑只要不申请试用许可和正式许可授权,不会触发硬件信息采集,如申请,视为同意采集。</span></p>
351
+ <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span>详情参见:</span><a href="https://hikyuu.readthedocs.io/zh-cn/latest/vip/vip-plan.html"><span style="text-decoration: underline; color:#3586ff;">捐赠权益</span></a><span style="font-weight:700;"> ,感谢大家的支持!</span></p></body></html>
352
+ """
353
+ self.label_46.setText(label_46_txt)
336
354
  self.label_46.setOpenExternalLinks(True)
355
+
337
356
  self.label_license.setText(view_license())
338
357
  self.fetch_trial_pushButton.setEnabled(not is_valid_license())
339
358
 
@@ -434,6 +453,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
434
453
  if (not is_valid_license()) or hdf5_enable or mysql_enable:
435
454
  clickhouse_enable = False
436
455
  self.enable_clickhouse_radioButton.setChecked(clickhouse_enable)
456
+ self.enable_clickhouse_radioButton.setEnabled(is_valid_license())
437
457
  self.clickhouse_tmpdir_lineEdit.setText(import_config.get('clickhouse', 'tmpdir', fallback='d:/stock'))
438
458
  self.clickhouse_tmpdir_pushButton.setEnabled(clickhouse_enable)
439
459
  clickhouse_ip = import_config.get('clickhouse', 'host', fallback='127.0.0.1')
@@ -618,7 +638,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
618
638
  '5MIN': self.hdf5_5min_progressBar
619
639
  }
620
640
 
621
- @pyqtSlot()
641
+ @Slot()
622
642
  def on_fetch_trial_pushButton_clicked(self):
623
643
  email = self.email_lineEdit.text()
624
644
  info = fetch_trial_license(email)
@@ -626,7 +646,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
626
646
  self.label_license.setText(view_license())
627
647
  self.fetch_trial_pushButton.setEnabled(not is_valid_license())
628
648
 
629
- @pyqtSlot()
649
+ @Slot()
630
650
  def on_pytdx_radioButton_clicked(self):
631
651
  if self.pytdx_radioButton.isChecked():
632
652
  self.tdx_radioButton.setChecked(False)
@@ -634,7 +654,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
634
654
  self.use_download = 'pytdx'
635
655
  self.on_tdx_or_pytdx_toggled()
636
656
 
637
- @pyqtSlot()
657
+ @Slot()
638
658
  def on_tdx_radioButton_clicked(self):
639
659
  if self.tdx_radioButton.isChecked():
640
660
  self.pytdx_radioButton.setChecked(False)
@@ -642,6 +662,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
642
662
  self.use_download = 'tdx'
643
663
  self.on_tdx_or_pytdx_toggled()
644
664
 
665
+ @Slot()
645
666
  def on_qmt_radioButton_clicked(self):
646
667
  if self.qmt_radioButton.isChecked():
647
668
  self.tdx_radioButton.setChecked(False)
@@ -675,7 +696,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
675
696
  self.time_start_dateEdit.setEnabled(False)
676
697
  self.use_tdx_number_spinBox.setEnabled(False)
677
698
 
678
- @pyqtSlot()
699
+ @Slot()
679
700
  def on_select_tdx_dir_pushButton_clicked(self):
680
701
  dlg = QFileDialog()
681
702
  dlg.setFileMode(QFileDialog.Directory)
@@ -685,7 +706,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
685
706
  dirname = dlg.selectedFiles()
686
707
  self.tdx_dir_lineEdit.setText(dirname[0])
687
708
 
688
- @pyqtSlot()
709
+ @Slot()
689
710
  def on_hdf5_dir_pushButton_clicked(self):
690
711
  dlg = QFileDialog()
691
712
  dlg.setFileMode(QFileDialog.Directory)
@@ -695,21 +716,21 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
695
716
  dirname = dlg.selectedFiles()
696
717
  self.hdf5_dir_lineEdit.setText(dirname[0])
697
718
 
698
- @pyqtSlot()
719
+ @Slot()
699
720
  def on_enable_hdf55_radioButton_clicked(self):
700
721
  if self.enable_hdf55_radioButton.isChecked():
701
722
  self.enable_mysql_radioButton.setChecked(False)
702
723
  self.enable_clickhouse_radioButton.setChecked(False)
703
724
  self.on_enable_database_toggled(hdf5=True, mysql=False, clickhouse=False)
704
725
 
705
- @pyqtSlot()
726
+ @Slot()
706
727
  def on_enable_mysql_radioButton_clicked(self):
707
728
  if self.enable_mysql_radioButton.isChecked():
708
729
  self.enable_hdf55_radioButton.setChecked(False)
709
730
  self.enable_clickhouse_radioButton.setChecked(False)
710
731
  self.on_enable_database_toggled(hdf5=False, mysql=True, clickhouse=False)
711
732
 
712
- @pyqtSlot()
733
+ @Slot()
713
734
  def on_enable_clickhouse_radioButton_clicked(self):
714
735
  if self.enable_clickhouse_radioButton.isChecked():
715
736
  self.enable_hdf55_radioButton.setChecked(False)
@@ -732,7 +753,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
732
753
  self.clickhouse_test_pushButton.setEnabled(clickhouse)
733
754
  self.clickhouse_tmpdir_pushButton.setEnabled(clickhouse)
734
755
 
735
- @pyqtSlot()
756
+ @Slot()
736
757
  def on_mysql_tmpdir_pushButton_clicked(self):
737
758
  dlg = QFileDialog()
738
759
  dlg.setFileMode(QFileDialog.Directory)
@@ -742,7 +763,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
742
763
  dirname = dlg.selectedFiles()
743
764
  self.mysql_tmpdir_lineEdit.setText(dirname[0])
744
765
 
745
- @pyqtSlot()
766
+ @Slot()
746
767
  def on_clickhouse_tmpdir_pushButton_clicked(self):
747
768
  if not is_valid_license():
748
769
  QMessageBox.critical(self, "clickhouse引擎", "需要捐赠授权才能使用clickhouse引擎")
@@ -756,7 +777,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
756
777
  dirname = dlg.selectedFiles()
757
778
  self.clickhouse_tmpdir_lineEdit.setText(dirname[0])
758
779
 
759
- @pyqtSlot()
780
+ @Slot()
760
781
  def on_mysql_test_pushButton_clicked(self):
761
782
  """测试数据库连接"""
762
783
  db_config = {
@@ -780,7 +801,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
780
801
 
781
802
  QMessageBox.about(self, "测试数据库连接", " 连接成功!")
782
803
 
783
- @pyqtSlot()
804
+ @Slot()
784
805
  def on_clickhouse_test_pushButton_clicked(self):
785
806
  """测试数据库连接"""
786
807
  db_config = {
@@ -821,7 +842,8 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
821
842
  if msg_name == 'ESCAPE_TIME':
822
843
  self.escape_time = msg_task_name
823
844
  self.import_status_label.setText(
824
- "耗时:{:>.2f} 秒 ({:>.2f}分钟) {}".format(self.escape_time, self.escape_time / 60, datetime.datetime.now())
845
+ "耗时:{:>.2f} 秒 ({:>.2f}分钟) {}".format(
846
+ self.escape_time, self.escape_time / 60, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
825
847
  )
826
848
 
827
849
  elif msg_name == 'HDF5_IMPORT':
@@ -846,6 +868,17 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
846
868
  "Hikyuu 新版本 ({}) 已发布,建议更新".format(get_last_version()))
847
869
  self.import_detail_textEdit.append("更新命令: pip instal hikyuu --upgrade")
848
870
  self.import_detail_textEdit.append("========================================================")
871
+ if is_valid_license():
872
+ expire_date = get_expire_date()
873
+ if expire_date != Datetime.min():
874
+ delta = expire_date - Datetime.now()
875
+ if delta < TimeDelta(3):
876
+ self.import_detail_textEdit.append(
877
+ "========================================================")
878
+ self.import_detail_textEdit.append(
879
+ "您的授权即将到期,截止日期:{}!".format(expire_date))
880
+ self.import_detail_textEdit.append(
881
+ "========================================================")
849
882
  self.import_running = False
850
883
 
851
884
  elif msg_task_name == 'IMPORT_KDATA':
@@ -890,7 +923,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
890
923
  if msg[2] != 'FINISHED':
891
924
  self.import_detail_textEdit.append(msg[2])
892
925
 
893
- @pyqtSlot()
926
+ @Slot()
894
927
  def on_start_import_pushButton_clicked(self):
895
928
  try:
896
929
  self.saveConfig()
@@ -965,7 +998,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
965
998
  self.escape_time_thread.message.connect(self.on_message_from_thread)
966
999
  self.escape_time_thread.start()
967
1000
 
968
- @pyqtSlot()
1001
+ @Slot()
969
1002
  def on_sched_import_pushButton_clicked(self):
970
1003
  self.sched_import_pushButton.setEnabled(False)
971
1004
  if self._is_sched_import_running:
@@ -993,7 +1026,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
993
1026
  self.sched_import_pushButton.setText("停止定时导入")
994
1027
  self.sched_import_pushButton.setEnabled(True)
995
1028
 
996
- @pyqtSlot()
1029
+ @Slot()
997
1030
  def on_collect_start_pushButton_clicked(self):
998
1031
  if self._is_collect_running:
999
1032
  if self.collect_spot_thread is not None and self.collect_spot_thread.isRunning():
@@ -1033,6 +1066,41 @@ def start():
1033
1066
  sys.exit(app.exec())
1034
1067
 
1035
1068
 
1069
+ def is_font_installed(font_name):
1070
+ """检查字体是否安装"""
1071
+ if sys.platform == "win32":
1072
+ try:
1073
+ import winreg
1074
+ # 打开注册表中的字体项
1075
+ key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts")
1076
+ i = 0
1077
+ while True:
1078
+ try:
1079
+ name, value, _ = winreg.EnumValue(key, i)
1080
+ if font_name in name:
1081
+ winreg.CloseKey(key)
1082
+ return True
1083
+ i += 1
1084
+ except WindowsError:
1085
+ break
1086
+ winreg.CloseKey(key)
1087
+ except:
1088
+ # 如果注册表检查失败,则尝试创建字体对象
1089
+ try:
1090
+ f = QFont(font_name)
1091
+ return f.exactMatch()
1092
+ except:
1093
+ pass
1094
+ return False
1095
+ else:
1096
+ # 非Windows系统简单检查
1097
+ try:
1098
+ f = QFont(font_name)
1099
+ return f.exactMatch()
1100
+ except:
1101
+ return False
1102
+
1103
+
1036
1104
  if __name__ == "__main__":
1037
1105
  import requests
1038
1106
  import urllib
@@ -1040,14 +1108,13 @@ if __name__ == "__main__":
1040
1108
  logging.getLogger("urllib3").setLevel(logging.WARNING)
1041
1109
  logging.getLogger("pytdx").setLevel(logging.WARNING)
1042
1110
 
1043
- # 自适应分辨率,防止字体显示不全
1044
- QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
1045
- QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
1046
-
1047
1111
  app = QApplication(sys.argv)
1048
- f = QFont('SimSun')
1049
- f.setPixelSize(12)
1050
- app.setFont(f)
1112
+ if sys.platform == 'win32':
1113
+ # 检查Microsoft YaHei字体是否存在
1114
+ if is_font_installed('Microsoft YaHei'):
1115
+ f = QFont('Microsoft YaHei')
1116
+ f.setPixelSize(12)
1117
+ app.setFont(f)
1051
1118
 
1052
1119
  if (len(sys.argv) > 1 and sys.argv[1] == '0'):
1053
1120
  FORMAT = '%(asctime)-15s [%(levelname)s]: %(message)s [%(name)s::%(funcName)s]'
@@ -1058,5 +1125,6 @@ if __name__ == "__main__":
1058
1125
  else:
1059
1126
  myWin = MyMainWindow(capture_output=True)
1060
1127
 
1128
+ myWin.resize(1100, 400)
1061
1129
  myWin.show()
1062
1130
  sys.exit(app.exec())
@@ -6,7 +6,7 @@ import logging
6
6
  import time
7
7
  import datetime
8
8
  from math import ceil
9
- from PyQt5.QtCore import QThread, QWaitCondition, QMutex
9
+ from PySide6.QtCore import QThread, QWaitCondition, QMutex
10
10
 
11
11
  from hikyuu.util import *
12
12
  from hikyuu.gui.spot_server import collect, release_nng_senders
@@ -3,10 +3,10 @@
3
3
  # cp936
4
4
 
5
5
  import time
6
- from PyQt5.QtCore import QThread, pyqtSignal
6
+ from PySide6.QtCore import QThread, Signal
7
7
 
8
8
  class EscapetimeThread(QThread):
9
- message = pyqtSignal(list)
9
+ message = Signal(list)
10
10
 
11
11
  def __init__(self):
12
12
  super(self.__class__, self).__init__()
@@ -14,19 +14,13 @@ class EscapetimeThread(QThread):
14
14
  self.msg_name = 'ESCAPE_TIME'
15
15
  self.init_time = time.time()
16
16
 
17
- def __del__(self):
18
- self.working = False
19
- #print("EscapetimeThread", "__del__", time.time() - self.init_time)
20
- self.wait()
21
-
22
- def send_message(self, msg):
23
- self.message.emit([self.msg_name] + msg)
17
+ def run(self):
18
+ while self.working:
19
+ time.sleep(1)
20
+ current_time = time.time()
21
+ self.message.emit([self.msg_name, round(current_time - self.init_time, 1)])
24
22
 
25
23
  def stop(self):
26
24
  self.working = False
25
+ self.quit()
27
26
  self.wait()
28
-
29
- def run(self):
30
- while self.working:
31
- self.msleep(10)
32
- self.send_message([(time.time() - self.init_time),])
@@ -6,7 +6,6 @@
6
6
 
7
7
  import sqlite3
8
8
  import mysql.connector
9
- from hikyuu.data.common import MARKET, get_stk_code_name_list
10
9
  from hikyuu.data.em_block_to_mysql import em_import_block_to_mysql
11
10
  from hikyuu.data.em_block_to_sqlite import em_import_block_to_sqlite
12
11
  from hikyuu.data.em_block_to_clickhouse import em_import_block_to_clickhouse
@@ -14,11 +13,10 @@ from hikyuu.util import *
14
13
 
15
14
 
16
15
  class ImportBlockInfoTask:
17
- def __init__(self, log_queue, queue, config, categorys):
16
+ def __init__(self, log_queue, queue, config):
18
17
  self.log_queue = log_queue
19
18
  self.queue = queue
20
19
  self.config = config
21
- self.categorys = categorys
22
20
  self.task_name = 'IMPORT_BLOCKINFO'
23
21
  self.status = "no run"
24
22
 
@@ -52,16 +50,11 @@ class ImportBlockInfoTask:
52
50
 
53
51
  count = 0
54
52
  try:
55
- code_market_dict = {}
56
- for market in (MARKET.SH, MARKET.SZ, MARKET.BJ):
57
- x = get_stk_code_name_list(market)
58
- for v in x:
59
- code_market_dict[v["code"]] = market
60
- count = import_block(connect, code_market_dict, self.categorys)
53
+ count = import_block(connect)
61
54
  except Exception as e:
62
55
  hku_error(str(e))
63
56
 
64
57
  connect.close()
65
58
 
66
- self.queue.put([self.task_name, "BLOCKINFO", f"{self.categorys}板块信息下载完毕: {count}", None, None])
59
+ self.queue.put([self.task_name, "BLOCKINFO", f"板块信息更新完毕: {count}", None, None])
67
60
  self.status = "finished"