hikyuu 2.5.3__py3-none-win_amd64.whl → 2.5.6__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 (61) hide show
  1. hikyuu/__init__.pyi +514 -514
  2. hikyuu/analysis/__init__.pyi +490 -489
  3. hikyuu/analysis/analysis.pyi +491 -490
  4. hikyuu/core.pyi +492 -491
  5. hikyuu/cpp/__init__.pyi +2 -2
  6. hikyuu/cpp/core310.pyd +0 -0
  7. hikyuu/cpp/core310.pyi +21 -2
  8. hikyuu/cpp/core311.pyd +0 -0
  9. hikyuu/cpp/core311.pyi +21 -2
  10. hikyuu/cpp/core312.pyd +0 -0
  11. hikyuu/cpp/core312.pyi +21 -2
  12. hikyuu/cpp/core313.pyd +0 -0
  13. hikyuu/cpp/core313.pyi +21 -2
  14. hikyuu/cpp/core38.pyd +0 -0
  15. hikyuu/cpp/core38.pyi +21 -2
  16. hikyuu/cpp/core39.pyd +0 -0
  17. hikyuu/cpp/core39.pyi +21 -2
  18. hikyuu/cpp/hikyuu.dll +0 -0
  19. hikyuu/cpp/hikyuu.lib +0 -0
  20. hikyuu/cpp/sqlite3.dll +0 -0
  21. hikyuu/data/tdx_to_mysql.py +15 -15
  22. hikyuu/draw/__init__.pyi +1 -1
  23. hikyuu/draw/drawplot/__init__.pyi +9 -9
  24. hikyuu/draw/drawplot/bokeh_draw.pyi +505 -505
  25. hikyuu/draw/drawplot/common.pyi +1 -1
  26. hikyuu/draw/drawplot/echarts_draw.pyi +507 -507
  27. hikyuu/draw/drawplot/matplotlib_draw.pyi +516 -516
  28. hikyuu/draw/elder.pyi +11 -11
  29. hikyuu/draw/kaufman.pyi +18 -18
  30. hikyuu/draw/volume.pyi +10 -10
  31. hikyuu/extend.pyi +500 -500
  32. hikyuu/fetcher/stock/zh_block_em.py +18 -7
  33. hikyuu/gui/data/UseTdxImportToH5Thread.py +2 -2
  34. hikyuu/hub.py +7 -13
  35. hikyuu/hub.pyi +9 -6
  36. hikyuu/include/hikyuu/indicator/crt/BARSSINCE.h +14 -2
  37. hikyuu/include/hikyuu/indicator/imp/IBarsSince.h +6 -0
  38. hikyuu/include/hikyuu/utilities/config.h +1 -1
  39. hikyuu/include/hikyuu/utilities/datetime/Datetime.h +4 -3
  40. hikyuu/include/hikyuu/utilities/datetime/TimeDelta.h +8 -0
  41. hikyuu/include/hikyuu/utilities/plugin/PluginBase.h +47 -0
  42. hikyuu/include/hikyuu/utilities/plugin/PluginClient.h +55 -0
  43. hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +64 -0
  44. hikyuu/include/hikyuu/utilities/plugin/__init__.py +1 -0
  45. hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +1 -1
  46. hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +1 -1
  47. hikyuu/include/hikyuu/utilities/thread/StealThreadPool.h +1 -1
  48. hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +1 -1
  49. hikyuu/include/hikyuu/version.h +4 -4
  50. hikyuu/indicator/indicator.py +1 -1
  51. hikyuu/trade_manage/__init__.pyi +505 -505
  52. hikyuu/trade_manage/broker.pyi +3 -3
  53. hikyuu/trade_manage/broker_easytrader.pyi +1 -1
  54. hikyuu/trade_manage/trade.pyi +505 -505
  55. hikyuu/util/singleton.pyi +1 -1
  56. {hikyuu-2.5.3.dist-info → hikyuu-2.5.6.dist-info}/METADATA +1 -1
  57. {hikyuu-2.5.3.dist-info → hikyuu-2.5.6.dist-info}/RECORD +61 -57
  58. {hikyuu-2.5.3.dist-info → hikyuu-2.5.6.dist-info}/top_level.txt +1 -0
  59. {hikyuu-2.5.3.dist-info → hikyuu-2.5.6.dist-info}/LICENSE +0 -0
  60. {hikyuu-2.5.3.dist-info → hikyuu-2.5.6.dist-info}/WHEEL +0 -0
  61. {hikyuu-2.5.3.dist-info → hikyuu-2.5.6.dist-info}/entry_points.txt +0 -0
