quantcli 0.2.2__tar.gz → 0.2.5__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.2/quantcli.egg-info → quantcli-0.2.5}/PKG-INFO +1 -1
- {quantcli-0.2.2 → quantcli-0.2.5}/pyproject.toml +1 -1
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/cli.py +99 -13
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/mysql.py +11 -4
- {quantcli-0.2.2 → quantcli-0.2.5/quantcli.egg-info}/PKG-INFO +1 -1
- {quantcli-0.2.2 → quantcli-0.2.5}/LICENSE +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/README.md +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/core/__init__.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/core/backtest.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/core/data.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/core/factor.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/__init__.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/akshare.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/baostock.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/base.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/cache.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/fundamentals/__init__.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/fundamentals/provider.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/mixed.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/sync/__init__.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/sync/akshare.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/sync/base.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/sync/gm.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/datasources/sync/gm_fundamental.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/__init__.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_001.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_002.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_003.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_004.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_005.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_006.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_007.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_008.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_009.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_010.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_011.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_012.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_013.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_014.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_015.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_016.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_017.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_018.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_019.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_020.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_021.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_022.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_023.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_024.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_025.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_026.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_027.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_028.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_029.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_030.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_031.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_032.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_033.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_034.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_035.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_036.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_037.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_038.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_039.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/alpha101/alpha_040.yaml +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/base.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/compute.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/loader.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/pipeline.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/ranking.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/ranking_executor.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/screening.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/factors/screening_executor.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/models/bar.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/parser/__init__.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/parser/constants.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/parser/formula.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/utils/__init__.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/utils/env.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/utils/logger.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/utils/path.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/utils/symbol_utils.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/utils/time.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli/utils/validate.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli.egg-info/SOURCES.txt +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli.egg-info/dependency_links.txt +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli.egg-info/entry_points.txt +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli.egg-info/requires.txt +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/quantcli.egg-info/top_level.txt +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/setup.cfg +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_akshare_integration.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_builtin_factors.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_cli.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_data_manager.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_datasources.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_factors.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_gm_executors.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_mixed_datasource.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_multi_factor.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_pipeline_integration.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_symbol_utils.py +0 -0
- {quantcli-0.2.2 → quantcli-0.2.5}/tests/test_time.py +0 -0
|
@@ -107,7 +107,7 @@ def data(ctx):
|
|
|
107
107
|
@click.option(
|
|
108
108
|
"--source",
|
|
109
109
|
type=click.Choice(["akshare", "baostock", "mixed", "mysql"]),
|
|
110
|
-
default="
|
|
110
|
+
default="mysql",
|
|
111
111
|
help="数据源 (akshare/baostock/mixed/mysql)",
|
|
112
112
|
)
|
|
113
113
|
@click.option("--use-cache/--no-cache", default=True, help="是否使用缓存")
|
|
@@ -173,7 +173,93 @@ def data_fetch(ctx, symbol, start, end, source, use_cache, cache_raw, output):
|
|
|
173
173
|
click.echo(f"Saved to {output}")
|
|
174
174
|
|
|
175
175
|
except Exception as e:
|
|
176
|
-
|
|
176
|
+
error_msg = str(e)
|
|
177
|
+
if "Access denied" in error_msg or "Connection refused" in error_msg:
|
|
178
|
+
click.echo(f"MySQL 连接失败: 请检查数据库配置", err=True)
|
|
179
|
+
click.echo(
|
|
180
|
+
"提示: 使用 --source akshare 或 --source baostock 可以切换到其他数据源",
|
|
181
|
+
err=True,
|
|
182
|
+
)
|
|
183
|
+
else:
|
|
184
|
+
click.echo(f"Error: {e}", err=True)
|
|
185
|
+
sys.exit(1)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@data.command("fetch-fundamental")
|
|
189
|
+
@click.argument("symbols", type=str, nargs=-1)
|
|
190
|
+
@click.option(
|
|
191
|
+
"--date",
|
|
192
|
+
type=date_type,
|
|
193
|
+
default=None,
|
|
194
|
+
help="截止日期 (YYYY-MM-DD,默认今天)",
|
|
195
|
+
)
|
|
196
|
+
@click.option(
|
|
197
|
+
"--source",
|
|
198
|
+
type=click.Choice(["mysql", "baostock"]),
|
|
199
|
+
default="mysql",
|
|
200
|
+
help="数据源 (mysql/baostock)",
|
|
201
|
+
)
|
|
202
|
+
@click.option(
|
|
203
|
+
"--output",
|
|
204
|
+
"-o",
|
|
205
|
+
type=click.Path(),
|
|
206
|
+
default=None,
|
|
207
|
+
help="输出文件路径 (如: data.csv)",
|
|
208
|
+
)
|
|
209
|
+
@click.pass_context
|
|
210
|
+
def data_fetch_fundamental(ctx, symbols, date, source, output):
|
|
211
|
+
"""获取股票基本面数据
|
|
212
|
+
|
|
213
|
+
股票代码:
|
|
214
|
+
000001 - 平安银行
|
|
215
|
+
600519 - 贵州茅台
|
|
216
|
+
|
|
217
|
+
示例:
|
|
218
|
+
quantcli data fetch-fundamental 000001 600519
|
|
219
|
+
quantcli data fetch-fundamental 600519 --date 2024-12-31
|
|
220
|
+
quantcli data fetch-fundamental 000001 --source baostock -o fundamentals.csv
|
|
221
|
+
"""
|
|
222
|
+
if not symbols:
|
|
223
|
+
click.echo("Error: At least one symbol is required")
|
|
224
|
+
sys.exit(1)
|
|
225
|
+
|
|
226
|
+
if date is None:
|
|
227
|
+
date = today()
|
|
228
|
+
|
|
229
|
+
click.echo(
|
|
230
|
+
f"Fetching fundamental data for {len(symbols)} symbols at {format_date(date)}..."
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
config = DataConfig(source=source)
|
|
234
|
+
dm = DataManager(config)
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
df = dm.datasource.get_fundamental(list(symbols), date)
|
|
238
|
+
|
|
239
|
+
if df.empty:
|
|
240
|
+
click.echo(f"No fundamental data found for symbols")
|
|
241
|
+
return
|
|
242
|
+
|
|
243
|
+
click.echo(f"Retrieved {len(df)} rows")
|
|
244
|
+
|
|
245
|
+
click.echo(df.to_string())
|
|
246
|
+
|
|
247
|
+
if output:
|
|
248
|
+
if output.endswith(".csv"):
|
|
249
|
+
df.to_csv(output, index=False)
|
|
250
|
+
elif output.endswith(".parquet"):
|
|
251
|
+
df.to_parquet(output, index=False)
|
|
252
|
+
else:
|
|
253
|
+
df.to_csv(output, index=False)
|
|
254
|
+
click.echo(f"Saved to {output}")
|
|
255
|
+
|
|
256
|
+
except Exception as e:
|
|
257
|
+
error_msg = str(e)
|
|
258
|
+
if "Access denied" in error_msg or "Connection refused" in error_msg:
|
|
259
|
+
click.echo(f"MySQL 连接失败: 请检查数据库配置", err=True)
|
|
260
|
+
click.echo("提示: 使用 --source baostock 可以切换到其他数据源", err=True)
|
|
261
|
+
else:
|
|
262
|
+
click.echo(f"Error: {e}", err=True)
|
|
177
263
|
sys.exit(1)
|
|
178
264
|
|
|
179
265
|
|
|
@@ -195,7 +281,7 @@ def data_cache(ctx):
|
|
|
195
281
|
@click.pass_context
|
|
196
282
|
def data_cache_ls(ctx, pattern, sort):
|
|
197
283
|
"""列出缓存文件"""
|
|
198
|
-
config = DataConfig()
|
|
284
|
+
config = DataConfig(source="mysql")
|
|
199
285
|
dm = DataManager(config)
|
|
200
286
|
sizes = dm.get_cache_size()
|
|
201
287
|
|
|
@@ -233,7 +319,7 @@ def data_cache_ls(ctx, pattern, sort):
|
|
|
233
319
|
@click.pass_context
|
|
234
320
|
def data_cache_clean(ctx, older_than):
|
|
235
321
|
"""清理缓存文件"""
|
|
236
|
-
config = DataConfig()
|
|
322
|
+
config = DataConfig(source="mysql")
|
|
237
323
|
dm = DataManager(config)
|
|
238
324
|
|
|
239
325
|
count = dm.clear_cache(older_than=older_than)
|
|
@@ -244,7 +330,7 @@ def data_cache_clean(ctx, older_than):
|
|
|
244
330
|
@click.pass_context
|
|
245
331
|
def data_health(ctx):
|
|
246
332
|
"""检查数据源健康状态"""
|
|
247
|
-
config = DataConfig()
|
|
333
|
+
config = DataConfig(source="mysql")
|
|
248
334
|
dm = DataManager(config)
|
|
249
335
|
health = dm.health_check()
|
|
250
336
|
|
|
@@ -309,7 +395,7 @@ def factor_run(ctx, name, expr, symbol, start, end, output):
|
|
|
309
395
|
click.echo(f"Computing factor '{name}'...")
|
|
310
396
|
|
|
311
397
|
# 创建引擎
|
|
312
|
-
config = DataConfig()
|
|
398
|
+
config = DataConfig(source="mysql")
|
|
313
399
|
dm = DataManager(config)
|
|
314
400
|
engine = FactorEngine(dm)
|
|
315
401
|
|
|
@@ -370,7 +456,7 @@ def factor_eval(ctx, name, symbol, start, end, method):
|
|
|
370
456
|
|
|
371
457
|
click.echo(f"Evaluating factor '{name}'...")
|
|
372
458
|
|
|
373
|
-
config = DataConfig()
|
|
459
|
+
config = DataConfig(source="mysql")
|
|
374
460
|
dm = DataManager(config)
|
|
375
461
|
engine = FactorEngine(dm)
|
|
376
462
|
|
|
@@ -735,7 +821,7 @@ def filter_run(
|
|
|
735
821
|
if daily_conditions:
|
|
736
822
|
# 只对候选获取日线数据
|
|
737
823
|
click.echo(f"Fetching daily data for {len(candidates)} candidates...")
|
|
738
|
-
dm = DataManager(DataConfig(source="
|
|
824
|
+
dm = DataManager(DataConfig(source="mysql"))
|
|
739
825
|
|
|
740
826
|
price_data = {}
|
|
741
827
|
for symbol in candidates:
|
|
@@ -833,7 +919,7 @@ def filter_run(
|
|
|
833
919
|
# 阶段2: 日线
|
|
834
920
|
click.echo(f"\n=== Stage 2: Daily Screening ===")
|
|
835
921
|
click.echo(f"Fetching daily data for {len(candidates)} candidates...")
|
|
836
|
-
dm = DataManager(DataConfig(source="
|
|
922
|
+
dm = DataManager(DataConfig(source="mysql"))
|
|
837
923
|
|
|
838
924
|
price_data = {}
|
|
839
925
|
for symbol in candidates:
|
|
@@ -889,7 +975,7 @@ def filter_run(
|
|
|
889
975
|
return
|
|
890
976
|
|
|
891
977
|
click.echo(f"Fetching price data for {len(candidates)} candidates...")
|
|
892
|
-
dm = DataManager(DataConfig(source="
|
|
978
|
+
dm = DataManager(DataConfig(source="mysql"))
|
|
893
979
|
|
|
894
980
|
price_data = {}
|
|
895
981
|
for symbol in candidates:
|
|
@@ -1307,7 +1393,7 @@ def analyze_ic(ctx, expr, name, symbol, start, end, period, window, method):
|
|
|
1307
1393
|
click.echo(f"Forward period: {period} days, Window: {window}")
|
|
1308
1394
|
|
|
1309
1395
|
# 获取数据
|
|
1310
|
-
config = DataConfig()
|
|
1396
|
+
config = DataConfig(source="mysql")
|
|
1311
1397
|
dm = DataManager(config)
|
|
1312
1398
|
df = dm.get_daily(symbol, start, end)
|
|
1313
1399
|
|
|
@@ -1426,7 +1512,7 @@ def analyze_batch(ctx, dir, symbol, start, end, period, window, top, output):
|
|
|
1426
1512
|
click.echo(f"Analyzing with period={period}d, window={window}...\n")
|
|
1427
1513
|
|
|
1428
1514
|
# 获取数据
|
|
1429
|
-
config = DataConfig()
|
|
1515
|
+
config = DataConfig(source="mysql")
|
|
1430
1516
|
dm = DataManager(config)
|
|
1431
1517
|
df = dm.get_daily(symbol, start, end)
|
|
1432
1518
|
|
|
@@ -1545,7 +1631,7 @@ def config():
|
|
|
1545
1631
|
@click.pass_context
|
|
1546
1632
|
def config_show(ctx):
|
|
1547
1633
|
"""显示当前配置"""
|
|
1548
|
-
config = DataConfig()
|
|
1634
|
+
config = DataConfig(source="mysql")
|
|
1549
1635
|
click.echo("QuantCLI Configuration:")
|
|
1550
1636
|
click.echo(f" data.source: {config.source}")
|
|
1551
1637
|
click.echo(f" data.cache_dir: {config.cache_dir}")
|
|
@@ -88,9 +88,14 @@ class MySQLDataSource(DataSource):
|
|
|
88
88
|
self._prefix = config_dict["table_prefix"]
|
|
89
89
|
self._autocommit = autocommit
|
|
90
90
|
self._conn = None
|
|
91
|
+
self._tables_initialized = False
|
|
91
92
|
|
|
92
|
-
|
|
93
|
+
def _ensure_tables(self):
|
|
94
|
+
"""确保数据库表已初始化(懒加载)"""
|
|
95
|
+
if self._tables_initialized:
|
|
96
|
+
return
|
|
93
97
|
self._init_tables()
|
|
98
|
+
self._tables_initialized = True
|
|
94
99
|
|
|
95
100
|
def _get_connection(self):
|
|
96
101
|
"""获取数据库连接"""
|
|
@@ -208,9 +213,8 @@ class MySQLDataSource(DataSource):
|
|
|
208
213
|
"""批量转换为 MySQL 新格式"""
|
|
209
214
|
return [to_mysql(s) for s in symbols]
|
|
210
215
|
|
|
211
|
-
def get_daily(
|
|
212
|
-
self
|
|
213
|
-
) -> pd.DataFrame:
|
|
216
|
+
def get_daily(self, symbol: str, start_date, end_date) -> pd.DataFrame:
|
|
217
|
+
self._ensure_tables()
|
|
214
218
|
"""获取日线数据
|
|
215
219
|
|
|
216
220
|
Args:
|
|
@@ -559,6 +563,7 @@ class MySQLDataSource(DataSource):
|
|
|
559
563
|
# ==================== 股票列表和日历 ====================
|
|
560
564
|
|
|
561
565
|
def get_stock_list(self, market: str = "all") -> pd.DataFrame:
|
|
566
|
+
self._ensure_tables()
|
|
562
567
|
"""获取股票列表"""
|
|
563
568
|
conn = self._get_connection()
|
|
564
569
|
|
|
@@ -595,6 +600,7 @@ class MySQLDataSource(DataSource):
|
|
|
595
600
|
)
|
|
596
601
|
|
|
597
602
|
def get_trading_calendar(self, exchange: str = "SSE") -> List[date]:
|
|
603
|
+
self._ensure_tables()
|
|
598
604
|
"""获取交易日历"""
|
|
599
605
|
conn = self._get_connection()
|
|
600
606
|
|
|
@@ -619,6 +625,7 @@ class MySQLDataSource(DataSource):
|
|
|
619
625
|
def get_fundamental(
|
|
620
626
|
self, symbols: List[str], date, indicators: Optional[List[str]] = None
|
|
621
627
|
) -> pd.DataFrame:
|
|
628
|
+
self._ensure_tables()
|
|
622
629
|
"""获取基本面数据
|
|
623
630
|
|
|
624
631
|
Args:
|
|
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
|
|
File without changes
|