hikyuu 2.5.1__py3-none-win_amd64.whl → 2.5.3__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 (89) hide show
  1. hikyuu/__init__.py +5 -1
  2. hikyuu/__init__.pyi +522 -505
  3. hikyuu/analysis/__init__.pyi +489 -478
  4. hikyuu/analysis/analysis.pyi +490 -479
  5. hikyuu/core.pyi +491 -480
  6. hikyuu/cpp/__init__.pyi +3 -0
  7. hikyuu/cpp/core310.pyd +0 -0
  8. hikyuu/cpp/core310.pyi +13154 -0
  9. hikyuu/cpp/core311.pyd +0 -0
  10. hikyuu/cpp/core311.pyi +13154 -0
  11. hikyuu/cpp/core312.pyd +0 -0
  12. hikyuu/cpp/core312.pyi +13154 -0
  13. hikyuu/cpp/core313.pyd +0 -0
  14. hikyuu/cpp/core313.pyi +13132 -0
  15. hikyuu/cpp/core38.pyd +0 -0
  16. hikyuu/cpp/core38.pyi +13154 -0
  17. hikyuu/cpp/core39.pyd +0 -0
  18. hikyuu/cpp/core39.pyi +13154 -0
  19. hikyuu/cpp/hikyuu.dll +0 -0
  20. hikyuu/cpp/hikyuu.lib +0 -0
  21. hikyuu/data/mysql_upgrade/0027.sql +6 -0
  22. hikyuu/data/pytdx_to_h5.py +7 -4
  23. hikyuu/data/pytdx_to_mysql.py +7 -4
  24. hikyuu/data/sqlite_upgrade/0027.sql +8 -0
  25. hikyuu/draw/drawplot/__init__.py +8 -1
  26. hikyuu/draw/drawplot/__init__.pyi +11 -7
  27. hikyuu/draw/drawplot/bokeh_draw.pyi +510 -495
  28. hikyuu/draw/drawplot/common.pyi +1 -1
  29. hikyuu/draw/drawplot/echarts_draw.pyi +512 -497
  30. hikyuu/draw/drawplot/matplotlib_draw.py +134 -12
  31. hikyuu/draw/drawplot/matplotlib_draw.pyi +571 -509
  32. hikyuu/draw/elder.pyi +11 -11
  33. hikyuu/draw/kaufman.pyi +18 -18
  34. hikyuu/draw/volume.pyi +10 -10
  35. hikyuu/extend.py +0 -24
  36. hikyuu/extend.pyi +500 -506
  37. hikyuu/hub.py +154 -9
  38. hikyuu/hub.pyi +51 -13
  39. hikyuu/include/hikyuu/DataType.h +1 -2
  40. hikyuu/include/hikyuu/StockManager.h +2 -1
  41. hikyuu/include/hikyuu/StrategyContext.h +12 -3
  42. hikyuu/include/hikyuu/indicator/Indicator.h +24 -0
  43. hikyuu/include/hikyuu/indicator/Indicator2InImp.h +1 -0
  44. hikyuu/include/hikyuu/indicator/build_in.h +2 -0
  45. hikyuu/include/hikyuu/indicator/crt/ATR.h +2 -13
  46. hikyuu/include/hikyuu/indicator/crt/KALMAN.h +30 -0
  47. hikyuu/include/hikyuu/indicator/crt/TR.h +32 -0
  48. hikyuu/include/hikyuu/indicator/imp/IAtr.h +3 -1
  49. hikyuu/include/hikyuu/indicator/imp/IKalman.h +27 -0
  50. hikyuu/include/hikyuu/indicator/imp/ITr.h +35 -0
  51. hikyuu/include/hikyuu/python/convert_any.h +299 -0
  52. hikyuu/include/hikyuu/trade_manage/PositionRecord.h +8 -2
  53. hikyuu/include/hikyuu/trade_sys/allocatefunds/crt/AF_MultiFactor.h +1 -1
  54. hikyuu/include/hikyuu/trade_sys/allocatefunds/imp/MultiFactorAllocaterFunds.h +3 -0
  55. hikyuu/include/hikyuu/trade_sys/condition/ConditionBase.h +4 -1
  56. hikyuu/include/hikyuu/trade_sys/condition/imp/{SubCondition.h → logic/SubCondition.h} +1 -1
  57. hikyuu/include/hikyuu/trade_sys/environment/EnvironmentBase.h +20 -6
  58. hikyuu/include/hikyuu/trade_sys/environment/build_in.h +1 -0
  59. hikyuu/include/hikyuu/trade_sys/environment/crt/EV_Logic.h +35 -0
  60. hikyuu/include/hikyuu/trade_sys/environment/imp/logic/AddEnvironment.h +42 -0
  61. hikyuu/include/hikyuu/trade_sys/environment/imp/logic/AndEnvironment.h +42 -0
  62. hikyuu/include/hikyuu/trade_sys/environment/imp/logic/DivEnvironment.h +42 -0
  63. hikyuu/include/hikyuu/trade_sys/environment/imp/logic/MultiEnvironment.h +42 -0
  64. hikyuu/include/hikyuu/trade_sys/environment/imp/logic/OrEnvironment.h +42 -0
  65. hikyuu/include/hikyuu/trade_sys/environment/imp/logic/SubEnvironment.h +42 -0
  66. hikyuu/include/hikyuu/trade_sys/environment/imp/logic/__init__.py +1 -0
  67. hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +0 -4
  68. hikyuu/include/hikyuu/trade_sys/signal/SignalBase.h +1 -7
  69. hikyuu/include/hikyuu/trade_sys/signal/crt/SG_Logic.h +94 -4
  70. hikyuu/include/hikyuu/trade_sys/signal/crt/SG_OneSide.h +10 -0
  71. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/AndSignal.h +19 -0
  72. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorSignal.h +3 -1
  73. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorValueSignal.h +1 -0
  74. hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OrSignal.h +19 -0
  75. hikyuu/include/hikyuu/version.h +4 -4
  76. hikyuu/indicator/indicator.py +1 -0
  77. hikyuu/trade_manage/__init__.pyi +506 -495
  78. hikyuu/trade_manage/broker.pyi +3 -3
  79. hikyuu/trade_manage/broker_easytrader.pyi +1 -1
  80. hikyuu/trade_manage/trade.pyi +506 -495
  81. hikyuu/trade_sys/trade_sys.py +4 -3
  82. hikyuu/util/__init__.pyi +2 -2
  83. hikyuu/util/singleton.pyi +1 -1
  84. {hikyuu-2.5.1.dist-info → hikyuu-2.5.3.dist-info}/METADATA +3 -2
  85. {hikyuu-2.5.1.dist-info → hikyuu-2.5.3.dist-info}/RECORD +89 -65
  86. {hikyuu-2.5.1.dist-info → hikyuu-2.5.3.dist-info}/top_level.txt +1 -0
  87. {hikyuu-2.5.1.dist-info → hikyuu-2.5.3.dist-info}/LICENSE +0 -0
  88. {hikyuu-2.5.1.dist-info → hikyuu-2.5.3.dist-info}/WHEEL +0 -0
  89. {hikyuu-2.5.1.dist-info → hikyuu-2.5.3.dist-info}/entry_points.txt +0 -0
hikyuu/hub.py CHANGED
@@ -11,6 +11,7 @@ from sqlalchemy.orm import sessionmaker, scoped_session, declarative_base
11
11
  from sqlalchemy import (create_engine, Sequence, Column, Integer, String, and_, UniqueConstraint)
12
12
  from hikyuu.util.singleton import SingletonType
13
13
  from hikyuu.util.check import checkif
14
+ from hikyuu.util import hku_info
14
15
  import os
15
16
  import stat
16
17
  import errno
@@ -19,7 +20,9 @@ import shutil
19
20
  import pathlib
20
21
  import logging
21
22
  import importlib
22
- from configparser import ConfigParser
23
+ import inspect
24
+ import sqlalchemy
25
+ from functools import lru_cache
23
26
 
24
27
  # 引入 git 前需设置环境变量,否则某些情况下会报错失败
25
28
  os.environ['GIT_PYTHON_REFRESH'] = 'quiet'
@@ -79,6 +82,10 @@ class PartModel(Base):
79
82
  version = Column(String) # 版本
80
83
  doc = Column(String) # 帮助说明
81
84
  module_name = Column(String) # 实际策略导入模块名
85
+ label = Column(String) # 标签
86
+ __table_args__ = (
87
+ UniqueConstraint('name', name='uq_part_model_name'),
88
+ )
82
89
 
83
90
  def __str__(self):
84
91
  return 'PartModel(id={}, hub_name={}, part={}, name={}, author={}, module_name={})'.format(
@@ -173,6 +180,25 @@ class HubManager(metaclass=SingletonType):
173
180
 
174
181
  # 创建仓库数据库
175
182
  engine = create_engine("sqlite:///{}/.hikyuu/hub.db".format(usr_dir))
183
+
184
+ inspector = sqlalchemy.inspect(engine)
185
+ if inspector.has_table(PartModel.__tablename__):
186
+ columns = inspector.get_columns(PartModel.__tablename__)
187
+ column_exists = any(column['name'] == 'label' for column in columns)
188
+ if not column_exists:
189
+ add_column_sql = sqlalchemy.text(
190
+ f"ALTER TABLE {PartModel.__tablename__} ADD COLUMN label TEXT;")
191
+ with engine.connect() as connection:
192
+ connection.execute(add_column_sql)
193
+
194
+ indexes = inspector.get_indexes(PartModel.__tablename__)
195
+ index_exists = any(index['name'] == "uq_part_model_name" for index in indexes)
196
+ if not index_exists:
197
+ create_index_sql = sqlalchemy.text(
198
+ f"CREATE INDEX uq_part_model_name ON {PartModel.__tablename__} (name);")
199
+ with engine.connect() as connection:
200
+ connection.execute(create_index_sql)
201
+
176
202
  Base.metadata.create_all(engine)
177
203
  self._scoped_Session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
178
204
  self._session = None
@@ -365,8 +391,8 @@ class HubManager(metaclass=SingletonType):
365
391
  except ModuleNotFoundError:
366
392
  self.logger.error('{} 缺失 part.py 文件, 位置:"{}"!'.format(module_name, entry.path))
367
393
  continue
368
- except:
369
- self.logger.error('{} 无法导入该文件: {}'.format(module_name, entry.path))
394
+ except Exception as e:
395
+ self.logger.error('{} 无法导入该文件: {}! {}'.format(module_name, entry.path, str(e)))
370
396
  continue
371
397
 
372
398
  module_vars = vars(part_module)
@@ -386,7 +412,8 @@ class HubManager(metaclass=SingletonType):
386
412
  module_name=module_name,
387
413
  author=part_module.author.strip() if 'author' in module_vars else 'None',
388
414
  version=part_module.version.strip() if 'version' in module_vars else 'None',
389
- doc=part_module.part.__doc__.strip() if part_module.part.__doc__ else "None"
415
+ doc=part_module.part.__doc__.strip() if part_module.part.__doc__ else "None",
416
+ label=part_module.label.strip() if 'label' in module_vars else 'None',
390
417
  )
391
418
  self._session.add(part_model)
392
419
  except Exception as e:
@@ -426,6 +453,30 @@ class HubManager(metaclass=SingletonType):
426
453
  pass
427
454
  return part
428
455
 
456
+ @dbsession
457
+ def get_part_module(self, name):
458
+ """获取指定策略部件
459
+
460
+ :param str name: 策略部件名称
461
+ :param kwargs: 其他部件相关参数
462
+ """
463
+ name_parts = name.split('.')
464
+ checkif(
465
+ len(name_parts) < 2
466
+ or (name_parts[-2] not in ('af', 'cn', 'ev', 'mf', 'mm', 'pg', 'se', 'sg', 'sp', 'st', 'pf', 'sys', 'ind', 'other')),
467
+ name, PartNameError
468
+ )
469
+
470
+ # 未指定仓库名,则默认使用 'default' 仓库
471
+ part_name = 'default.{}'.format(name) if len(name_parts) == 2 else name
472
+ part_model = self._session.query(PartModel).filter_by(name=part_name).first()
473
+ checkif(part_model is None, part_name, PartNotFoundError, cause='仓库中不存在')
474
+ try:
475
+ part_module = importlib.import_module(part_model.module_name)
476
+ except ModuleNotFoundError:
477
+ raise PartNotFoundError(part_name, '请检查部件对应路径是否存在')
478
+ return part_module
479
+
429
480
  @dbsession
430
481
  def get_part_info(self, name):
431
482
  """获取策略部件信息
@@ -434,11 +485,25 @@ class HubManager(metaclass=SingletonType):
434
485
  """
435
486
  part_model = self._session.query(PartModel).filter_by(name=name).first()
436
487
  checkif(part_model is None, name, PartNotFoundError, cause='仓库中不存在')
488
+ try:
489
+ part_module = importlib.import_module(part_model.module_name)
490
+ except ModuleNotFoundError:
491
+ raise PartNotFoundError(name, '请检查部件对应路径是否存在')
492
+ signature = inspect.signature(part_module.part)
493
+ func_name = f'\npart("{name}",'
494
+ for param_name, param in signature.parameters.items():
495
+ if param.default is param.empty:
496
+ func_name += f"{param_name}, "
497
+ else:
498
+ default_value = param.default
499
+ func_name += f"{param_name}={default_value}, "
500
+ func_name += ")\n"
501
+ func_name += part_module.part.__doc__
437
502
  return {
438
503
  'name': name,
439
504
  'author': part_model.author,
440
505
  'version': part_model.version,
441
- 'doc': part_model.doc,
506
+ 'doc': func_name # part_module.part.__doc__,
442
507
  }
