|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | | -import os |
6 | | -import re |
7 | | -from collections.abc import Mapping, Sequence |
| 5 | +from collections.abc import Sequence |
8 | 6 | from typing import Any |
9 | 7 |
|
10 | 8 | from ..endpoints import ENDPOINTS |
11 | | -from ..exceptions import FtshareDownloadError |
12 | 9 | from ..params import symbols_to_json_string |
13 | 10 |
|
14 | 11 |
|
@@ -4388,94 +4385,6 @@ def ashare_news_sentiment_factors(self, trade_code: Any | None = None, start_dat |
4388 | 4385 | return self.get_paginated(path, page=page, page_size=page_size, limit=limit, all_pages=all_pages, max_pages=max_pages, raw=raw, fields=fields, as_dataframe=as_dataframe, **params) |
4389 | 4386 |
|
4390 | 4387 |
|
4391 | | - def kline_archives( |
4392 | | - self, |
4393 | | - *, |
4394 | | - raw: bool = False, |
4395 | | - fields: Sequence[str] | str | None = None, |
4396 | | - as_dataframe: bool = True, |
4397 | | - **kwargs: Any, |
4398 | | - ) -> Any: |
4399 | | - """年度分K归档包清单. |
4400 | | -
|
4401 | | - Endpoint: ``api/v2/market/data/kline-archives``. |
4402 | | - Method: ``GET``. |
4403 | | - Documented endpoint: ``kline_archives``. |
4404 | | -
|
4405 | | - Args: |
4406 | | - raw: Return the decoded JSON payload without tabular extraction. |
4407 | | - fields: Optional field list or comma-separated field string applied after extraction. |
4408 | | - as_dataframe: Return a pandas ``DataFrame`` by default; set to ``False`` for Python rows. |
4409 | | - **kwargs: Extra request parameters forwarded unchanged. |
4410 | | -
|
4411 | | - Returns: |
4412 | | - A pandas ``DataFrame`` by default, Python rows when ``as_dataframe=False``, or raw JSON when ``raw=True``. Rows carry `year`, `size_bytes`, `last_modified` and `sha256` for each downloadable archive package. |
4413 | | - """ |
4414 | | - request_params = dict(kwargs) |
4415 | | - return self._call_endpoint( |
4416 | | - 'kline_archives', |
4417 | | - raw=raw, |
4418 | | - fields=fields, |
4419 | | - as_dataframe=as_dataframe, |
4420 | | - **request_params, |
4421 | | - ) |
4422 | | - |
4423 | | - def kline_archives_download( |
4424 | | - self, |
4425 | | - year: Any, |
4426 | | - save_dir: str | os.PathLike[str] = ".", |
4427 | | - retries: int = 3, |
4428 | | - ) -> str: |
4429 | | - """下载年度分K归档包. |
4430 | | -
|
4431 | | - Endpoint: ``api/v2/market/data/kline-archives/{year}/download``. |
4432 | | - Method: ``GET``. |
4433 | | -
|
4434 | | - 归档包为按年打包的分钟 K 线(zstd 压缩 tar,4–5 GB),下载前先用 ``kline_archives`` 校验该年份是否在清单内,下载中支持 HTTP Range 断点续传(半成品写在 `{文件名}.part`,旁挂 `.part.meta` 记录 ETag;服务端 ETag 变化时丢弃半成品重下),支持网络失败重试,下载完成后按清单的 `sha256` 校验完整性。 |
4435 | | -
|
4436 | | - Args: |
4437 | | - year: 4 位年份,如 `2023`;须为 ``kline_archives`` 返回的年份之一 (type: int | string; required: Y). |
4438 | | - save_dir: 保存目录,默认为当前目录;目录不存在时自动创建。 |
4439 | | - retries: 首次失败后的额外重试次数,默认 3(即最多尝试 4 次)。网络异常、429、5xx 与 416 会重试。 |
4440 | | -
|
4441 | | - Returns: |
4442 | | - 落盘后的文件路径;目标文件已存在且 sha256 与清单一致时直接返回该路径,不重新下载。 |
4443 | | -
|
4444 | | - Raises: |
4445 | | - ValueError: 传入的 `year` 不是 4 位数字。 |
4446 | | - FtshareDownloadError: 该年份不在清单内,或下载完成后 size / sha256 校验不一致。 |
4447 | | - FtshareHTTPError: 下载接口返回不可重试的 HTTP 错误状态。 |
4448 | | - """ |
4449 | | - year_str = str(year) |
4450 | | - if re.fullmatch(r"\d{4}", year_str) is None: |
4451 | | - raise ValueError(f"year must be a 4-digit year; got {year!r}") |
4452 | | - |
4453 | | - listing = self.kline_archives(as_dataframe=False) |
4454 | | - rows = listing if isinstance(listing, list) else [] |
4455 | | - entry = next( |
4456 | | - ( |
4457 | | - row |
4458 | | - for row in rows |
4459 | | - if isinstance(row, Mapping) and str(row.get('year')) == year_str |
4460 | | - ), |
4461 | | - None, |
4462 | | - ) |
4463 | | - if entry is None: |
4464 | | - raise FtshareDownloadError( |
4465 | | - self._url_for(ENDPOINTS['kline_archives'].path), |
4466 | | - f"no archive package is offered for year {year_str}", |
4467 | | - ) |
4468 | | - |
4469 | | - path = self._format_path(ENDPOINTS['kline_archives'].path + '/{year}/download', {'year': year_str}) |
4470 | | - return self.download_resumable( |
4471 | | - path, |
4472 | | - expected_size=entry.get('size_bytes'), |
4473 | | - expected_sha256=entry.get('sha256'), |
4474 | | - save_dir=save_dir, |
4475 | | - filename=f"ftshare_1m_{year_str}.tar.zst", |
4476 | | - retries=retries, |
4477 | | - ) |
4478 | | - |
4479 | 4388 | def kline_pattern_annotations(self, date: Any | None = None, symbol: Any | None = None, pattern: Any | None = None, page: Any | None = None, page_size: Any | None = None, limit: int | None = None, all_pages: bool = False, max_pages: int | None = None, *, raw: bool = False, fields: Sequence[str] | str | None = None, as_dataframe: bool = True, **kwargs: Any) -> Any: |
4480 | 4389 | """K线形态标注.""" |
4481 | 4390 | params = {'date': date, 'symbol': symbol, 'pattern': pattern} |
|
0 commit comments