quantcli 0.2.1__tar.gz → 0.2.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.
- {quantcli-0.2.1/quantcli.egg-info → quantcli-0.2.2}/PKG-INFO +1 -1
- {quantcli-0.2.1 → quantcli-0.2.2}/pyproject.toml +1 -1
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/cli.py +6 -2
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/core/data.py +3 -3
- {quantcli-0.2.1 → quantcli-0.2.2/quantcli.egg-info}/PKG-INFO +1 -1
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_data_manager.py +9 -7
- {quantcli-0.2.1 → quantcli-0.2.2}/LICENSE +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/README.md +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/core/__init__.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/core/backtest.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/core/factor.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/__init__.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/akshare.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/baostock.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/base.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/cache.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/fundamentals/__init__.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/fundamentals/provider.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/mixed.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/mysql.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/sync/__init__.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/sync/akshare.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/sync/base.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/sync/gm.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/datasources/sync/gm_fundamental.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/__init__.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_001.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_002.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_003.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_004.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_005.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_006.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_007.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_008.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_009.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_010.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_011.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_012.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_013.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_014.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_015.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_016.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_017.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_018.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_019.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_020.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_021.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_022.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_023.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_024.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_025.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_026.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_027.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_028.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_029.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_030.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_031.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_032.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_033.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_034.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_035.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_036.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_037.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_038.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_039.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/alpha101/alpha_040.yaml +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/base.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/compute.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/loader.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/pipeline.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/ranking.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/ranking_executor.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/screening.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/factors/screening_executor.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/models/bar.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/parser/__init__.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/parser/constants.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/parser/formula.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/utils/__init__.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/utils/env.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/utils/logger.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/utils/path.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/utils/symbol_utils.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/utils/time.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli/utils/validate.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli.egg-info/SOURCES.txt +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli.egg-info/dependency_links.txt +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli.egg-info/entry_points.txt +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli.egg-info/requires.txt +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/quantcli.egg-info/top_level.txt +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/setup.cfg +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_akshare_integration.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_builtin_factors.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_cli.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_datasources.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_factors.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_gm_executors.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_mixed_datasource.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_multi_factor.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_pipeline_integration.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_symbol_utils.py +0 -0
- {quantcli-0.2.1 → quantcli-0.2.2}/tests/test_time.py +0 -0
|
@@ -111,6 +111,9 @@ def data(ctx):
|
|
|
111
111
|
help="数据源 (akshare/baostock/mixed/mysql)",
|
|
112
112
|
)
|
|
113
113
|
@click.option("--use-cache/--no-cache", default=True, help="是否使用缓存")
|
|
114
|
+
@click.option(
|
|
115
|
+
"--cache-raw/--no-cache-raw", default=False, help="是否缓存原始数据到parquet"
|
|
116
|
+
)
|
|
114
117
|
@click.option(
|
|
115
118
|
"--output",
|
|
116
119
|
"-o",
|
|
@@ -119,7 +122,7 @@ def data(ctx):
|
|
|
119
122
|
help="输出文件路径 (如: data.csv)",
|
|
120
123
|
)
|
|
121
124
|
@click.pass_context
|
|
122
|
-
def data_fetch(ctx, symbol, start, end, source, use_cache, output):
|
|
125
|
+
def data_fetch(ctx, symbol, start, end, source, use_cache, cache_raw, output):
|
|
123
126
|
"""获取股票日线数据
|
|
124
127
|
|
|
125
128
|
股票代码:
|
|
@@ -131,6 +134,7 @@ def data_fetch(ctx, symbol, start, end, source, use_cache, output):
|
|
|
131
134
|
quantcli data fetch 000001 --start 2025-01-01 --end 2025-12-31
|
|
132
135
|
quantcli data fetch 600519 --start 2025-01-01 --source mysql
|
|
133
136
|
quantcli data fetch 000001 --start 2025-01-01 -o data.csv
|
|
137
|
+
quantcli data fetch 000001 --start 2025-01-01 --cache-raw
|
|
134
138
|
"""
|
|
135
139
|
if end is None:
|
|
136
140
|
end = today()
|
|
@@ -139,7 +143,7 @@ def data_fetch(ctx, symbol, start, end, source, use_cache, output):
|
|
|
139
143
|
f"Fetching {symbol} data from {format_date(start)} to {format_date(end)}..."
|
|
140
144
|
)
|
|
141
145
|
|
|
142
|
-
config = DataConfig(source=source)
|
|
146
|
+
config = DataConfig(source=source, cache_raw=cache_raw)
|
|
143
147
|
dm = DataManager(config)
|
|
144
148
|
|
|
145
149
|
try:
|
|
@@ -30,6 +30,7 @@ logger = get_logger(__name__)
|
|
|
30
30
|
class DataConfig:
|
|
31
31
|
"""数据管理配置"""
|
|
32
32
|
|
|
33
|
+
cache_raw: bool = False
|
|
33
34
|
source: str = "akshare"
|
|
34
35
|
cache_dir: str = "./data"
|
|
35
36
|
parallel: int = 4
|
|
@@ -141,8 +142,7 @@ class DataManager:
|
|
|
141
142
|
logger.warning(f"No data for {symbol}")
|
|
142
143
|
return df
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
if use_cache:
|
|
145
|
+
if use_cache and self.config.cache_raw:
|
|
146
146
|
self._save_to_cache(cache_file, df, f"stock_daily_{symbol}")
|
|
147
147
|
|
|
148
148
|
return df
|
|
@@ -257,7 +257,7 @@ class DataManager:
|
|
|
257
257
|
|
|
258
258
|
df = self.datasource.get_index_daily(symbol, start_date, end_date)
|
|
259
259
|
|
|
260
|
-
if use_cache and not df.empty:
|
|
260
|
+
if use_cache and self.config.cache_raw and not df.empty:
|
|
261
261
|
self._save_to_cache(cache_file, df, f"index_daily_{symbol}")
|
|
262
262
|
|
|
263
263
|
return df
|
|
@@ -52,7 +52,7 @@ class TestGetDailyCacheLogic:
|
|
|
52
52
|
self, temp_cache_dir, mock_datasource
|
|
53
53
|
):
|
|
54
54
|
"""缓存存在且完整 → 直接返回缓存"""
|
|
55
|
-
config = DataConfig(cache_dir=temp_cache_dir, source="mock")
|
|
55
|
+
config = DataConfig(cache_dir=temp_cache_dir, source="mock", cache_raw=True)
|
|
56
56
|
dm = DataManager(config)
|
|
57
57
|
dm._datasource = mock_datasource
|
|
58
58
|
|
|
@@ -95,7 +95,7 @@ class TestGetDailyCacheLogic:
|
|
|
95
95
|
|
|
96
96
|
def test_cache_incomplete_fetches_full_data(self, temp_cache_dir, mock_datasource):
|
|
97
97
|
"""缓存不完整 → 全量拉取"""
|
|
98
|
-
config = DataConfig(cache_dir=temp_cache_dir, source="mock")
|
|
98
|
+
config = DataConfig(cache_dir=temp_cache_dir, source="mock", cache_raw=True)
|
|
99
99
|
dm = DataManager(config)
|
|
100
100
|
dm._datasource = mock_datasource
|
|
101
101
|
|
|
@@ -138,7 +138,7 @@ class TestGetDailyCacheLogic:
|
|
|
138
138
|
|
|
139
139
|
def test_no_cache_fetches_full_data(self, temp_cache_dir, mock_datasource):
|
|
140
140
|
"""缓存不存在 → 全量拉取"""
|
|
141
|
-
config = DataConfig(cache_dir=temp_cache_dir, source="mock")
|
|
141
|
+
config = DataConfig(cache_dir=temp_cache_dir, source="mock", cache_raw=True)
|
|
142
142
|
dm = DataManager(config)
|
|
143
143
|
dm._datasource = mock_datasource
|
|
144
144
|
|
|
@@ -165,7 +165,7 @@ class TestGetDailyCacheLogic:
|
|
|
165
165
|
|
|
166
166
|
def test_no_calendar_fetches_full_data(self, temp_cache_dir, mock_datasource):
|
|
167
167
|
"""交易日历不可用 → 直接拉取,不使用缓存"""
|
|
168
|
-
config = DataConfig(cache_dir=temp_cache_dir, source="mock")
|
|
168
|
+
config = DataConfig(cache_dir=temp_cache_dir, source="mock", cache_raw=True)
|
|
169
169
|
dm = DataManager(config)
|
|
170
170
|
dm._datasource = mock_datasource
|
|
171
171
|
|
|
@@ -200,7 +200,7 @@ class TestGetDailyCacheLogic:
|
|
|
200
200
|
self, temp_cache_dir, mock_datasource
|
|
201
201
|
):
|
|
202
202
|
"""交易日历不可用 + 无缓存 → 全量拉取"""
|
|
203
|
-
config = DataConfig(cache_dir=temp_cache_dir, source="mock")
|
|
203
|
+
config = DataConfig(cache_dir=temp_cache_dir, source="mock", cache_raw=True)
|
|
204
204
|
dm = DataManager(config)
|
|
205
205
|
dm._datasource = mock_datasource
|
|
206
206
|
|
|
@@ -222,7 +222,9 @@ class TestGetDailyBatch:
|
|
|
222
222
|
|
|
223
223
|
def test_batch_uses_parallel_when_enabled(self, temp_cache_dir, mock_datasource):
|
|
224
224
|
"""批量获取启用并行"""
|
|
225
|
-
config = DataConfig(
|
|
225
|
+
config = DataConfig(
|
|
226
|
+
cache_dir=temp_cache_dir, source="mock", parallel=2, cache_raw=True
|
|
227
|
+
)
|
|
226
228
|
dm = DataManager(config)
|
|
227
229
|
dm._datasource = mock_datasource
|
|
228
230
|
|
|
@@ -240,7 +242,7 @@ class TestCacheCleanup:
|
|
|
240
242
|
|
|
241
243
|
def test_clear_cache_removes_files(self, temp_cache_dir, mock_datasource):
|
|
242
244
|
"""清理缓存删除文件"""
|
|
243
|
-
config = DataConfig(cache_dir=temp_cache_dir, source="mock")
|
|
245
|
+
config = DataConfig(cache_dir=temp_cache_dir, source="mock", cache_raw=True)
|
|
244
246
|
dm = DataManager(config)
|
|
245
247
|
dm._datasource = mock_datasource
|
|
246
248
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|