443
508
 
444
509
  def print_part_info(self, name):
@@ -450,10 +515,7 @@ class HubManager(metaclass=SingletonType):
450
515
  print('+---------+------------------------------------------------')
451
516
  print('| version | ', info['version'])
452
517
  print('+---------+------------------------------------------------')
453
- # print('\n')
454
518
  print(info['doc'])
455
- # print('\n')
456
- # print('----------------------------------------------------------')
457
519
 
458
520
  @dbsession
459
521
  def get_hub_path(self, name):
@@ -500,6 +562,37 @@ class HubManager(metaclass=SingletonType):
500
562
  checkif(hub_model is None, local_base, HubNotFoundError)
501
563
  return hub_model.name
502
564
 
565
+ @dbsession
566
+ def search_part(self, name: str = None, hub: str = None, part_type: str = None, label=None):
567
+ """搜索部件
568
+ :param str name: 部件名称
569
+ :param str hub: 仓库名
570
+ :param str part_type: 部件类型
571
+ :param str label: 标签
572
+ :return: 部件名称列表
573
+ :rtype: list
574
+ """
575
+ parts = None
576
+ if name is not None:
577
+ parts = self._session.query(PartModel).filter(PartModel.name.like(f'%{name}%'))
578
+ if hub is not None:
579
+ if parts is None:
580
+ parts = self._session.query(PartModel).fileter(PartModel.hub_name.like(f'%{hub}%'))
581
+ else:
582
+ parts = parts.filter(PartModel.hub_name.like(f'%{hub}%'))
583
+ if part_type is not None:
584
+ if parts is None:
585
+ parts = self._session.query(PartModel).filter(PartModel.part.like(f'%{part_type}%'))
586
+ else:
587
+ parts = parts.filter(PartModel.part.like(f'%{part_type}%'))
588
+ if label is not None:
589
+ if parts is None:
590
+ parts = self._session.query(PartModel).filter(PartModel.label.like(f'%{label}%'))
591
+ else:
592
+ parts = parts.filter(PartModel.label.like(f'%{label}%'))
593
+ records = parts.all() if parts is not None else []
594
+ return [record.name for record in records]
595
+
503
596
 
504
597
  def add_remote_hub(name, url, branch='main'):
505
598
  """增加远程策略仓库
@@ -552,7 +645,29 @@ def get_part(name, *args, **kwargs):
552
645
  :param args: 其他部件相关参数
553
646
  :param kwargs: 其他部件相关参数
554
647
  """
555
- return HubManager().get_part(name, *args, **kwargs)
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
660
+
661
+
662
+ def get_part_list(name_list):
663
+ """
664
+ 获取指定策略部件列表
665
+
666
+ :param list name_list: 部件名称列表
667
+ :return: 部件列表
668
+ :rtype: list
669
+ """
670
+ return [get_part(name) for name in name_list]
556
671
 
557
672
 
558
673
  def get_hub_path(name):
@@ -575,6 +690,9 @@ def print_part_info(name):
575
690
  HubManager().print_part_info(name)
576
691
 
577
692
 
693
+ help_part = print_part_info
694
+
695
+
578
696
  def get_hub_name_list():
579
697
  """返回仓库名称列表"""
580
698
  return HubManager().get_hub_name_list()
@@ -588,6 +706,16 @@ def get_part_name_list(hub=None, part_type=None):
588
706
  return HubManager().get_part_name_list(hub, part_type)
589
707
 
590
708
 
709
+ def get_part_module(part_name: str):
710
+ """获取部件模块
711
+ :param str part_name: 部件名称
712
+ :return: 部件模块
713
+ :rtype: module
714
+ """
715
+ return HubManager().get_part_module(part_name)
716
+
717
+
718
+ @lru_cache
591
719
  def get_current_hub(filename):