@@ -10,6 +10,8 @@ import akshare as ak
10
10
  import pandas as pd
11
11
  from hikyuu.util import *
12
12
 
13
+ em_num_per_page = 100
14
+
13
15
 
14
16
  @hku_catch(ret=[], trace=True)
15
17
  def get_hybk_names():
@@ -17,7 +19,7 @@ def get_hybk_names():
17
19
  url = "https://19.push2.eastmoney.com/api/qt/clist/get"
18
20
  params = {
19
21
  "pn": "1",
20
- "pz": "200",
22
+ "pz": str(em_num_per_page),
21
23
  "po": "1",
22
24
  "np": "1",
23
25
  "ut": "bd1d9ddb04089700cf9c27f6f7426281",
@@ -31,6 +33,15 @@ def get_hybk_names():
31
33
  r = requests.get(url, params=params, timeout=15)
32
34
  data_json = r.json()
33
35
  ret = [(v['f12'], v['f14']) for v in data_json["data"]["diff"]]
36
+ total_page = math.ceil(data_json["data"]["total"] / em_num_per_page)
37
+ for page in range(2, total_page + 1):
38
+ params["pn"] = page
39
+ r = requests.get(url, params=params, timeout=15)
40
+ data_json = r.json()
41
+ if data_json["data"] is None:
42
+ continue
43
+ tmp = [(v['f12'], v['f14']) for v in data_json["data"]["diff"]]
44
+ ret.extend(tmp)
34
45
  return ret
35
46
 
36
47
 
@@ -40,7 +51,7 @@ def get_hybk_cons_code(blk_code):
40
51
  url = "http://30.push2.eastmoney.com/api/qt/clist/get"
41
52
  params = {
42
53
  "pn": "1",
43
- "pz": "200",
54
+ "pz": str(em_num_per_page),
44
55
  "po": "1",
45
56
  "np": "1",
46
57
  "ut": "bd1d9ddb04089700cf9c27f6f7426281",
@@ -54,7 +65,7 @@ def get_hybk_cons_code(blk_code):
54
65
  r = requests.get(url, params=params, timeout=15)
55
66
  data_json = r.json()
56
67
  ret = [v['f12'] for v in data_json["data"]["diff"]]
57
- total_page = math.ceil(data_json["data"]["total"] / 200)
68
+ total_page = math.ceil(data_json["data"]["total"] / em_num_per_page)
58
69
  for page in range(2, total_page + 1):
59
70
  params["pn"] = page
60
71
  r = requests.get(url, params=params, timeout=15)
@@ -99,7 +110,7 @@ def get_dybk_names():
99
110
  url = "http://13.push2.eastmoney.com/api/qt/clist/get"
100
111
  params = {
101
112
  "pn": "1",
102
- "pz": "200",
113
+ "pz": str(em_num_per_page),
103
114
  "po": "1",
104
115
  "np": "1",
105
116
  "ut": "bd1d9ddb04089700cf9c27f6f7426281",
@@ -115,7 +126,7 @@ def get_dybk_names():
115
126
  hku_check(data_json['data'] is not None, "获取地域板块名称列表失败!")
116
127
  ret = [(v["f12"], v["f14"]) for v in data_json["data"]["diff"]]
117
128
 
118
- total_page = math.ceil(data_json["data"]["total"] / 200)
129
+ total_page = math.ceil(data_json["data"]["total"] / em_num_per_page)
119
130
  for page in range(2, total_page + 1):
120
131
  params["pn"] = page
121
132
  r = requests.get(url, params=params, timeout=15)
@@ -133,7 +144,7 @@ def get_all_dybk_info(code_market_dict, sep=""):
133
144
  url = "http://13.push2.eastmoney.com/api/qt/clist/get"
134
145
  params = {
135
146
  "pn": "1",
136
- "pz": "200",
147
+ "pz": str(em_num_per_page),
137
148
  "po": "1",
138
149
  "np": "1",
139
150
  "ut": "bd1d9ddb04089700cf9c27f6f7426281",
@@ -160,7 +171,7 @@ def get_all_dybk_info(code_market_dict, sep=""):
160
171
  ret[blk_name] = [
161
172
  f"{code_market_dict[v['f12']]}{sep}{v['f12']}" for v in stk_json if v['f12'] in code_market_dict]
162
173
 
163
- total_page = math.ceil(data["data"]["total"] / 200)
174
+ total_page = math.ceil(data["data"]["total"] / em_num_per_page)
164
175
  for page in range(2, total_page + 1):
165
176
  params["pn"] = page
166
177
  r = requests.get(url, params=params, timeout=15)
@@ -145,8 +145,8 @@ class UseTdxImportToH5Thread(QThread):
145
145
  connect = sqlite3.connect(dest_dir + "/stock.db")
146
146
  create_database(connect)
147
147
 
148
- tdx_import_stock_name_from_file(connect, src_dir + "\\T0002\\hq_cache\\shm.tnf", 'SH', self.quotations)
149
- tdx_import_stock_name_from_file(connect, src_dir + "\\T0002\\hq_cache\\szm.tnf", 'SZ', self.quotations)
148
+ tdx_import_stock_name_from_file(connect, src_dir + "/T0002/hq_cache/shm.tnf", 'SH', self.quotations)
149
+ tdx_import_stock_name_from_file(connect, src_dir + "/T0002/hq_cache/szm.tnf", 'SZ', self.quotations)
150
150
 
151
151
  self.send_message(['FINISHED_IMPORT_CODE'])
152
152
 
hikyuu/hub.py CHANGED
@@ -344,6 +344,10 @@ class HubManager(metaclass=SingletonType):
344
344
  self._session.query(PartModel).filter_by(hub_name=name).delete()
345
345
  self._session.query(HubModel).filter_by(name=name).delete()
346
346
 
347
+ @lru_cache
348
+ def _get_module(self, module_name):
349
+ return importlib.import_module(module_name)
350
+
347
351
  @dbsession
348
352
  def import_part_to_db(self, hub_model):
349
353
  part_dict = {
@@ -387,7 +391,8 @@ class HubManager(metaclass=SingletonType):
387
391
 
388
392
  # 导入模块
389
393
  try:
390
- part_module = importlib.import_module(module_name)
394
+ # part_module = importlib.import_module(module_name)
395
+ part_module = self._get_module(module_name)
391
396
  except ModuleNotFoundError:
392
397
  self.logger.error('{} 缺失 part.py 文件, 位置:"{}"!'.format(module_name, entry.path))
393
398
  continue
@@ -645,18 +650,7 @@ def get_part(name, *args, **kwargs):
645
650
  :param args: 其他部件相关参数
646
651
  :param kwargs: 其他部件相关参数
647
652
  """
648
- @lru_cache
649
- def _get_part(name, *args, **kwargs):
650
- return HubManager().get_part(name, *args, **kwargs)
651
-
652
- try:
653
- return _get_part(name, *args, **kwargs)
654
- except TypeError as e:
655
- if "unhashable type" in str(e):
656
- hku_info("{}! 该对象不可hash无法缓存, 可考虑优化", str(e))
657
- return HubManager().get_part(name, *args, **kwargs)
658
- else:
659
- raise e
653
+ return HubManager().get_part(name, *args, **kwargs)
660
654
 
661
655
 
662
656
  def get_part_list(name_list):
hikyuu/hub.pyi CHANGED
@@ -28,11 +28,11 @@ import sys as sys
28
28
  import typing
29
29
  __all__: list = ['add_remote_hub', 'add_local_hub', 'update_hub', 'remove_hub', 'build_hub', 'help_part', 'get_part', 'get_part_list', 'get_hub_path', 'get_part_info', 'get_part_module', 'print_part_info', 'get_hub_name_list', 'get_part_name_list', 'get_current_hub', 'search_part']
30
30
  class ConfigModel(sqlalchemy.orm.decl_api.Base):
31
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x26f9bde2d90; ConfigModel>
31
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x1b27916c590; ConfigModel>
32
32
  __table__: typing.ClassVar[sqlalchemy.sql.schema.Table] # value = Table('hub_config', MetaData(), Column('id', Integer(), table=<hub_config>, primary_key=True, nullable=False, default=Sequence('config_id_seq', metadata=MetaData())), Column('key', String(), table=<hub_config>), Column('value', String(), table=<hub_config>), schema=None)
33
33
  __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('key', String(), table=<hub_config>)))
34
34
  __tablename__: typing.ClassVar[str] = 'hub_config'
35
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.ConfigModel'> at 26f9bdf0950>
35
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.ConfigModel'> at 1b279530550>
36
36
  def __init__(self, **kwargs):
37
37
  """
38
38
  A simple constructor that allows initialization from kwargs.
@@ -55,6 +55,9 @@ class HubManager:
55
55
  """
56
56
  _instance: typing.ClassVar[HubManager] # value = <hikyuu.hub.HubManager object>
57
57
  @staticmethod
58
+ def _get_module(*args, **kwargs):
59
+ ...
60
+ @staticmethod
58
61
  def add_local_hub(*args, **kwargs):
59
62
  ...
60
63
  @staticmethod
@@ -106,11 +109,11 @@ class HubManager:
106
109
  def print_part_info(self, name):
107
110
  ...
108
111
  class HubModel(sqlalchemy.orm.decl_api.Base):
109
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x26f9be26430; HubModel>
112
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x1b27951e630; HubModel>
110
113
  __table__: typing.ClassVar[sqlalchemy.sql.schema.Table] # value = Table('hub_repo', MetaData(), Column('id', Integer(), table=<hub_repo>, primary_key=True, nullable=False, default=Sequence('remote_id_seq', metadata=MetaData())), Column('name', String(), table=<hub_repo>), Column('hub_type', String(), table=<hub_repo>), Column('local_base', String(), table=<hub_repo>), Column('local', String(), table=<hub_repo>), Column('url', String(), table=<hub_repo>), Column('branch', String(), table=<hub_repo>), schema=None)
111
114
  __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('name', String(), table=<hub_repo>)))
112
115
  __tablename__: typing.ClassVar[str] = 'hub_repo'
113
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.HubModel'> at 26f9be1e720>
116
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.HubModel'> at 1b279548e60>
114
117
  def __init__(self, **kwargs):
115
118
  """
116
119
  A simple constructor that allows initialization from kwargs.
@@ -143,11 +146,11 @@ class ModuleConflictError(Exception):
143
146
  def __str__(self):
144
147
  ...
145
148
  class PartModel(sqlalchemy.orm.decl_api.Base):
146
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x26f9be26dc0; PartModel>
149
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x1b27951f020; PartModel>
147
150
  __table__: typing.ClassVar[sqlalchemy.sql.schema.Table] # value = Table('hub_part', MetaData(), Column('id', Integer(), table=<hub_part>, primary_key=True, nullable=False, default=Sequence('part_id_seq', metadata=MetaData())), Column('hub_name', String(), table=<hub_part>), Column('part', String(), table=<hub_part>), Column('name', String(), table=<hub_part>), Column('author', String(), table=<hub_part>), Column('version', String(), table=<hub_part>), Column('doc', String(), table=<hub_part>), Column('module_name', String(), table=<hub_part>), Column('label', String(), table=<hub_part>), schema=None)
148
151
  __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('name', String(), table=<hub_part>)))
149
152
  __tablename__: typing.ClassVar[str] = 'hub_part'
150
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.PartModel'> at 26f9be2c220>
153
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.PartModel'> at 1b2795499f0>
151
154
  def __init__(self, **kwargs):
152
155
  """
153
156
  A simple constructor that allows initialization from kwargs.
@@ -25,8 +25,6 @@ namespace hku {
25
25
  * @ingroup Indicator
26
26
  */
27
27
  Indicator HKU_API BARSSINCE();
28
- Indicator BARSSINCE(Indicator::value_t);
29
- Indicator BARSSINCE(const Indicator& ind);
30
28
 
31
29
  inline Indicator BARSSINCE(const Indicator& ind) {
32
30
  return BARSSINCE()(ind);
@@ -36,6 +34,20 @@ inline Indicator BARSSINCE(Indicator::value_t val) {
36
34
  return BARSSINCE(CVAL(val));
37
35
  }
38
36
 
37
+ /**
38
+ * N周期内首个条件成立位置
39
+ * @details N周期内第一个条件成立到当前的周期数
40
+ * <pre>
41
+ * 用法:BARSSINCEN(X,N):N周期内第一次X不为0到现在的周期数,N为常量BARSSINCEN(X,N):
42
+ * 例如:BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数
43
+ * </pre>
44
+ * @ingroup Indicator
45
+ */
46
+ Indicator HKU_API BARSSINCEN(int n);
47
+ inline Indicator BARSSINCEN(const Indicator& ind, int n) {
48
+ return BARSSINCEN(n)(ind);
49
+ }
50
+
39
51
  } // namespace hku
40
52
 
41
53
  #endif /* INDICATOR_CRT_BARSSINCE_H_ */
@@ -15,6 +15,11 @@
15
15
 
16
16
  namespace hku {
17
17
 
18
+ /*
19
+ * N周期内首个条件成立位置, N为0时,为整个序列
20
+ * 用法:BARSSINCEN(X,N):N周期内第一次X不为0到现在的周期数,N为常量BARSSINCEN(X,N):
21
+ * 例如:BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数
22
+ */
18
23
  class IBarsSince : public IndicatorImp {
19
24
  INDICATOR_IMP(IBarsSince)
20
25
  INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION
@@ -22,6 +27,7 @@ class IBarsSince : public IndicatorImp {
22
27
  public:
23
28
  IBarsSince();
24
29
  virtual ~IBarsSince();
30
+ virtual void _checkParam(const string& name) const override;
25
31
  };
26
32
 
27
33
  } /* namespace hku */
@@ -26,7 +26,7 @@
26
26
  #define HKU_CLOSE_SPEND_TIME 0
27
27
 
28
28
  #define HKU_USE_SPDLOG_ASYNC_LOGGER 0
29
- #define HKU_LOG_ACTIVE_LEVEL "2"
29
+ #define HKU_LOG_ACTIVE_LEVEL 2
30
30
 
31
31
  #define HKU_ENABLE_MO 0
32
32
 
@@ -298,9 +298,10 @@ HKU_UTILS_API std::ostream &operator<<(std::ostream &, const Datetime &);
298
298
  typedef std::vector<Datetime> DatetimeList;
299
299
 
300
300
  /**
301
- * 获取指定范围的日历日期列表[start, end),仅仅是日,不含时分秒
301
+ * 获取指定范围的日历日期列表[start,end),仅仅是日,不含时分秒。
302
+ * @note 如果指定的结束日期过大,可能会耗费大量内存
302
303
  * @param start 起始日期
303
- * @param end 结束日期
304
+ * @param end 结束日期, 如果为空,将使用 Datetime::max
304
305
  * @return [start, end)范围内的日历日期
305
306
  */
306
307
  DatetimeList HKU_UTILS_API getDateRange(const Datetime &start, const Datetime &end);
@@ -411,7 +412,7 @@ template <>
411
412
  class hash<hku::Datetime> {
412
413
  public:
413
414
  size_t operator()(hku::Datetime const &d) const noexcept {
414
- return d.ticks(); // or use boost::hash_combine
415
+ return std::hash<uint64_t>()(d.ticks());
415
416
  }
416
417
  };
417
418
 
@@ -320,6 +320,14 @@ inline TimeDelta Microseconds(int64_t microsecs) {
320
320
 
321
321
  namespace std {
322
322
 
323
+ template <>
324
+ class hash<hku::TimeDelta> {
325
+ public:
326
+ size_t operator()(hku::TimeDelta const &d) const noexcept {
327
+ return std::hash<int64_t>()(d.ticks());
328
+ }
329
+ };
330
+
323
331
  inline string to_string(const hku::TimeDelta &delta) {
324
332
  return delta.str();
325
333
  }
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Copyright (c) 2025 hikyuu.org
3
+ *
4
+ * Created on: 2025-03-18
5
+ * Author: fasiondog
6
+ */
7
+
8
+ #pragma once
9
+ #ifndef HKU_UTILS_PLUGIN_BASE_H_
10
+ #define HKU_UTILS_PLUGIN_BASE_H_
11
+
12
+ #include <string>
13
+ #include "hikyuu/utilities/config.h"
14
+ #include "hikyuu/utilities/osdef.h"
15
+
16
+ namespace hku {
17
+
18
+ class PluginBase {
19
+ public:
20
+ PluginBase() = default;
21
+ virtual ~PluginBase() = default;
22
+
23
+ /**
24
+ * @brief 返回插件信息
25
+ * @details
26
+ * 插件信息为json格式,包含name(string)、version(int)、description(string)、author(string)字段
27
+ * 如:{"name":"unknown","version": 1.0,"description":"","author":"unknown"}
28
+ * @return std::string
29
+ */
30
+ virtual std::string info() const noexcept = 0;
31
+ };
32
+
33
+ } // namespace hku
34
+
35
+ #if HKU_OS_WINDOWS
36
+ #define HKU_PLUGIN_DEFINE(plugin) \
37
+ extern "C" __declspec(dllexport) hku::PluginBase* createPlugin() { \
38
+ return new plugin(); \
39
+ }
40
+ #else
41
+ #define HKU_PLUGIN_DEFINE(plugin) \
42
+ extern "C" hku::PluginBase* createPlugin() { \
43
+ return new plugin(); \
44
+ }
45
+ #endif
46
+
47
+ #endif /* HKU_UTILS_PLUGIN_BASE_H_ */
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (c) 2025 hikyuu.org
3
+ *
4
+ * Created on: 2025-04-06
5
+ * Author: fasiondog
6
+ */
7
+
8
+ #pragma once
9
+
10
+ #include "PluginLoader.h"
11
+
12
+ namespace hku {
13
+
14
+ template <typename InterfaceT>
15
+ class PluginClient : public InterfaceT {
16
+ public:
17
+ PluginClient() = delete;
18
+ PluginClient(const std::string &path, const std::string &filename) {
19
+ m_loader = std::make_unique<PluginLoader>(path);
20
+ m_loader->load(filename);
21
+ m_impl = m_loader->instance<InterfaceT>();
22
+ }
23
+ virtual ~PluginClient() = default;
24
+
25
+ PluginClient(const PluginClient &) = delete;
26
+ PluginClient &operator=(const PluginClient &) = delete;
27
+
28
+ PluginClient(PluginClient &&rhs) : m_impl(rhs.m_impl), m_loader(std::move(rhs.m_loader)) {
29
+ rhs.m_impl = nullptr;
30
+ }
31
+
32
+ PluginClient &operator=(PluginClient &&rhs) {
33
+ if (this != &rhs) {
34
+ m_loader = std::move(rhs.m_loader);
35
+ m_impl = rhs.m_impl;
36
+ rhs.m_impl = nullptr;
37
+ }
38
+ }
39
+
40
+ std::string info() const noexcept override {
41
+ return m_impl->info();
42
+ }
43
+
44
+ InterfaceT *getPlugin() const {
45
+ return m_impl;
46
+ }
47
+
48
+ protected:
49
+ InterfaceT *m_impl;
50
+
51
+ protected:
52
+ std::unique_ptr<PluginLoader> m_loader;
53
+ };
54
+
55
+ } // namespace hku
@@ -0,0 +1,64 @@
1
+ /*
2
+ * Copyright (c) 2025 hikyuu.org
3
+ *
4
+ * Created on: 2025-03-18
5
+ * Author: fasiondog
6
+ */
7
+
8
+ #pragma once
9
+ #ifndef HKU_UTILS_PLUGIN_LOADER_H_
10
+ #define HKU_UTILS_PLUGIN_LOADER_H_
11
+
12
+ #include <mutex>
13
+ #include <string>
14
+ #include <memory>
15
+ #include "hikyuu/utilities/config.h"
16
+ #include "hikyuu/utilities/osdef.h"
17
+ #include "hikyuu/utilities/Log.h"
18
+ #include "PluginBase.h"
19
+
20
+ #if HKU_OS_WINDOWS
21
+ #include <windows.h>
22
+ #endif
23
+
24
+ #ifndef HKU_UTILS_API
25
+ #define HKU_UTILS_API
26
+ #endif
27
+
28
+ namespace hku {
29
+
30
+ class HKU_UTILS_API PluginLoader final {
31
+ public:
32
+ PluginLoader();
33
+ explicit PluginLoader(const std::string& path);
34
+ PluginLoader(const PluginLoader&) = delete;
35
+ PluginLoader(PluginLoader&&) = delete;
36
+
37
+ ~PluginLoader();
38
+
39
+ bool load(const std::string& pluginname) noexcept;
40
+
41
+ template <typename T>
42
+ T* instance() const noexcept {
43
+ HKU_IF_RETURN(!m_plugin, nullptr);
44
+ return dynamic_cast<T*>(m_plugin.get());
45
+ }
46
+
47
+ private:
48
+ void unload() noexcept;
49
+ void* getFunciton(const char* symbol) noexcept;
50
+ std::string getFileName(const std::string& pluginname) const noexcept;
51
+
52
+ private:
53
+ #if HKU_OS_WINDOWS
54
+ HMODULE m_handle{nullptr};
55
+ #else
56
+ void* m_handle{nullptr};
57
+ #endif
58
+ std::string m_path;
59
+ std::unique_ptr<PluginBase> m_plugin{nullptr};
60
+ };
61
+
62
+ } // namespace hku
63
+
64
+ #endif /* HKU_UTILS_PLUGIN_LOADER_H_ */
@@ -242,7 +242,7 @@ private:
242
242
  std::vector<std::thread> m_threads; // 工作线程
243
243
 
244
244
  // 线程本地变量
245
- #if CPP_STANDARD >= CPP_STANDARD_17
245
+ #if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
246
246
  inline static thread_local MQStealQueue<task_type>* m_local_work_queue =
247
247
  nullptr; // 本地任务队列
248
248
  inline static thread_local int m_index = -1; // 在线程池中的序号
@@ -235,7 +235,7 @@ private:
235
235
  std::vector<std::thread> m_threads; // 工作线程
236
236
 
237
237
  // 线程本地变量
238
- #if CPP_STANDARD >= CPP_STANDARD_17
238
+ #if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
239
239
  inline static thread_local ThreadSafeQueue<task_type>* m_local_work_queue =
240
240
  nullptr; // 本地任务队列
241
241
  inline static thread_local int m_index = -1; // 在线程池中的序号
@@ -239,7 +239,7 @@ private:
239
239
  std::vector<std::thread> m_threads; // 工作线程
240
240
 
241
241
  // 线程本地变量
242
- #if CPP_STANDARD >= CPP_STANDARD_17
242
+ #if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
243
243
  inline static thread_local WorkStealQueue* m_local_work_queue = nullptr; // 本地任务队列
244
244
  inline static thread_local int m_index = -1; // 在线程池中的序号
245
245
  inline static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
@@ -193,7 +193,7 @@ private:
193
193
  std::vector<InterruptFlag*> m_interrupt_flags; // 线程中断标志
194
194
 
195
195
  // 线程本地变量
196
- #if CPP_STANDARD >= CPP_STANDARD_17
196
+ #if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
197
197
  inline static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
198
198
  inline static thread_local int m_index = -1; // 在线程池中的序号
199
199
  #else
@@ -12,13 +12,13 @@
12
12
  #define HKU_VERSION_H
13
13
 
14
14
  // clang-format off
15
- #define HKU_VERSION "2.5.3"
15
+ #define HKU_VERSION "2.5.6"
16
16
  #define HKU_VERSION_MAJOR 2
17
17
  #define HKU_VERSION_MINOR 5
18
- #define HKU_VERSION_ALTER 3
19
- #define HKU_VERSION_BUILD 202503071538
18
+ #define HKU_VERSION_ALTER 6
19
+ #define HKU_VERSION_BUILD 202504131513
20
20
  #define HKU_VERSION_MODE "RELEASE"
21
- #define HKU_VERSION_GIT "2.5.3 release.204e0fc6 (RELEASE)"
21
+ #define HKU_VERSION_GIT "2.5.6 release.2e933ae9 (RELEASE)"
22
22
  // clang-format on
23
23
 
24
24
  #endif /* HKU_VERSION_H */
@@ -90,7 +90,7 @@ def concat_to_df(dates, ind_list, head_stock_code=True, head_ind_name=False):
90
90
  示例:
91
91
  query = Query(-200)
92
92
  k_list = [stk.get_kdata(query) for stk in [sm['sz000001'], sm['sz000002']]]
93
- ma_list = [MA(k) for k in k_list]
93
+ ma_list = [MA(CLOSE(k)) for k in k_list]
94
94
  concat_to_df(sm.get_trading_calendar(query), ma_list, head_stock_code=True, head_ind_name=False)
95
95
 
96
96
  输出: