quant1x 0.7.1__tar.gz → 0.7.2__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 (67) hide show
  1. {quant1x-0.7.1 → quant1x-0.7.2}/PKG-INFO +3 -3
  2. {quant1x-0.7.1 → quant1x-0.7.2}/README.md +2 -2
  3. quant1x-0.7.2/quant1x/cache/__init__.py +7 -0
  4. quant1x-0.7.2/quant1x/cache/f10.py +36 -0
  5. quant1x-0.7.2/quant1x/cache/market.py +136 -0
  6. quant1x-0.7.2/quant1x/cache/sector.py +77 -0
  7. quant1x-0.7.2/quant1x/cache/security.py +56 -0
  8. quant1x-0.7.2/quant1x/encoding/yaml.py +101 -0
  9. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/indicators/__init__.py +0 -2
  10. quant1x-0.7.2/quant1x/indicators/cdtd.py +80 -0
  11. quant1x-0.7.2/quant1x/indicators/f89k.py +162 -0
  12. quant1x-0.7.2/quant1x/indicators/hjk.py +72 -0
  13. quant1x-0.7.2/quant1x/indicators/p2fb.py +96 -0
  14. quant1x-0.7.2/quant1x/level1/__init__.py +3 -0
  15. quant1x-0.7.2/quant1x/level1/config.py +330 -0
  16. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/level1/protocol.py +29 -12
  17. {quant1x-0.7.1/quant1x/io → quant1x-0.7.2/quant1x/log}/__init__.py +2 -2
  18. {quant1x-0.7.1/quant1x/io → quant1x-0.7.2/quant1x/log}/logger.py +28 -4
  19. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/version.py +25 -6
  20. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x.egg-info/PKG-INFO +3 -3
  21. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x.egg-info/SOURCES.txt +13 -5
  22. quant1x-0.7.2/tests/test_cache.py +48 -0
  23. quant1x-0.7.1/quant1x/cache.py +0 -363
  24. quant1x-0.7.1/quant1x/encoding/yaml.py +0 -52
  25. quant1x-0.7.1/quant1x/level1/__init__.py +0 -7
  26. quant1x-0.7.1/quant1x/level1/config.py +0 -322
  27. quant1x-0.7.1/quant1x/market.py +0 -56
  28. {quant1x-0.7.1 → quant1x-0.7.2}/LICENSE +0 -0
  29. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/__init__.py +0 -0
  30. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/config/__init__.py +0 -0
  31. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/config/config.py +0 -0
  32. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/device.py +0 -0
  33. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/devp.py +0 -0
  34. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/encoding/__init__.py +0 -0
  35. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/exchange/__init__.py +0 -0
  36. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/exchange/code.py +0 -0
  37. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/exchange/markets.py +0 -0
  38. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/exchange/security.py +0 -0
  39. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/formula/__init__.py +0 -0
  40. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/formula/formula.py +0 -0
  41. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/formula/formula_plus.py +0 -0
  42. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/indicators/ma1x.py +0 -0
  43. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/level1/client.py +0 -0
  44. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/level1/security_list.py +0 -0
  45. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/net/__init__.py +0 -0
  46. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/net/connection_pool.py +0 -0
  47. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/net/endpoint.py +0 -0
  48. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/net/operation_handler.py +0 -0
  49. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/network.py +0 -0
  50. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/numerics.py +0 -0
  51. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/std/__init__.py +0 -0
  52. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/std/pattern.py +0 -0
  53. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/system.py +0 -0
  54. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/timestamp.py +0 -0
  55. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/util/__init__.py +0 -0
  56. {quant1x-0.7.1/quant1x → quant1x-0.7.2/quant1x/util}/chart.py +0 -0
  57. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x/util/font.py +0 -0
  58. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x.egg-info/dependency_links.txt +0 -0
  59. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x.egg-info/not-zip-safe +0 -0
  60. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x.egg-info/requires.txt +0 -0
  61. {quant1x-0.7.1 → quant1x-0.7.2}/quant1x.egg-info/top_level.txt +0 -0
  62. {quant1x-0.7.1 → quant1x-0.7.2}/setup.cfg +0 -0
  63. {quant1x-0.7.1 → quant1x-0.7.2}/setup.py +0 -0
  64. {quant1x-0.7.1 → quant1x-0.7.2}/tests/test_connection_pool.py +0 -0
  65. {quant1x-0.7.1 → quant1x-0.7.2}/tests/test_handshake.py +0 -0
  66. {quant1x-0.7.1 → quant1x-0.7.2}/tests/test_protocol_fixtures.py +0 -0
  67. {quant1x-0.7.1 → quant1x-0.7.2}/tests/test_protocol_real_network.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quant1x
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Summary: Quant1X量化研究
5
5
  Home-page: https://gitee.com/quant1x/quant1x