592
720
  """用于在仓库part.py中获取当前所在的仓库名。
593
721
  示例: get_current_hub(__file__)
@@ -595,6 +723,19 @@ def get_current_hub(filename):
595
723
  return HubManager().get_current_hub(filename)
596
724
 
597
725
 
726
+ def search_part(name: str = None, hub: str = None, part_type: str = None, label: str = None):
727
+ """搜索部件
728
+
729
+ :param str name: 部件名称
730
+ :param str hub: 仓库名
731
+ :param str part_type: 部件类型
732
+ :param str label: 标签
733
+ :return: 部件名称列表
734
+ :rtype: list
735
+ """
736
+ return HubManager().search_part(name, hub, part_type, label)
737
+
738
+
598
739
  # 初始化仓库
599
740
  try:
600
741
  HubManager().setup_hub()
@@ -607,13 +748,17 @@ __all__ = [
607
748
  'update_hub',
608
749
  'remove_hub',
609
750
  'build_hub',
751
+ 'help_part',
610
752
  'get_part',
753
+ 'get_part_list',
611
754
  'get_hub_path',
612
755
  'get_part_info',
756
+ 'get_part_module',
613
757
  'print_part_info',
614
758
  'get_hub_name_list',
615
759
  'get_part_name_list',
616
760
  'get_current_hub',
761
+ 'search_part',
617
762
  ]
618
763
 
619
764
  if __name__ == "__main__":
hikyuu/hub.pyi CHANGED
@@ -1,23 +1,23 @@
1
1
  from __future__ import annotations
2
- from configparser import ConfigParser
3
2
  import errno as errno
3
+ from functools import lru_cache
4
4
  import git as git
5
5
  from hikyuu.util.check import checkif
6
+ from hikyuu.util.mylog import hku_info
6
7
  from hikyuu.util.singleton import SingletonType
7
8
  import importlib as importlib
9
+ import inspect as inspect
8
10
  import logging as logging
9
11
  import os as os
10
12
  import pathlib as pathlib
11
13
  import shutil as shutil
14
+ import sqlalchemy as sqlalchemy
12
15
  from sqlalchemy.engine.create import create_engine
13
16
  from sqlalchemy.orm.decl_api import Base
14
17
  from sqlalchemy.orm.decl_api import declarative_base
15
- import sqlalchemy.orm.instrumentation
16
- import sqlalchemy.orm.mapper
17
18
  from sqlalchemy.orm.scoping import scoped_session
18
19
  from sqlalchemy.orm.session import sessionmaker
19
20
  from sqlalchemy.sql._elements_constructors import and_
20
- import sqlalchemy.sql.schema
21
21
  from sqlalchemy.sql.schema import Column
22
22
  from sqlalchemy.sql.schema import Sequence
23
23
  from sqlalchemy.sql.schema import UniqueConstraint
@@ -26,13 +26,13 @@ from sqlalchemy.sql.sqltypes import String
26
26
  import stat as stat
27
27
  import sys as sys
28
28
  import typing
29
- __all__: list = ['add_remote_hub', 'add_local_hub', 'update_hub', 'remove_hub', 'build_hub', 'get_part', 'get_hub_path', 'get_part_info', 'print_part_info', 'get_hub_name_list', 'get_part_name_list', 'get_current_hub']
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 0x247390a0f50; ConfigModel>
31
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x26f9bde2d90; 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 2473909a800>
35
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.ConfigModel'> at 26f9bdf0950>
36
36
  def __init__(self, **kwargs):
37
37
  """
38
38
  A simple constructor that allows initialization from kwargs.
@@ -79,6 +79,9 @@ class HubManager:
79
79
  def get_part_info(*args, **kwargs):
80
80
  ...
81
81
  @staticmethod
82
+ def get_part_module(*args, **kwargs):
83
+ ...
84
+ @staticmethod
82
85
  def get_part_name_list(*args, **kwargs):
83
86
  ...
84
87
  @staticmethod
@@ -88,6 +91,9 @@ class HubManager:
88
91
  def remove_hub(*args, **kwargs):
89
92
  ...
90
93
  @staticmethod
94
+ def search_part(*args, **kwargs):
95
+ ...
96
+ @staticmethod
91
97
  def setup_hub(*args, **kwargs):
92
98
  ...
93
99
  @staticmethod
@@ -100,11 +106,11 @@ class HubManager:
100
106
  def print_part_info(self, name):
101
107
  ...
102
108
  class HubModel(sqlalchemy.orm.decl_api.Base):
103
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x2473847b0e0; HubModel>
109
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x26f9be26430; HubModel>
104
110
  __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)
105
111
  __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('name', String(), table=<hub_repo>)))
106
112
  __tablename__: typing.ClassVar[str] = 'hub_repo'
107
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.HubModel'> at 247390bf110>
113
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.HubModel'> at 26f9be1e720>
108
114
  def __init__(self, **kwargs):
