quant1x 0.5.2__tar.gz → 0.5.6__tar.gz

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 (62) hide show
  1. {quant1x-0.5.2 → quant1x-0.5.6}/PKG-INFO +2 -4
  2. quant1x-0.5.6/quant1x/__init__.py +1 -0
  3. quant1x-0.5.6/quant1x/base/__init__.py +19 -0
  4. quant1x-0.5.6/quant1x/base/app.py +36 -0
  5. quant1x-0.5.6/quant1x/base/base.py +72 -0
  6. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x/base/basic.py +62 -62
  7. quant1x-0.5.6/quant1x/base/cache.py +281 -0
  8. quant1x-0.5.6/quant1x/base/config.py +52 -0
  9. quant1x-0.5.6/quant1x/base/device.py +25 -0
  10. quant1x-0.5.6/quant1x/base/devp.py +27 -0
  11. quant1x-0.5.6/quant1x/base/exchange.py +340 -0
  12. quant1x-0.5.6/quant1x/base/file.py +46 -0
  13. quant1x-0.5.6/quant1x/base/logger.py +21 -0
  14. quant1x-0.5.6/quant1x/base/market.py +56 -0
  15. quant1x-0.5.6/quant1x/base/network.py +59 -0
  16. quant1x-0.5.6/quant1x/base/numerics.py +36 -0
  17. quant1x-0.5.6/quant1x/base/pattern.py +20 -0
  18. quant1x-0.5.6/quant1x/base/timestamp.py +170 -0
  19. quant1x-0.5.6/quant1x/base/version.py +59 -0
  20. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x/data/quotes.py +638 -638
  21. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x/formula/__init__.py +4 -4
  22. {quant1x-0.5.2/quant1x/base → quant1x-0.5.6/quant1x/formula}/formula.py +993 -993
  23. {quant1x-0.5.2/quant1x/base → quant1x-0.5.6/quant1x/formula}/formula_plus.py +191 -191
  24. {quant1x-0.5.2/quant1x/strategy → quant1x-0.5.6/quant1x/indicators}/__init__.py +4 -3
  25. {quant1x-0.5.2/quant1x/indicator → quant1x-0.5.6/quant1x/indicators}/ma1x.py +193 -193
  26. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x/util/font.py +38 -38
  27. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x.egg-info/PKG-INFO +2 -4
  28. quant1x-0.5.6/quant1x.egg-info/SOURCES.txt +37 -0
  29. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x.egg-info/requires.txt +0 -3
  30. {quant1x-0.5.2 → quant1x-0.5.6}/setup.py +3 -2
  31. quant1x-0.5.2/quant1x/__init__.py +0 -20
  32. quant1x-0.5.2/quant1x/base/__init__.py +0 -8
  33. quant1x-0.5.2/quant1x/base/series.py +0 -93
  34. quant1x-0.5.2/quant1x/data/block.py +0 -179
  35. quant1x-0.5.2/quant1x/data/futu-basicinfo.py +0 -27
  36. quant1x-0.5.2/quant1x/data/tdx.py +0 -6
  37. quant1x-0.5.2/quant1x/data/trade_date.py +0 -55
  38. quant1x-0.5.2/quant1x/findpeaks/__init__.py +0 -13
  39. quant1x-0.5.2/quant1x/findpeaks/filters/__init__.py +0 -0
  40. quant1x-0.5.2/quant1x/findpeaks/filters/frost.py +0 -168
  41. quant1x-0.5.2/quant1x/findpeaks/filters/kuan.py +0 -139
  42. quant1x-0.5.2/quant1x/findpeaks/filters/lee.py +0 -147
  43. quant1x-0.5.2/quant1x/findpeaks/filters/lee_enhanced.py +0 -163
  44. quant1x-0.5.2/quant1x/findpeaks/filters/mean.py +0 -122
  45. quant1x-0.5.2/quant1x/findpeaks/filters/median.py +0 -103
  46. quant1x-0.5.2/quant1x/findpeaks/findpeaks.py +0 -1253
  47. quant1x-0.5.2/quant1x/findpeaks/interpolate.py +0 -194
  48. quant1x-0.5.2/quant1x/findpeaks/stats.py +0 -593
  49. quant1x-0.5.2/quant1x/findpeaks/union_find.py +0 -73
  50. quant1x-0.5.2/quant1x/indicator/__init__.py +0 -4
  51. quant1x-0.5.2/quant1x/strategy/bad_base.py +0 -112
  52. quant1x-0.5.2/quant1x/strategy/linear_regression.py +0 -65
  53. quant1x-0.5.2/quant1x.egg-info/SOURCES.txt +0 -42
  54. {quant1x-0.5.2 → quant1x-0.5.6}/LICENSE +0 -0
  55. {quant1x-0.5.2 → quant1x-0.5.6}/README.md +0 -0
  56. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x/chart.py +0 -0
  57. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x/data/__init__.py +0 -0
  58. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x/util/__init__.py +0 -0
  59. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x.egg-info/dependency_links.txt +0 -0
  60. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x.egg-info/not-zip-safe +0 -0
  61. {quant1x-0.5.2 → quant1x-0.5.6}/quant1x.egg-info/top_level.txt +0 -0
  62. {quant1x-0.5.2 → quant1x-0.5.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quant1x
3
- Version: 0.5.2
3
+ Version: 0.5.6
4
4
  Summary: Quant1X量化研究
5
5
  Home-page: https://gitee.com/quant1x/quant1x
6
6
  Author: WangFeng
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
21
22
  Description-Content-Type: text/markdown
22
23
  License-File: LICENSE
23
24
  Requires-Dist: setuptools~=78.0.0
@@ -35,8 +36,6 @@ Requires-Dist: matplotlib~=3.10.5
35
36
  Requires-Dist: akshare~=1.17.38
36
37
  Requires-Dist: findpeaks~=2.7.4
37
38
  Requires-Dist: mootdx~=0.11.7
38
- Requires-Dist: numpy~=2.3.0
39
- Requires-Dist: pandas~=2.3.0
40
39
  Requires-Dist: python-dateutil~=2.9.0.post0
41
40
  Requires-Dist: requests==2.32.0
42
41
  Requires-Dist: tqdm~=4.67.1
@@ -46,7 +45,6 @@ Requires-Dist: matplotlib~=3.10.1
46
45
  Requires-Dist: scipy~=1.16.0
47
46
  Requires-Dist: caerus~=0.1.10
48
47
  Requires-Dist: joblib~=1.5.1
49
- Requires-Dist: quant1x-base~=0.6.18
50
48
  Dynamic: author
51
49
  Dynamic: author-email
52
50
  Dynamic: classifier
@@ -0,0 +1 @@
1
+ # -*- coding: UTF-8 -*-
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ """
5
+ 基础工具集
6
+ """
7
+
8
+ __author__ = 'WangFeng'
9
+
10
+ from .app import application
11
+ from .device import cpu_num, max_procs
12
+ from .devp import project_path, redirect
13
+ from .file import mkdirs, touch, homedir
14
+ from .logger import logger
15
+ from .network import ip_is_private, ip_is_secure, lan_address
16
+ from .numerics import is_nan, float_round, fix_float
17
+ from .pattern import Singleton
18
+ from .timestamp import TimeRange, FORMAT_DATETIME
19
+ from .timestamp import TradingSession, seconds_to_timestamp
@@ -0,0 +1,36 @@
1
+ # -*- coding: UTF-8 -*-
2
+ import os.path
3
+ import sys
4
+
5
+ from . import file
6
+
7
+
8
+ def application() -> tuple[str, str, str]:
9
+ """
10
+ 获取应用程序的名字
11
+ :return: 目录, 文件名, 扩展名
12
+ """
13
+ app = sys.argv[0]
14
+ # print(app)
15
+ # print(os.path.abspath(app))
16
+ abspath = os.path.abspath(app)
17
+ # print(os.path.realpath(app))
18
+ dirname, filename = os.path.split(abspath)
19
+ (filename, ext) = os.path.splitext(filename)
20
+ # print(filename, ext)
21
+ return dirname, filename, ext
22
+
23
+
24
+ def getuser():
25
+ """
26
+ 获取用户名
27
+ :return:
28
+ """
29
+ home = file.homedir()
30
+ _, username = os.path.split(home)
31
+ return username
32
+
33
+
34
+ if __name__ == '__main__':
35
+ name = application()
36
+ print(name)
@@ -0,0 +1,72 @@
1
+ # -*- coding: UTF-8 -*-
2
+ import os
3
+
4
+ import yaml
5
+
6
+ import file
7
+
8
+ def get_quant1x_config_filename() -> str:
9
+ """
10
+ 获取quant1x.yaml文件路径
11
+ :return:
12
+ """
13
+ # 默认配置文件名
14
+ default_config_filename = 'quant1x.yaml'
15
+ yaml_filename = os.path.join('~', 'runtime', 'etc', default_config_filename)
16
+ yaml_filename = os.path.expanduser(yaml_filename)
17
+ user_home = file.homedir()
18
+ if not os.path.isfile(yaml_filename):
19
+ quant1x_root = os.path.join(user_home, '.quant1x')
20
+ yaml_filename = os.path.join(quant1x_root, default_config_filename)
21
+ yaml_filename = os.path.expanduser(yaml_filename)
22
+ yaml_filename = os.path.expanduser(yaml_filename)
23
+ return yaml_filename
24
+
25
+
26
+ # 安全加载YAML配置
27
+ def load_config(file_path: str) -> dict:
28
+ """安全加载YAML配置"""
29
+ try:
30
+ with open(file_path, 'r', encoding='utf-8') as f:
31
+ config = yaml.safe_load(f) or {}
32
+ return config
33
+ except FileNotFoundError:
34
+ raise ValueError(f"配置文件 {file_path} 不存在")
35
+ except yaml.YAMLError as e:
36
+ raise ValueError(f"YAML格式错误: {str(e)}")
37
+ except Exception as e:
38
+ raise ValueError(f"加载配置失败: {str(e)}")
39
+
40
+ class Quant1XConfig:
41
+ _instance = None
42
+
43
+ def __new__(cls):
44
+ if cls._instance is None:
45
+ cls._instance = super().__new__(cls)
46
+ cls._instance._initialize()
47
+ return cls._instance
48
+
49
+ def _initialize(self):
50
+ """初始化配置"""
51
+ self.__home_path = file.homedir()
52
+ self.__config_filename = get_quant1x_config_filename()
53
+ self.__config = load_config(self.__config_filename)
54
+
55
+ # 初始化路径
56
+ self.__default_main_path = os.path.join(self.__home_path, '.quant1x')
57
+
58
+ self.meta_path = os.path.join(self.__default_main_path, 'meta')
59
+ """str: 元数据路径"""
60
+
61
+ self.data_path = self.__config.get('basedir', '').strip()
62
+ """str: 数据目录 """
63
+
64
+ if not self.data_path:
65
+ self.data_path = os.path.join(self.__default_main_path, 'data')
66
+ self.data_path= os.path.expanduser(self.data_path)
67
+ # 数据路径
68
+ self.kline_path = os.path.join(self.data_path, 'day')
69
+ """str: K线路径 """
70
+
71
+ # 创建配置单例
72
+ config = Quant1XConfig()
@@ -1,62 +1,62 @@
1
- #!/usr/bin/python
2
- # -*- coding: UTF-8 -*-
3
- """
4
- 最基础的工具
5
- """
6
-
7
-
8
- # A_YI:=100000000;
9
- # 亿:A_YI;
10
- # 股价:CLOSE<30;
11
- # 市值:FINANCE(40)<(2000*A_YI);
12
- # 涨停比例:IF(FINANCE(3)=2,0.3,IF((FINANCE(3)=4 OR FINANCE(3)=3),0.2,0.1));
13
- def ZTBL(code: str) -> float:
14
- """
15
- 涨停比例, 只支持A股
16
-
17
- .. note::
18
- 30 68开头的个股涨停比例20%, 其余10%
19
-
20
- :param code:
21
- :return:
22
- """
23
- symbol = code[-6:]
24
- prefix = symbol[0:2]
25
- if prefix in ['30', '68']:
26
- return 0.2
27
- else:
28
- return 0.1
29
-
30
-
31
- def ZTPRICE(close, ztbl) -> float:
32
- """
33
- 计算涨停价
34
- :param close:
35
- :param ztbl:
36
- :return:
37
- """
38
- return close * (1 + ztbl)
39
-
40
- # 停牌:DYNAINFO(8)<=0;
41
- # ST股:NAMELIKE('ST') OR NAMELIKE('*ST') OR NAMELIKE('S');
42
- # 真阳线:CLOSE>REF(CLOSE,1);
43
- # 筹码锁定:BARSLASTCOUNT(LFS>REF(LFS,1))>=2 AND LFS>=30;
44
- # 浮筹比例:(WINNER(C*1.1)-WINNER(C*0.9))/WINNER(HHV(H,0))*100;
45
- #
46
- # JXN1:=5;
47
- # JXN2:=10;
48
- # M1:=MA(CLOSE,JXN1);
49
- # M2:=MA(CLOSE,JXN2);
50
- # 均线粘合:ABS(M1/M2-1)<0.01;
51
- #
52
- # {K线数据}
53
- # X_HIGH:HIGH;
54
- # X_LOW:LOW;
55
- # X_OPEN:OPEN;
56
- # X_CLOSE:CLOSE;
57
- # X_VOL:VOL;
58
- # X_AMOUNT:AMOUNT;
59
- #
60
- # {斜率}
61
- # C_WIDTH:0.009499432279;
62
- # C_PI:3.141592654;
1
+ #!/usr/bin/python
2
+ # -*- coding: UTF-8 -*-
3
+ """
4
+ 最基础的工具
5
+ """
6
+
7
+
8
+ # A_YI:=100000000;
9
+ # 亿:A_YI;
10
+ # 股价:CLOSE<30;
11
+ # 市值:FINANCE(40)<(2000*A_YI);
12
+ # 涨停比例:IF(FINANCE(3)=2,0.3,IF((FINANCE(3)=4 OR FINANCE(3)=3),0.2,0.1));
13
+ def ZTBL(code: str) -> float:
14
+ """
15
+ 涨停比例, 只支持A股
16
+
17
+ .. note::
18
+ 30 68开头的个股涨停比例20%, 其余10%
19
+
20
+ :param code:
21
+ :return:
22
+ """
23
+ symbol = code[-6:]
24
+ prefix = symbol[0:2]
25
+ if prefix in ['30', '68']:
26
+ return 0.2
27
+ else:
28
+ return 0.1
29
+
30
+
31
+ def ZTPRICE(close, ztbl) -> float:
32
+ """
33
+ 计算涨停价
34
+ :param close:
35
+ :param ztbl:
36
+ :return:
37
+ """
38
+ return close * (1 + ztbl)
39
+
40
+ # 停牌:DYNAINFO(8)<=0;
41
+ # ST股:NAMELIKE('ST') OR NAMELIKE('*ST') OR NAMELIKE('S');
42
+ # 真阳线:CLOSE>REF(CLOSE,1);
43
+ # 筹码锁定:BARSLASTCOUNT(LFS>REF(LFS,1))>=2 AND LFS>=30;
44
+ # 浮筹比例:(WINNER(C*1.1)-WINNER(C*0.9))/WINNER(HHV(H,0))*100;
45
+ #
46
+ # JXN1:=5;
47
+ # JXN2:=10;
48
+ # M1:=MA(CLOSE,JXN1);
49
+ # M2:=MA(CLOSE,JXN2);
50
+ # 均线粘合:ABS(M1/M2-1)<0.01;
51
+ #
52
+ # {K线数据}
53
+ # X_HIGH:HIGH;
54
+ # X_LOW:LOW;
55
+ # X_OPEN:OPEN;
56
+ # X_CLOSE:CLOSE;
57
+ # X_VOL:VOL;
58
+ # X_AMOUNT:AMOUNT;
59
+ #
60
+ # {斜率}
61
+ # C_WIDTH:0.009499432279;
62
+ # C_PI:3.141592654;
@@ -0,0 +1,281 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # 缓存的数据
3
+ import json
4
+ import os
5
+ from functools import lru_cache
6
+ from typing import Dict, Any
7
+
8
+ import pandas as pd
9
+ from dateutil import parser
10
+ from pandas import DataFrame
11
+
12
+ import base
13
+ import exchange
14
+
15
+
16
+ @lru_cache(maxsize=None)
17
+ def securities() -> pd.DataFrame:
18
+ """
19
+ 证券列表
20
+ """
21
+ full_path = os.path.join(base.config.meta_path, 'securities.csv')
22
+ if not os.path.isfile(full_path):
23
+ return pd.DataFrame()
24
+ df = pd.read_csv(full_path)
25
+ # 转换为小写
26
+ df.columns = df.columns.str.lower()
27
+ return df[['code', 'name']]
28
+
29
+
30
+ @lru_cache(maxsize=None)
31
+ def block_list():
32
+ """
33
+ 板块列表
34
+ """
35
+ df = securities()
36
+ return df[df['code'].astype(str).str.startswith(('sh880', 'sh881'))]
37
+
38
+
39
+ def stock_name(code: str) -> str:
40
+ corrected_symbol = exchange.correct_security_code(code)
41
+ df = securities()
42
+ tmp = df[df['code'] == corrected_symbol]
43
+ name = tmp['name'].iloc[0]
44
+ return name
45
+
46
+
47
+ def klines(code: str) -> pd.DataFrame | None:
48
+ """
49
+ 获取缓存的日线数据
50
+ """
51
+ corrected_symbol = exchange.correct_security_code(code)
52
+ suffix_length = 3 # 修正拼写并明确表示后缀长度
53
+ symbol_directory = os.path.join(base.config.kline_path, corrected_symbol[:-suffix_length]) # 更清晰表达目录用途
54
+ file_extension = '.csv'
55
+ filename = f"{corrected_symbol}{file_extension}" # 使用f-string格式化
56
+ full_path = os.path.join(symbol_directory, filename)
57
+
58
+ if os.path.isfile(full_path):
59
+ return pd.read_csv(full_path)
60
+ return None
61
+
62
+
63
+ def get_period_name(period: str = 'D') -> str:
64
+ """
65
+ 根据周期标识返回中文名称
66
+
67
+ Parameters:
68
+ period (str): 周期标识 'W', 'M', 'Q', 'Y'
69
+
70
+ Returns:
71
+ str: 中文周期名称
72
+ """
73
+ period_names = {
74
+ 'W': '周',
75
+ 'M': '月',
76
+ 'Q': '季',
77
+ 'Y': '年',
78
+ 'D': '日'
79
+ }
80
+ period = period.upper()
81
+ return period_names.get(period, period)
82
+
83
+
84
+ def convert_klines_trading(klines, period='D'):
85
+ """
86
+ 基于实际交易日的K线转换函数
87
+
88
+ Parameters:
89
+ klines (pd.DataFrame): 日线数据
90
+ period (str): 目标周期
91
+ 'W' - 周线
92
+ 'M' - 月线
93
+ 'Q' - 季度线
94
+ 'Y' - 年线
95
+
96
+ Returns:
97
+ pd.DataFrame: 转换后的K线数据,date字段表示实际交易日
98
+ """
99
+ if klines.empty:
100
+ return klines.copy()
101
+
102
+ df = klines.copy()
103
+ df['date'] = pd.to_datetime(df['date'])
104
+ df = df.sort_values('date').reset_index(drop=True)
105
+
106
+ # 直接使用简化的周期标识
107
+ period = period.upper()
108
+ if period not in ['W', 'M', 'Q', 'Y']:
109
+ return df
110
+
111
+ # 根据周期分组
112
+ groups = df['date'].dt.to_period(period)
113
+
114
+ # 聚合数据,date字段保留实际的交易日
115
+ result = df.groupby(groups).agg({
116
+ 'date': 'last', # 实际最后一个交易日
117
+ 'open': 'first',
118
+ 'high': 'max',
119
+ 'low': 'min',
120
+ 'close': 'last',
121
+ 'volume': 'sum',
122
+ 'amount': 'sum'
123
+ }).reset_index(drop=True)
124
+
125
+ return result
126
+
127
+
128
+ # SectorFilename 板块缓存文件名
129
+ def sector_filename(date: str = '') -> str:
130
+ """
131
+ 板块缓存文件名
132
+ """
133
+ name = 'blocks'
134
+ cache_date = date.strip()
135
+ if len(cache_date) == 0:
136
+ cache_date = exchange.last_trade_date()
137
+ filename = os.path.join(base.config.meta_path, f'{name}.{cache_date}')
138
+ return filename
139
+
140
+
141
+ @lru_cache(maxsize=None)
142
+ def get_sector_list() -> pd.DataFrame:
143
+ """
144
+ 获取板块列表
145
+ """
146
+ sfn = sector_filename()
147
+ df = pd.read_csv(sfn)
148
+ df['code'] = 'sh' + df['code'].astype(str)
149
+ return df
150
+
151
+
152
+ def get_sector_constituents(code: str) -> list[str]:
153
+ """
154
+ 获取板块成分股列表
155
+ """
156
+ code = code.strip()
157
+ security_code = exchange.correct_security_code(code)
158
+ df = get_sector_list().copy()
159
+ cs = df[df['code'] == security_code]['ConstituentStocks']
160
+ list = []
161
+ if cs.empty:
162
+ return list
163
+ cs1 = cs.iloc[0]
164
+ ConstituentStocks = json.loads(cs1)
165
+ list = []
166
+ for sc in ConstituentStocks:
167
+ sc = sc.strip()
168
+ sc = exchange.correct_security_code(sc)
169
+ list.append(sc)
170
+ return list
171
+
172
+
173
+ def date_format(date: str, layout: str = '%Y-%m-%d') -> str:
174
+ dt = parser.parse(date) # 自动识别各种常见日期格式
175
+ return dt.strftime(layout)
176
+
177
+
178
+ @lru_cache(maxsize=None)
179
+ def get_minutes_data(code: str, date: str) -> DataFrame | None:
180
+ """获取分时数据"""
181
+ code = code.strip()
182
+ corrected_symbol = exchange.correct_security_code(code)
183
+ file_extension = '.csv'
184
+ filename = f"{corrected_symbol}{file_extension}" # 使用f-string格式化
185
+ cache_date = date.strip()
186
+ if len(cache_date) == 0:
187
+ cache_date = exchange.last_trade_date()
188
+ # 获取年份
189
+ cache_date = date_format(cache_date, layout='%Y%m%d')
190
+ year = cache_date[:4]
191
+ base_path = os.path.join(base.config.data_path, 'minutes')
192
+ full_path = os.path.join(base_path, year, cache_date, filename)
193
+
194
+ if os.path.isfile(full_path):
195
+ return pd.read_csv(full_path)
196
+ return None
197
+
198
+
199
+ @lru_cache(maxsize=None)
200
+ def cache_f10(date: str = None) -> DataFrame:
201
+ factor_name = 'f10'
202
+ trade_date = date or exchange.last_trade_date()
203
+ file_extension = exchange.fix_trade_date(trade_date)
204
+ filename = f"{factor_name}.{file_extension}"
205
+ year = trade_date[:4]
206
+ base_path = os.path.join(base.config.data_path, 'flash')
207
+ return pd.read_csv(os.path.join(base_path, year, filename))
208
+
209
+
210
+ def get_f10(code: str, date: str = None) -> Dict[str, Any]:
211
+ """
212
+ 获取f10数据
213
+ Args:
214
+ code: 证券代码
215
+ date: 日期
216
+
217
+ Returns:
218
+ 返回f10数据
219
+ """
220
+ security_code = exchange.correct_security_code(code)
221
+ df = cache_f10(date)
222
+ result_df = df[df['Code'] == security_code]
223
+ if result_df.empty:
224
+ return {}
225
+
226
+ # 取第一行,转为字典
227
+ return result_df.iloc[0].to_dict()
228
+
229
+
230
+ @lru_cache(maxsize=None)
231
+ def get_tick_transaction(code: str, date: str) -> DataFrame | None:
232
+ """获取分时"""
233
+ code = code.strip()
234
+ corrected_symbol = exchange.correct_security_code(code)
235
+ file_extension = '.csv'
236
+ filename = f"{corrected_symbol}{file_extension}" # 使用f-string格式化
237
+ cache_date = date.strip()
238
+ if len(cache_date) == 0:
239
+ cache_date = exchange.last_trade_date()
240
+ # 获取年份
241
+ cache_date = date_format(cache_date, layout='%Y%m%d')
242
+ year = cache_date[:4]
243
+ base_path = os.path.join(base.config.data_path, 'trans')
244
+ full_path = os.path.join(base_path, year, cache_date, filename)
245
+
246
+ if os.path.isfile(full_path):
247
+ return pd.read_csv(full_path)
248
+ return None
249
+
250
+
251
+ if __name__ == '__main__':
252
+ print(base.get_quant1x_config_filename())
253
+ print('data_path', base.config.data_path)
254
+ print('kline_path', base.config.kline_path)
255
+ code = '600600'
256
+ df = klines(code)
257
+ print(df)
258
+ stock_name = stock_name(code)
259
+ print(stock_name)
260
+ security_list = securities()
261
+ print(security_list)
262
+ index_list = block_list()
263
+ print(index_list)
264
+ sfn = sector_filename()
265
+ df = pd.read_csv(sfn)
266
+ print(df)
267
+ print(df['code'].dtype)
268
+ df['code'] = 'sh' + df['code'].astype(str)
269
+ s1 = df[df['code'] == 'sh881478']
270
+ print(s1)
271
+
272
+ l1 = get_sector_constituents('880675')
273
+ print(l1)
274
+ print(type(l1))
275
+
276
+ df2 = get_minutes_data(code, date='2025-06-20')
277
+ print(df2)
278
+ df3 = get_tick_transaction(code, date='2025-06-20')
279
+ print(df3)
280
+ df4 = get_f10(code)
281
+ print(df4)
@@ -0,0 +1,52 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ import os
4
+
5
+ import yaml
6
+ from icecream import ic
7
+
8
+
9
+ class DictToClass(object):
10
+ """
11
+ 将字典准换为 class 类型
12
+ """
13
+
14
+ @classmethod
15
+ def to_object(cls, _obj):
16
+ _obj_ = type('new', (object,), _obj)
17
+ [setattr(_obj_, key, cls.to_object(value)) if isinstance(value, dict) else setattr(_obj_, key, value) for
18
+ key, value in _obj.items()]
19
+ return _obj_
20
+
21
+
22
+ class ReadConfigFiles(object):
23
+ def __init__(self):
24
+ """
25
+ 获取当前工作路径
26
+ """
27
+ self.works_path = os.path.dirname(os.path.realpath(__file__))
28
+
29
+ @classmethod
30
+ def open_file(cls):
31
+ """
32
+ 读取当前工作目录下cfg.yaml文件内容,并返回字典类型
33
+ :return:
34
+ """
35
+ return yaml.load(
36
+ open(os.path.join(cls().works_path, r'cfg.yaml'), 'r', encoding='utf-8').read(), Loader=yaml.FullLoader
37
+ )
38
+
39
+ @classmethod
40
+ def cfg(cls, item=None):
41
+ """
42
+ 调用该方法获取需要的配置,item如果为None,返回则是全部配置
43
+ :param item:
44
+ :return:
45
+ """
46
+ return DictToClass.to_object(cls.open_file().get(item) if item else cls.open_file())
47
+
48
+
49
+ if __name__ == '__main__':
50
+ cfg = ReadConfigFiles.cfg()
51
+ # 测试输出
52
+ ic(cfg.host.group)
@@ -0,0 +1,25 @@
1
+ # -*- coding: UTF-8 -*-
2
+ from multiprocessing import cpu_count
3
+
4
+
5
+ def cpu_num() -> int:
6
+ """
7
+ 获得CPU核数
8
+ :return:
9
+ """
10
+ return cpu_count()
11
+
12
+
13
+ def max_procs() -> int:
14
+ """
15
+ 最大可使用CPU核数
16
+ 默认使用一半的CPU资源
17
+ :return:
18
+ """
19
+ num = cpu_num()
20
+ return int(num / 2)
21
+
22
+
23
+ if __name__ == '__main__':
24
+ print(cpu_num())
25
+ print(max_procs())
@@ -0,0 +1,27 @@
1
+ # -*- coding: UTF-8 -*-
2
+ import os
3
+ import sys
4
+
5
+
6
+ def project_path(package: str = "quant1x", filename: str = '') -> str:
7
+ filename = filename.strip()
8
+ if len(filename) == 0:
9
+ # filename = __file__
10
+ raise Exception('filename is empty')
11
+ pos = filename.rfind(package)
12
+ project_path = filename[:pos - 1]
13
+ root_path = os.path.abspath(project_path)
14
+ return root_path
15
+
16
+
17
+ def redirect(package: str = "quant1x", filename: str = ''):
18
+ """
19
+ 重定向于当前工程目录
20
+ :return:
21
+ """
22
+ root_path = project_path(package, filename)
23
+ sys.path.insert(0, root_path)
24
+
25
+
26
+ if __name__ == '__main__':
27
+ sys.exit(redirect())