6
6
  Author: wangfeng
@@ -97,7 +97,7 @@ Quant1X 是一个多语言量化交易框架,支持 C++、Go、Rust、Python
97
97
  | Python | 3.12+ | 3.12.x |
98
98
  | Go | 1.25+ | 1.25.x |
99
99
  | Rust | 1.88+ | 1.90+ (2021) |
100
- | C++ | C++20 | GCC 14.3+/Clang 18+/MSVC 14.3+ |
100
+ | C++ | C++20 | GCC 13+/Clang 17+/MSVC 14.3+ |
101
101
 
102
102
  ## 🚀 快速开始
103
103
 
@@ -106,7 +106,7 @@ Quant1X 是一个多语言量化交易框架,支持 C++、Go、Rust、Python
106
106
  ## 1.1 默认均为64位操作系统
107
107
  | python | golang | rust | c++ |
108
108
  |:-------|:-------|:-----------|:----------------------------|
109
- | 3.12.x | 1.25.x | 1.90+/2021 | gcc14.3+/clang18+/msvc14.3+ |
109
+ | 3.12.x | 1.25.x | 1.90+/2021 | gcc13+/clang17+/msvc14.3+ |
110
110
 
111
111
  ## 1.2 环境安装推荐使用brew
112
112
  安装brew时需要注意避免使用root权限
@@ -36,7 +36,7 @@ Quant1X 是一个多语言量化交易框架,支持 C++、Go、Rust、Python
36
36
  | Python | 3.12+ | 3.12.x |
37
37
  | Go | 1.25+ | 1.25.x |
38
38
  | Rust | 1.88+ | 1.90+ (2021) |
39
- | C++ | C++20 | GCC 14.3+/Clang 18+/MSVC 14.3+ |
39
+ | C++ | C++20 | GCC 13+/Clang 17+/MSVC 14.3+ |
40
40
 
41
41
  ## 🚀 快速开始
42
42
 
@@ -45,7 +45,7 @@ Quant1X 是一个多语言量化交易框架,支持 C++、Go、Rust、Python
45
45
  ## 1.1 默认均为64位操作系统
46
46
  | python | golang | rust | c++ |
47
47
  |:-------|:-------|:-----------|:----------------------------|
48
- | 3.12.x | 1.25.x | 1.90+/2021 | gcc14.3+/clang18+/msvc14.3+ |
48
+ | 3.12.x | 1.25.x | 1.90+/2021 | gcc13+/clang17+/msvc14.3+ |
49
49
 
50
50
  ## 1.2 环境安装推荐使用brew
51
51
  安装brew时需要注意避免使用root权限