109
115
  """
110
116
  A simple constructor that allows initialization from kwargs.
@@ -137,10 +143,11 @@ class ModuleConflictError(Exception):
137
143
  def __str__(self):
138
144
  ...
139
145
  class PartModel(sqlalchemy.orm.decl_api.Base):
140
- __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x247390a1ca0; PartModel>
141
- __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>), schema=None)
146
+ __mapper__: typing.ClassVar[sqlalchemy.orm.mapper.Mapper] # value = <Mapper at 0x26f9be26dc0; PartModel>
147
+ __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
+ __table_args__: typing.ClassVar[tuple] # value = (UniqueConstraint(Column('name', String(), table=<hub_part>)))
142
149
  __tablename__: typing.ClassVar[str] = 'hub_part'
143
- _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.PartModel'> at 247390bfbb0>
150
+ _sa_class_manager: typing.ClassVar[sqlalchemy.orm.instrumentation.ClassManager] # value = <ClassManager of <class 'hikyuu.hub.PartModel'> at 26f9be2c220>
144
151
  def __init__(self, **kwargs):
145
152
  """
146
153
  A simple constructor that allows initialization from kwargs.
@@ -194,7 +201,7 @@ def build_hub(name, cmd = 'buildall'):
194
201
  """
195
202
  def dbsession(func):
196
203
  ...
197
- def get_current_hub(filename):
204
+ def get_current_hub(*args, **kwargs):
198
205
  """
199
206
  用于在仓库part.py中获取当前所在的仓库名。
200
207
  示例: get_current_hub(__file__)
@@ -226,6 +233,24 @@ def get_part_info(name):
226
233
 
227
234
  :param str name: 部件名称
228
235
 
236
+ """
237
+ def get_part_list(name_list):
238
+ """
239
+
240
+ 获取指定策略部件列表
241
+
242
+ :param list name_list: 部件名称列表
243
+ :return: 部件列表
244
+ :rtype: list
245
+
246
+ """
247
+ def get_part_module(part_name: str):
248
+ """
249
+ 获取部件模块
250
+ :param str part_name: 部件名称
251
+ :return: 部件模块
252
+ :rtype: module
253
+
229
254
  """
230
255
  def get_part_name_list(hub = None, part_type = None):
231
256
  """
@@ -244,6 +269,18 @@ def remove_hub(name):
244
269
 
245
270
  :param str name: 仓库名称
246
271
 
272
+ """
273
+ def search_part(name: str = None, hub: str = None, part_type: str = None, label: str = None):
274
+ """
275
+ 搜索部件
276
+
277
+ :param str name: 部件名称
278
+ :param str hub: 仓库名
279
+ :param str part_type: 部件类型
280
+ :param str label: 标签
281
+ :return: 部件名称列表
282
+ :rtype: list
283
+
247
284
  """
248
285
  def update_hub(name):
249
286
  """
@@ -252,3 +289,4 @@ def update_hub(name):
252
289
  :param str name: 仓库名称
253
290
 
254
291
  """
292
+ help_part = print_part_info
@@ -149,8 +149,7 @@ using std::isinf;
149
149
  using std::isnan;
150
150
 
151
151
  inline bool iszero(price_t num) {
152
- const price_t epsilon = std::numeric_limits<price_t>::epsilon();
153
- return std::abs(num) < epsilon;
152
+ return std::abs(num) < std::numeric_limits<price_t>::epsilon();
154
153
  }
155
154
 
156
155
  using fmt::format;
@@ -5,6 +5,7 @@
5
5
  * Author: fasiondog
6
6
  */
7
7
 
8
+ #pragma once
8
9
  #ifndef STOCKMANAGER_H_
9
10
  #define STOCKMANAGER_H_
10
11
 
@@ -278,7 +279,7 @@ private:
278
279
  static StockManager* m_sm;
279
280
  std::atomic_bool m_initializing;
280
281
  std::atomic_bool m_data_ready; // 用于指示是否所有数据准备完毕
281
- std::thread::id m_thread_id; // 记录线程id,用于判断Stratege是以独立进程方式还是线程方式运行
282
+ std::thread::id m_thread_id; // 记录线程id,用于判断Stratege是以独立进程方式还是线程方式运行
282
283
  string m_tmpdir;
283
284
  string m_datadir;
284
285
  BaseInfoDriverPtr m_baseInfoDriver;
@@ -24,7 +24,6 @@ public:
24
24
 
25
25
  /**
26
26
  * 构造函数
27
- * @note 未指定 ktypelist 时,默认按预加载参数加载全部
28
27
  * @param stockCodeList 指定的证券代码列表,如:如:{"sz000001", "sz000002"}
29
28
  */
30
29
  explicit StrategyContext(const vector<string>& stockCodeList);
@@ -32,11 +31,14 @@ public:
32
31
  /**
33
32
  * 构造函数
34
33
  * @note 证券列表中如果包含 ("ALL") 则表示全部证券;
35
- * 指定K线类型列表同时影响着K线数据的优先加载顺序,靠前的将优先加载。同时受系统配置中预加载参数影响!
34
+ * 1. 指定K线类型列表同时影响着K线数据的优先加载顺序,靠前的将优先加载。
35
+ * 2. 未指定 ktypelist 或 preloadNum 时,将使用全局配置文件参数
36
36
  * @param stockCodeList 指定的证券代码列表,如:{"sh000001", "sz000001"}
37
37
  * @param ktypeList 指定的 K线数据列表,如:{"day", "min"}
38
+ * @param preloadNum 指定的预加载数量,如:{{"min_max", 100}, {"day_max", 200}}
38
39
  */
39
- StrategyContext(const vector<string>& stockCodeList, const vector<KQuery::KType>& ktypeList);
40
+ StrategyContext(const vector<string>& stockCodeList, const vector<KQuery::KType>& ktypeList,
41
+ const unordered_map<string, int>& preloadNum = {});
40
42
 
41
43
  // 自定义移动构造与赋值会引起 python 中无法正常退出
42
44
  // StrategyContext(const StrategyContext&) = default;
@@ -75,6 +77,12 @@ public:
75
77
  return m_ktypeList;
76
78
  }
77
79
 
80
+ void setPreloadNum(const unordered_map<string, int>& preloadNum);
81
+
82
+ const unordered_map<string, int>& getPreloadNum() const noexcept {
83
+ return m_preloadNum;
84
+ }
85
+
78
86
  /**
79
87
  * 隐含的默认必须被加载的证券列表
80
88
  * @note 影响交易日历判断、和某些常被作为默认比较基准的证券,通常被作为某些函数的默认值
@@ -100,6 +108,7 @@ private:
100
108
  vector<string> m_mustLoad{"sh000001", "sh000300"}; // 默认必须加载的 stock
101
109
  vector<string> m_stockCodeList;
102
110
  vector<KQuery::KType> m_ktypeList;
111
+ unordered_map<string, int> m_preloadNum;
103
112
  };
104
113
 
105
114
  HKU_API std::ostream& operator<<(std::ostream& os, const StrategyContext& context);
@@ -198,6 +198,8 @@ public:
198
198
  return !m_imp && m_imp == other.m_imp;
199
199
  }
200
200
 
201
+ string str() const;
202
+
201
203
  protected:
202
204
  IndicatorImpPtr m_imp;
203
205
 
@@ -383,6 +385,13 @@ HKU_API Indicator operator|(Indicator::value_t, const Indicator&);
383
385
  */
384
386
  Indicator HKU_API WEAVE(const Indicator& ind1, const Indicator& ind2);
385
387
 
388
+ template <typename... Args>
389
+ inline Indicator WEAVE(const Indicator& ind1, const Indicator& ind2, const Args&... others) {
390
+ HKU_CHECK(sizeof...(others) <= 4, "WEAVE() only support 6 Indicator!");
391
+ Indicator tmp = WEAVE(ind1, ind2);
392
+ return WEAVE(std::move(tmp), others...);
393
+ }
394
+
386
395
  /**
387
396
  * 条件函数, 根据条件求不同的值。
388
397
  * @details
@@ -402,6 +411,21 @@ Indicator HKU_API IF(const Indicator& x, Indicator::value_t a, Indicator::value_
402
411
 
403
412
  } /* namespace hku */
404
413
 
414
+ namespace std {
415
+ template <>
416
+ class hash<hku::Indicator> {
417
+ public:
418
+ size_t operator()(hku::Indicator const& ind) const noexcept {
419
+ auto imp = ind.getImp();
420
+ return imp.get() ? std::hash<hku::IndicatorImpPtr>()(imp) : 0;
421
+ }
422
+ };
423
+
424
+ inline string to_string(const hku::Indicator& ind) {
425
+ return ind.str();
426
+ }
427
+ } // namespace std
428
+
405
429
  #if FMT_VERSION >= 90000
406
430
  template <>
407
431
  struct fmt::formatter<hku::Indicator> : ostream_formatter {};
@@ -47,6 +47,7 @@ private: \
47
47
  friend class boost::serialization::access; \
48
48
  template <class Archive> \
49
49
  void serialize(Archive& ar, const unsigned int version) { \
50
+ ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(IndicatorImp); \
50
51
  ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(Indicator2InImp); \
51
52
  }
52
53
  #else
@@ -66,6 +66,7 @@
66
66
  #include "crt/ISNA.h"
67
67
  #include "crt/JUMPUP.h"
68
68
  #include "crt/JUMPDOWN.h"
69
+ #include "crt/KALMAN.h"
69
70
  #include "crt/LAST.h"
70
71
  #include "crt/LASTVALUE.h"
71
72
  #include "crt/LIUTONGPAN.h"
@@ -115,6 +116,7 @@
115
116
  #include "crt/TIME.h"
116
117
  #include "crt/TIMELINE.h"
117
118
  #include "crt/TIMELINEVOL.h"
119
+ #include "crt/TR.h"
118
120
  #include "crt/TURNOVER.h"
119
121
  #include "crt/UPNDAY.h"
120
122
  #include "crt/VAR.h"
@@ -14,12 +14,11 @@
14
14
  namespace hku {
15
15
 
16
16
  /**
17
- * 平均真实波幅(Average True Range)
17
+ * 平均真实波幅(Average True Range), TR 的简单平均值
18
18
  * @param n 计算均值的周期窗口,必须为大于1的整数
19
19
  * @ingroup Indicator
20
20
  */
21
21
  Indicator HKU_API ATR(int n = 14);
22
- Indicator HKU_API ATR(const IndParam& n);
23
22
 
24
23
  /**
25
24
  * 平均真实波幅(Average True Range)
@@ -27,17 +26,7 @@ Indicator HKU_API ATR(const IndParam& n);
27
26
  * @param n 计算均值的周期窗口,必须为大于1的整数
28
27
  * @ingroup Indicator
29
28
  */
30
- inline Indicator HKU_API ATR(const Indicator& data, int n = 14) {
31
- return ATR(n)(data);
32
- }
33
-
34
- inline Indicator HKU_API ATR(const Indicator& data, const IndParam& n) {
35
- return ATR(n)(data);
36
- }
37
-
38
- inline Indicator HKU_API ATR(const Indicator& data, const Indicator& n) {
39
- return ATR(IndParam(n))(data);
40
- }
29
+ Indicator HKU_API ATR(const KData& kdata, int n = 14);
41
30
 
42
31
  } // namespace hku
43
32
 
@@ -0,0 +1,30 @@
1
+ /*
2
+ * Copyright (c) 2025 hikyuu.org
3
+ *
4
+ * Created on: 2025-03-02
5
+ * Author: fasiondog
6
+ */
7
+
8
+ #pragma once
9
+ #ifndef INDICATOR_CRT_KALMAN_H_
10
+ #define INDICATOR_CRT_KALMAN_H_
11
+
12
+ #include "CVAL.h"
13
+
14
+ namespace hku {
15
+
16
+ /**
17
+ * 卡尔曼滤波
18
+ * @param q 噪声方差
19
+ * @param r 测量噪声方差
20
+ * @ingroup Indicator
21
+ */
22
+ Indicator HKU_API KALMAN(double q = 0.01, double r = 0.1);
23
+
24
+ inline Indicator KALMAN(const Indicator& ind, double q = 0.01, double r = 0.1) {
25
+ return KALMAN(q, r)(ind);
26
+ }
27
+
28
+ } // namespace hku
29
+
30
+ #endif /* INDICATOR_CRT_KALMAN_H_ */
@@ -0,0 +1,32 @@
1
+ /*
2
+ * TRG.h
3
+ *
4
+ * Created on: 2019年3月6日
5
+ * Author: fasiondog
6
+ */
7
+
8
+ #pragma once
9
+ #ifndef INDICATOR_CRT_TR_H_
10
+ #define INDICATOR_CRT_TR_H_
11
+
12
+ #include "../Indicator.h"
13
+
14
+ namespace hku {
15
+
16
+ /**
17
+ * @brief 真实波动幅度(TR)
18
+ * @details
19
+ * <pre>
20
+ * 真实波动幅度(TR)是以下三个值中的最大值:
21
+ * 1. 当前周期最高价(H)与最低价(L)之差
22
+ * 2. 当前周期最高价与前一周期收盘价(PC)之差的绝对值
23
+ * 3. 当前周期最低价与前一周期收盘价之差的绝对值
24
+ * </pre>
25
+ * @ingroup Indicator
26
+ */
27
+ Indicator HKU_API TR();
28
+ Indicator HKU_API TR(const KData&);
29
+
30
+ } // namespace hku
31
+
32
+ #endif /* INDICATOR_CRT_TR_H_ */