@@ -0,0 +1,7 @@
1
+ # -*- coding: UTF-8 -*-
2
+ # 缓存的数据
3
+
4
+ from .security import securities, stock_name
5
+ from .market import klines, get_period_name, convert_klines_trading, get_minutes_data, get_tick_transaction, date_format
6
+ from .sector import block_list, sector_filename, get_sector_list, get_sector_constituents
7
+ from .f10 import cache_f10, get_f10
@@ -0,0 +1,36 @@
1
+ # -*- coding: UTF-8 -*-
2
+ import os
3
+ from functools import lru_cache
4
+ from typing import Dict, Any
5
+ import pandas as pd
6
+ from pandas import DataFrame
7
+ from .. import exchange, config
8
+
9
+ @lru_cache(maxsize=None)
10
+ def cache_f10(date: str = None) -> DataFrame:
11
+ factor_name = 'f10'
12
+ trade_date = date or exchange.last_trade_date()
13
+ file_extension = exchange.fix_trade_date(trade_date)
14
+ filename = f"{factor_name}.{file_extension}"
15
+ year = trade_date[:4]
16
+ base_path = os.path.join(config.quant1x_config.data_path, 'flash')
17
+ return pd.read_csv(os.path.join(base_path, year, filename))
18
+
19
+ def get_f10(code: str, date: str = None) -> Dict[str, Any]:
20
+ """
21
+ 获取f10数据
22
+ Args:
23
+ code: 证券代码
24
+ date: 日期
25
+
26
+ Returns:
27
+ 返回f10数据
28
+ """
29
+ security_code = exchange.correct_security_code(code)
30
+ df = cache_f10(date)
31
+ result_df = df[df['Code'] == security_code]
32
+ if result_df.empty:
33
+ return {}
34
+
35
+ # 取第一行,转为字典
36
+ return result_df.iloc[0].to_dict()
@@ -0,0 +1,136 @@
1
+ # -*- coding: UTF-8 -*-
2
+ import os
3
+ from functools import lru_cache
4
+ import pandas as pd
5
+ import inflection
6
+ from dateutil import parser
7
+ from pandas import DataFrame
8
+ from .. import exchange, config
9
+
10
+ def klines(code: str, freq:str = 'D') -> pd.DataFrame | None:
11
+ """
12
+ 获取缓存的日线数据
13
+ """
14
+ corrected_symbol = exchange.correct_security_code(code)
15
+ suffix_length = 3 # 修正拼写并明确表示后缀长度
16
+ freq_path = 'day' if freq == 'D' else freq
17
+ symbol_directory = os.path.join(config.quant1x_config.data_path, freq_path, corrected_symbol[:-suffix_length]) # 更清晰表达目录用途
18
+ file_extension = '.csv'
19
+ filename = f"{corrected_symbol}{file_extension}" # 使用f-string格式化
20
+ full_path = os.path.join(symbol_directory, filename)
21
+
22
+ if os.path.isfile(full_path):
23
+ df = pd.read_csv(full_path)
24
+ # 转换所有列名为 snake_case
25
+ df.columns = [inflection.underscore(col) for col in df.columns]
26
+ return df
27
+ return None
28
+
29
+ def get_period_name(period: str = 'D') -> str:
30
+ """
31
+ 根据周期标识返回中文名称
32
+
33
+ Parameters:
34
+ period (str): 周期标识 'W', 'M', 'Q', 'Y'
35
+
36
+ Returns:
37
+ str: 中文周期名称
38
+ """
39
+ period_names = {
40
+ 'W': '周',
41
+ 'M': '月',
42
+ 'Q': '季',
43
+ 'Y': '年',
44
+ 'D': '日'
45
+ }
46
+ period = period.upper()
47
+ return period_names.get(period, period)
48
+
49
+ def convert_klines_trading(klines, period='D'):
50
+ """
51
+ 基于实际交易日的K线转换函数
52
+
53
+ Parameters:
54
+ klines (pd.DataFrame): 日线数据
55
+ period (str): 目标周期
56
+ 'W' - 周线
57
+ 'M' - 月线
58
+ 'Q' - 季度线
59
+ 'Y' - 年线
60
+
61
+ Returns:
62
+ pd.DataFrame: 转换后的K线数据,date字段表示实际交易日
63
+ """
64
+ if klines.empty:
65
+ return klines.copy()
66
+
67
+ df = klines.copy()
68
+ df['date'] = pd.to_datetime(df['date'])
69
+ df = df.sort_values('date').reset_index(drop=True)
70
+
71
+ # 直接使用简化的周期标识
72
+ period = period.upper()
73
+ if period not in ['W', 'M', 'Q', 'Y']:
74
+ return df
75
+
76
+ # 根据周期分组
77
+ groups = df['date'].dt.to_period(period)
78
+
79
+ # 聚合数据,date字段保留实际的交易日
80
+ result = df.groupby(groups).agg({
81
+ 'date': 'last', # 实际最后一个交易日
82
+ 'open': 'first',
83
+ 'high': 'max',
84
+ 'low': 'min',
85
+ 'close': 'last',
86
+ 'volume': 'sum',
87
+ 'amount': 'sum'
88
+ }).reset_index(drop=True)
89
+
90
+ return result
91
+
92
+ def date_format(date: str, layout: str = '%Y-%m-%d') -> str:
93
+ dt = parser.parse(date) # 自动识别各种常见日期格式
94
+ return dt.strftime(layout)
95
+
96
+ @lru_cache(maxsize=None)
97
+ def get_minutes_data(code: str, date: str) -> DataFrame | None:
98
+ """获取分时数据"""
99
+ code = code.strip()
100
+ corrected_symbol = exchange.correct_security_code(code)
101
+ file_extension = '.csv'
102
+ filename = f"{corrected_symbol}{file_extension}" # 使用f-string格式化
103
+ cache_date = date.strip()
104
+ if len(cache_date) == 0:
105
+ cache_date = exchange.last_trade_date()
106
+ # 获取年份
107
+ cache_date = date_format(cache_date, layout='%Y%m%d')
108
+ year = cache_date[:4]
109
+ base_path = os.path.join(config.quant1x_config.data_path, 'minutes')
110
+ full_path = os.path.join(base_path, year, cache_date, filename)
111
+
112
+ if os.path.isfile(full_path):
113
+ return pd.read_csv(full_path)
114
+ return None
115
+
116
+ @lru_cache(maxsize=None)
117
+ def get_tick_transaction(code: str, date: str) -> DataFrame | None:
118
+ """获取分时"""
119
+ code = code.strip()
120
+ corrected_symbol = exchange.correct_security_code(code)
121
+ file_extension = '.csv'
122
+ filename = f"{corrected_symbol}{file_extension}" # 使用f-string格式化
123
+ cache_date = date.strip()
124
+ if len(cache_date) == 0:
125
+ cache_date = exchange.last_trade_date()
126
+ # 获取年份
127
+ cache_date = date_format(cache_date, layout='%Y%m%d')
128
+ year = cache_date[:4]
129
+ base_path = os.path.join(config.quant1x_config.data_path, 'trans')
130
+ full_path = os.path.join(base_path, year, cache_date, filename)
131
+
132
+ if os.path.isfile(full_path):
133
+ df = pd.read_csv(full_path)
134
+ df.columns = [col.lower() for col in df.columns]
135
+ return df
136
+ return None
@@ -0,0 +1,77 @@
1
+ # -*- coding: UTF-8 -*-
2
+ import os
3
+ import json
4
+ from functools import lru_cache
5
+ import pandas as pd
6
+ from .. import exchange, config
7
+ from .security import securities
8
+
9
+ # SectorFilename 板块缓存文件名
10
+ def sector_filename(date: str = '') -> str:
11
+ """
12
+ 板块缓存文件名
13
+ """
14
+ name = 'blocks'
15
+ cache_date = date.strip()
16
+ if len(cache_date) == 0:
17
+ cache_date = exchange.last_trade_date()
18
+ filename = os.path.join(config.quant1x_config.meta_path, f'{name}.{cache_date}')
19
+ if not os.path.isfile(filename):
20
+ # fallback to blocks.csv
21
+ filename = os.path.join(config.quant1x_config.meta_path, 'blocks.csv')
22
+ return filename
23
+
24
+ @lru_cache(maxsize=None)
25
+ def get_sector_list() -> pd.DataFrame:
26
+ """
27
+ 获取板块列表
28
+ """
29
+ sfn = sector_filename()
30
+ try:
31
+ df = pd.read_csv(sfn)
32
+ except FileNotFoundError:
33
+ # fallback: find latest blocks.* file under meta_path
34
+ meta_dir = os.path.dirname(sfn)
35
+ prefix = os.path.join(meta_dir, 'blocks.')
36
+ candidates = [f for f in os.listdir(meta_dir) if f.startswith('blocks.')]
37
+ if not candidates:
38
+ raise
39
+ # pick the latest by modification time
40
+ candidates_full = [os.path.join(meta_dir, f) for f in candidates]
41
+ candidates_full.sort(key=lambda p: os.path.getmtime(p), reverse=True)
42
+ sfn2 = candidates_full[0]
43
+ df = pd.read_csv(sfn2)
44
+ # 补全sh前缀
45
+ s = df['code'].astype(str)
46
+ df['code'] = s.where(s.str.startswith('sh'), 'sh' + s)
47
+ return df
48
+
49
+ @lru_cache(maxsize=None)
50
+ def block_list():
51
+ """
52
+ 板块列表
53
+ """
54
+ df = securities()
55
+ if df.empty or 'code' not in df.columns:
56
+ return pd.DataFrame(columns=df.columns if not df.empty else ['code', 'name'])
57
+ return df[df['code'].astype(str).str.startswith(('sh880', 'sh881'))]
58
+
59
+ def get_sector_constituents(code: str) -> list[str]:
60
+ """
61
+ 获取板块成分股列表
62
+ """
63
+ code = code.strip()
64
+ security_code = exchange.correct_security_code(code)
65
+ df = get_sector_list().copy()
66
+ cs = df[df['code'] == security_code]['ConstituentStocks']
67
+ list = []
68
+ if cs.empty:
69
+ return list
70
+ cs1 = cs.iloc[0]
71
+ ConstituentStocks = json.loads(cs1)
72
+ list = []
73
+ for sc in ConstituentStocks:
74
+ sc = sc.strip()
75
+ sc = exchange.correct_security_code(sc)
76
+ list.append(sc)
77
+ return list
@@ -0,0 +1,56 @@
1
+ # -*- coding: UTF-8 -*-
2
+ import os
3
+ from functools import lru_cache
4
+ import pandas as pd
5
+ from .. import exchange, config
6
+
7
+ @lru_cache(maxsize=None)
8
+ def securities() -> pd.DataFrame:
9
+ """
10
+ 证券列表
11
+ """
12
+ full_path = os.path.join(config.quant1x_config.meta_path, 'securities.csv')
13
+ if not os.path.isfile(full_path):
14
+ return pd.DataFrame(columns=['code', 'name'])
15
+ # with open(full_path, 'rb') as f:
16
+ # f.seek(87287 - 13)
17
+ # print('Bytes around 85710:', f.read(19).hex(' '))
18
+ df = pd.read_csv(full_path)
19
+ # 转换为小写
20
+ df.columns = df.columns.str.lower()
21
+ # 兼容多种列名:优先匹配 'code' 和 'name',否则尝试常见替代列名,最终回退到前两列
22
+ cols = list(df.columns)
23
+ code_candidates = ['code', 'symbol', 'securitycode', 'security_code', 'sec_code', 'sid']
24
+ name_candidates = ['name', 'sec_name', 'security_name', 'secname', 'stock_name']
25
+
26
+ def find_first(candidates, cols):
27
+ for c in candidates:
28
+ if c in cols:
29
+ return c
30
+ return None
31
+
32
+ code_col = find_first(code_candidates, cols) or (cols[0] if cols else None)
33
+ name_col = find_first(name_candidates, cols) or (cols[1] if len(cols) > 1 else (cols[0] if cols else None))
34
+
35
+ if code_col is None or name_col is None:
36
+ return pd.DataFrame(columns=['code', 'name'])
37
+
38
+ # 返回时保持列名为标准名称 'code' 和 'name',以便后续代码不变
39
+ out = df[[code_col, name_col]].copy()
40
+ out.columns = ['code', 'name']
41
+ return out
42
+
43
+ def stock_name(code: str) -> str:
44
+ corrected_symbol = exchange.correct_security_code(code)
45
+ df = securities()
46
+ if df.empty:
47
+ return ""
48
+ # ensure types align
49
+ try:
50
+ tmp = df[df['code'].astype(str) == str(corrected_symbol)]
51
+ except Exception:
52
+ tmp = df[df['code'] == corrected_symbol]
53
+ if tmp.empty:
54
+ return ""
55
+ name = tmp['name'].iloc[0]
56
+ return name
@@ -0,0 +1,101 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ import os
4
+ import yaml
5
+ from types import SimpleNamespace
6
+
7
+ try:
8
+ from yaml import CSafeLoader as Loader, CSafeDumper as Dumper
9
+ except ImportError:
10
+ from yaml import SafeLoader as Loader, SafeDumper as Dumper
11
+
12
+
13
+ def to_namespace(data):
14
+ """
15
+ 递归将字典转换为 SimpleNamespace,支持属性访问
16
+ """
17
+ if isinstance(data, dict):
18
+ return SimpleNamespace(**{k: to_namespace(v) for k, v in data.items()})
19
+ elif isinstance(data, list):
20
+ return [to_namespace(i) for i in data]
21
+ return data
22
+
23
+
24
+ def load(path, to_object=False):
25
+ """
26
+ 读取YAML文件
27
+ :param path: 文件路径
28
+ :param to_object: 是否转换为对象(SimpleNamespace)
29
+ :return: 字典或对象
30
+ """
31
+ if not os.path.exists(path):
32
+ return None
33
+
34
+ with open(path, 'r', encoding='utf-8') as f:
35
+ data = yaml.load(f, Loader=Loader)
36
+
37
+ if to_object:
38
+ return to_namespace(data)
39
+ return data
40
+
41
+
42
+ def dump(data, path):
43
+ """
44
+ 保存为YAML文件
45
+ :param data: 数据
46
+ :param path: 文件路径
47
+ """
48
+ # 注意:SimpleNamespace 不能直接被 yaml dump,如果需要保存对象,需先转回 dict
49
+ # 这里假设 data 是 dict, list 或基础类型
50
+ with open(path, 'w', encoding='utf-8') as f:
51
+ yaml.dump(data, f, Dumper=Dumper, allow_unicode=True)
52
+
53
+
54
+ class ReadConfigFiles(object):
55
+ """
56
+ 带缓存的配置文件读取类
57
+ """
58
+ _caches = {} # path -> {'mtime': float, 'data': dict}
59
+
60
+ @classmethod
61
+ def cfg(cls, path, item=None):
62
+ """
63
+ 调用该方法获取需要的配置,带缓存机制
64
+ :param path: 配置文件路径
65
+ :param item: 配置项名称
66
+ :return: SimpleNamespace 对象或具体值
67
+ """
68
+ if not path or not os.path.exists(path):
69
+ return None
70
+
71
+ # 检查文件修改时间,如果有变化则重新加载
72
+ try:
73
+ mtime = os.path.getmtime(path)
74
+ cache = cls._caches.get(path)
75
+
76
+ if cache is None or mtime > cache['mtime']:
77
+ data = load(path)
78
+ cls._caches[path] = {'mtime': mtime, 'data': data}
79
+ else:
80
+ data = cache['data']
81
+ except Exception:
82
+ return None
83
+
84
+ if not data:
85
+ return None
86
+
87
+ if item:
88
+ val = data.get(item)
89
+ return to_namespace(val) if isinstance(val, (dict, list)) else val
90
+
91
+ return to_namespace(data)
92
+
93
+
94
+ if __name__ == '__main__':
95
+ try:
96
+ from icecream import ic
97
+ # 示例:需要传入具体路径
98
+ # cfg = ReadConfigFiles.cfg('path/to/config.yaml')
99
+ pass
100
+ except ImportError:
101
+ pass
@@ -1,4 +1,2 @@
1
1
  #!/usr/bin/python
2
2
  # -*- coding: UTF-8 -*-
3
-
4
- from quant1x.indicators.ma1x import *
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: UTF-8 -*-
3
+ import pandas
4
+
5
+ from quant1x.formula.formula import *
6
+
7
+ np.seterr(divide='ignore', invalid='ignore')
8
+
9
+
10
+ def cdtd(data: pandas.DataFrame):
11
+ """
12
+ 抄底逃顶
13
+ :param data:
14
+ :return:
15
+ """
16
+ df = data.copy()
17
+ OPEN = df['open']
18
+ CLOSE = df['close']
19
+ HIGH = df['high']
20
+ LOW = df['low']
21
+ VOL = df['volume']
22
+ AMOUNT = df['amount']
23
+
24
+ # N1:=3;
25
+ N1 = 3
26
+ # N2:=9;
27
+ N2 = 9
28
+ # N3:=27;
29
+ N3 = 27
30
+ # N4:=5;
31
+ N4 = 5
32
+ # HHVLLV3:=HHV(HIGH,N3)-LLV(LOW,N3);
33
+ HHVLLV3 = HHV(HIGH, N3) - LLV(LOW, N3)
34
+ # df['cdtd.h3'] = HHV(HIGH, N3)
35
+ # df['cdtd.l3'] = LLV(LOW, N3)
36
+ # df['cdtd.hl3'] = HHVLLV3
37
+ # CLLV3:=CLOSE-LLV(LOW,N3);
38
+ CLLV3 = CLOSE - LLV(LOW, N3)
39
+ # RSV1:=(CLOSE-LLV(LOW,N2))/(HHV(HIGH,N2)-LLV(LOW,N2))*100;
40
+ RSV1 = (CLOSE - LLV(LOW, N2)) / (HHV(HIGH, N2) - LLV(LOW, N2)) * 100
41
+ # RSV2:=CLLV3/HHVLLV3*100;
42
+ RSV2 = CLLV3 / HHVLLV3 * 100
43
+ # WEN:=N1*SMA(RSV2,N4,1)-2*SMA(SMA(RSV2,N4,1),N1,1);
44
+ WEN = N1 * SMA(RSV2, N4, 1) - 2 * SMA(SMA(RSV2, N4, 1), N1, 1)
45
+ df['cdtd.wen'] = WEN
46
+ # J1:=SMA(RSV1,N1,1);
47
+ J1 = SMA(RSV1, N1, 1)
48
+ # J2:=SMA(J1,N1,1);
49
+ J2 = SMA(J1, N1, 1)
50
+ # W1:=SMA(RSV2,N1,1);
51
+ W1 = SMA(RSV2, N1, 1)
52
+ # W2:=SMA(W1,N1,1);
53
+ W2 = SMA(W1, N1, 1)
54
+ # 强弱界线:49,DOTLINE,LINETHICK1,COLOR9966CC;
55
+ # 顶:100, DOTLINE,COLORCCFF00;
56
+ # 底:0, DOTLINE, COLORRED;
57
+ # 趋势线:WEN,LINETHICK1,COLORFF84FF;
58
+ # 卖出:=CROSS(J2,J1) AND J2>85;
59
+ S1 = CROSS(J2, J1)
60
+ S2 = J2 > 85
61
+ S = S1 & S2
62
+ df['cdtd.S1'] = S
63
+ # 卖点预警线:90,DOTLINE,LINETHICK1,COLORBLUE;
64
+ # DRAWICON(卖出, 70, 2);
65
+ # 买入:=趋势线<REF(趋势线,1) AND 趋势线<=5;
66
+ B1 = WEN < REF(WEN, 1)
67
+ B2 = WEN <= 5
68
+ B = B1 & B2
69
+ df['cdtd.B'] = B
70
+ # 买点预警线:10,DOTLINE,LINETHICK1,COLORWHITE;
71
+ # DRAWICON(买入, 30, 1);
72
+ # G1:=W1{,LINETHICK2,COLORWHITE};
73
+ # G2:=W2{,LINETHICK2,COLORCYAN};
74
+ # STICKLINE(趋势线>=85,100,趋势线,5,1),COLORGREEN;
75
+ # STICKLINE(趋势线<=5,0,趋势线,5,1),COLORYELLOW;
76
+ df['cdtd.S2'] = B2
77
+ # STICKLINE(COUNT(趋势线<REF(趋势线,1) AND 趋势线<=5,2)=2,0,20,8,0),COLORRED;
78
+ df['cdtd.S3'] = COUNT(B1 & B2, 2) == 2
79
+ # STICKLINE(CROSS(J2,J1) AND J2>=85,100,80,8,0),COLORGREEN;
80
+ return df