From 3d45d0026c188820ad64b101f9cd2db27568d591 Mon Sep 17 00:00:00 2001 From: zhuhao Date: Tue, 29 Sep 2026 20:34:59 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E8=82=A1?= =?UTF-8?q?=E7=A5=A8=E5=88=86=E9=92=9F=E5=B0=81=E5=8D=95=E9=87=91=E9=A2=9D?= =?UTF-8?q?=E4=B8=8E=E4=B8=9C=E6=96=B9=E8=B4=A2=E5=AF=8CETF=E8=B5=84?= =?UTF-8?q?=E9=87=91=E6=B5=81=E6=8E=A5=E5=8F=A3=EF=BC=8C=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=B7=B1=E4=BA=A4=E6=89=80=E5=8F=AF=E8=BD=AC=E5=80=BA=E7=94=B3?= =?UTF-8?q?=E6=8A=A5=E5=BF=AB=E7=85=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 stock_minute_seal(api/v2/market/data/stock-minute-seal)与 eastmoney_etf_flow(api/v1/market/data/eastmoney-etf-flow)的端点注册、API 方法与单测 - 移除 szse_convertible_bond_declaration_snapshots 的端点注册、API 方法、接口用例与真机已知问题项 - API_REFERENCE 总数 240→238,股票数据 126→127、债券专题 10→9 - 版本号 1.0.9 → 1.0.10 --- docs/API_REFERENCE.md | 74 +++++++++++++------------------- pyproject.toml | 2 +- src/ftshare/apis/bond.py | 59 ------------------------- src/ftshare/apis/stock.py | 67 +++++++++++++++++++++++++++++ src/ftshare/endpoints/bond.py | 8 ---- src/ftshare/endpoints/stock.py | 16 +++++++ tests/endpoint_cases.py | 4 +- tests/test_client.py | 32 ++++++++++++++ tests/test_integration_market.py | 1 - 9 files changed, 149 insertions(+), 114 deletions(-) diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md index 546fd30..937d799 100644 --- a/docs/API_REFERENCE.md +++ b/docs/API_REFERENCE.md @@ -6,22 +6,22 @@ | 指标 | 数量 | |---|---:| -| SDK 方法总数 | 239 | +| SDK 方法总数 | 238 | ## 专题分布 | ftshare-doc 专题 | SDK 方法数 | API mixin 模块 | Endpoint 模块 | |---|---:|---|---| -| 股票数据 | 125 | `ftshare.apis.stock` | `ftshare.endpoints.stock` | +| 股票数据 | 127 | `ftshare.apis.stock` | `ftshare.endpoints.stock` | | 港股数据 | 3 | `ftshare.apis.hk` | `ftshare.endpoints.hk` | | 美股数据 | 2 | `ftshare.apis.us` | `ftshare.endpoints.us` | | 指数专题 | 15 | `ftshare.apis.index` | `ftshare.endpoints.index` | -| ETF专题 | 18 | `ftshare.apis.etf` | `ftshare.endpoints.etf` | +| ETF专题 | 17 | `ftshare.apis.etf` | `ftshare.endpoints.etf` | | 公募基金 | 18 | `ftshare.apis.fund` | `ftshare.endpoints.fund` | | 期货数据 | 18 | `ftshare.apis.futures` | `ftshare.endpoints.futures` | -| 债券专题 | 10 | `ftshare.apis.bond` | `ftshare.endpoints.bond` | +| 债券专题 | 9 | `ftshare.apis.bond` | `ftshare.endpoints.bond` | | 宏观经济 | 23 | `ftshare.apis.economic` | `ftshare.endpoints.economic` | -| 大模型语料 | 6 | `ftshare.apis.llm_corpus` | `ftshare.endpoints.llm_corpus` | +| 大模型语料 | 5 | `ftshare.apis.llm_corpus` | `ftshare.endpoints.llm_corpus` | | 现货数据 | 1 | `ftshare.apis.spot` | `ftshare.endpoints.spot` | | 外汇数据 | 0 | `ftshare.apis.forex` | `ftshare.endpoints.forex` | @@ -59,6 +59,7 @@ | [`eastmoney_board_daily_kline`](#api-eastmoney-board-daily-kline) | 东方财富板块日线OHLC | `GET` | `api/v1/market/data/eastmoney-board-daily-ohlc` | `board_code`, `start_date`, `end_date`, `page`, `page_size` | `东方财富板块日线OHLC.md` | | [`eastmoney_concept_boards`](#api-eastmoney-concept-boards) | 东方财富概念板块 | `GET` | `api/v1/market/data/eastmoney-concept-boards` | - | `东方财富概念板块.md` | | [`eastmoney_dapan_flow`](#api-eastmoney-dapan-flow) | 东方财富大盘资金流 | `GET` | `api/v1/market/data/eastmoney-dapan-flow` | `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `东方财富大盘资金流.md` | +| [`eastmoney_etf_flow`](#api-eastmoney-etf-flow) | 东方财富ETF资金流 | `GET` | `api/v1/market/data/eastmoney-etf-flow` | `symbol`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `东方财富ETF资金流.md` | | [`eastmoney_market_valuation`](#api-eastmoney-market-valuation) | 东方财富市场估值 | `GET` | `api/v1/market/data/eastmoney-market-valuation` | `market_code`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `东方财富市场估值.md` | | [`eastmoney_rank`](#api-eastmoney-rank) | 东方财富股票排名 | `GET` | `api/v1/market/data/eastmoney-rank` | `rank_group`, `market`, `trade_date` | `东方财富股票排名.md` | | [`eastmoney_sector_flow`](#api-eastmoney-sector-flow) | 东方财富板块资金流 | `GET` | `api/v1/market/data/eastmoney-sector-flow` | `board_code`, `board_type`, `board_level`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `东方财富板块资金流.md` | @@ -127,6 +128,7 @@ | [`stock_list`](#api-stock-list) | 股票列表 | `GET` | `api/v1/market/data/stock-list` | `page`, `page_size` | `股票列表.md` | | [`stock_market`](#api-stock-market) | 市场行情快照 | `GET` | `api/v1/market/data/daec/market/snapshot` | `scope` | `市场行情快照.md` | | [`stock_market_distribution_intraday`](#api-stock-market-distribution-intraday) | 市场涨跌分布分时 | `GET` | `api/v2/market/data/market-distribution-intraday` | - | `市场涨跌分布分时.md` | +| [`stock_minute_seal`](#api-stock-minute-seal) | 股票分钟封单金额 | `GET` | `api/v2/market/data/stock-minute-seal` | `trade_date`, `symbol` | `股票分钟封单金额.md` | | [`stock_minutes`](#api-stock-minutes) | 股票历史分钟行情 | `GET` | `api/v2/market/data/stock_minutes` | `symbol`, `interval_value`, `adjust_kind`, `since_ts_millis`, `until_ts_millis`, `limit` | `股票历史分钟行情.md` | | [`stock_pledge_detail`](#api-stock-pledge-detail) | 股权质押明细 | `GET` | `api/v1/market/data/pledge/pledge-detail` | `stock_code`, `is_last`, `page`, `page_size` | `股权质押明细.md` | | [`stock_prev_close`](#api-stock-prev-close) | 标的昨收价 | `GET` | `api/v1/market/data/daec/history/prev-closes` | `symbol`, `since`, `until` | `标的昨收价.md` | @@ -276,7 +278,6 @@ | [`convertible_bond_minute_candlesticks`](#api-convertible-bond-minute-candlesticks) | 可转债历史分钟K线 | `GET` | `api/v2/market/data/convertible-bond-minute-candlesticks` | `symbol`, `symbols`, `interval_value`, `since_ts_millis`, `until_ts_millis`, `limit` | `可转债历史分钟K线.md` | | [`convertible_bond_realtime_day_kline`](#api-convertible-bond-realtime-day-kline) | 可转债实时日K线 | `GET` | `api/v4/market/data/convertible-bond-realtime-day-kline` | `symbols` | `可转债实时日K线.md` | | [`convertible_bond_realtime_minute_kline`](#api-convertible-bond-realtime-minute-kline) | 可转债实时分钟K线 | `GET` | `api/v4/market/data/convertible-bond-realtime-minute-kline` | `symbols` | `可转债实时分钟K线.md` | -| [`szse_convertible_bond_declaration_snapshots`](#api-szse-convertible-bond-declaration-snapshots) | 深交所可转债申报快照 | `GET` | `api/v1/market/data/convertible-bond/szse/declaration-snapshots` | `security_code`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `深交所可转债申报快照.md` | | [`szse_convertible_bond_directed_trades`](#api-szse-convertible-bond-directed-trades) | 深交所可转债定向成交 | `GET` | `api/v1/market/data/convertible-bond/szse/directed-trades` | `security_code`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `深交所可转债定向成交.md` | | [`szse_convertible_bond_matching_trades`](#api-szse-convertible-bond-matching-trades) | 深交所可转债匹配成交 | `GET` | `api/v1/market/data/convertible-bond/szse/matching-trades` | `security_code`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `深交所可转债匹配成交.md` | | [`szse_convertible_bond_negotiated_trades`](#api-szse-convertible-bond-negotiated-trades) | 深交所可转债协议成交 | `GET` | `api/v1/market/data/convertible-bond/szse/negotiated-trades` | `security_code`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` | `深交所可转债协议成交.md` | @@ -823,6 +824,16 @@ Returns: payloads when multi-page fetching is used with ``raw=True``. ``` +

eastmoney_etf_flow

+ +- 接口名称:东方财富ETF资金流 +- HTTP:`GET` +- Path:`api/v1/market/data/eastmoney-etf-flow` +- 参数:`symbol`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` +- 来源文档:`东方财富ETF资金流.md` +- 原始接口:`get_eastmoney_etf_flow` +- 说明:返回 `code/message/data` 分页信封,记录位于 `data.records`;`page_size` 上限 1000,`trade_date`、`start_date`、`end_date` 按 AND 组合过滤。 +

eastmoney_market_valuation

- 接口名称:东方财富市场估值 @@ -2753,6 +2764,20 @@ Returns: A pandas ``DataFrame`` by default, Python rows when ``as_dataframe=False``, or raw JSON when ``raw=True``. ``` +

stock_minute_seal

+ +- 接口名称:股票分钟封单金额 +- HTTP:`GET` +- Path:`api/v2/market/data/stock-minute-seal` +- 参数:`trade_date`, `symbol` +- 来源文档:`股票分钟封单金额.md` +- 原始接口:`stock_minute_seal` +- 说明:返回 `code/message/data`(非分页)。`trade_date` 必填,八位 `YYYYMMDD` 且须为真实日历日,不接受 `YYYY-MM-DD`;`symbol` 可省略,省略时返回该日全部有封单记录的股票。`data` 含 `trade_date`、`sampling`(固定 `last_accepted_quote_per_minute`)与 `stocks`,`stocks[]` 含 `symbol`、`market_id`(3553 沪市 / 3554 深市)与 `minutes`,`minutes[]` 含 `minute`(北京时间 `HH:MM`)、`direction`(`up` 涨停封单 / `down` 跌停封单)、`seal_amount_yuan`(元,十进制字符串)。无匹配数据时成功返回 `stocks: []`。 + +```text +股票分钟封单金额. +``` +

stock_minutes

- 接口名称:股票历史分钟行情 @@ -5381,43 +5406,6 @@ Returns: ``as_dataframe=False``, or raw JSON when ``raw=True``. ``` -

szse_convertible_bond_declaration_snapshots

- -- 接口名称:深交所可转债申报快照 -- HTTP:`GET` -- Path:`api/v1/market/data/convertible-bond/szse/declaration-snapshots` -- 参数:`security_code`, `trade_date`, `start_date`, `end_date`, `page`, `page_size` -- 来源文档:`深交所可转债申报快照.md` -- 原始接口:`szse_convertible_bond_declaration_snapshots` - -```text -深交所可转债申报快照. - -Endpoint: ``api/v1/market/data/convertible-bond/szse/declaration-snapshots``. -Method: ``GET``. -Documented endpoint: ``szse_convertible_bond_declaration_snapshots``. - -Args: - security_code: 六位可转债证券代码,例如 `123001`。 (type: string; required: N). - trade_date: 单个交易日,格式 `YYYYMMDD`;不能与 `start_date`、`end_date` 同时使用。 (type: integer; required: N). - start_date: 查询开始日期,格式 `YYYYMMDD`。 (type: integer; required: N). - end_date: 查询结束日期,格式 `YYYYMMDD`。 (type: integer; required: N). - page: Page number, starting from 1. If omitted, the server default is used unless ``limit`` or ``all_pages`` is set. - page_size: Rows per page. The SDK validates this against the endpoint-specific maximum. - limit: Maximum number of rows to return. The SDK may fetch multiple pages to satisfy this limit. - all_pages: Fetch and combine pages until the server reports the last page. - max_pages: Optional safety cap for ``all_pages``. - raw: Return the decoded JSON payload without tabular extraction. - fields: Optional field list or comma-separated field string applied after extraction. - as_dataframe: Return a pandas ``DataFrame`` by default; set to ``False`` for Python rows. - **kwargs: Extra request parameters forwarded unchanged. Useful when the service adds parameters before the SDK is regenerated. - -Returns: - A pandas ``DataFrame`` by default, Python rows when - ``as_dataframe=False``, raw JSON when ``raw=True``, or raw page - payloads when multi-page fetching is used with ``raw=True``. -``` -

szse_convertible_bond_directed_trades

- 接口名称:深交所可转债定向成交 diff --git a/pyproject.toml b/pyproject.toml index c9df81f..257f5c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "ftshare" -version = "1.0.9" +version = "1.0.10" description = "Python SDK for FTShare market data APIs." readme = "README.md" requires-python = ">=3.9" diff --git a/src/ftshare/apis/bond.py b/src/ftshare/apis/bond.py index 24b5e18..315d31e 100644 --- a/src/ftshare/apis/bond.py +++ b/src/ftshare/apis/bond.py @@ -382,62 +382,3 @@ def cb_lists(self, *, raw: bool = False, fields: Sequence[str] | str | None = No params = {} params.update(kwargs) return self._call_endpoint('cb_lists', raw=raw, fields=fields, as_dataframe=as_dataframe, **params) - - def szse_convertible_bond_declaration_snapshots( - self, - security_code: Any | None = None, - trade_date: Any | None = None, - start_date: Any | None = None, - end_date: Any | None = None, - page: int | None = None, - page_size: int | 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: - """深交所可转债申报快照. - - Endpoint: ``api/v1/market/data/convertible-bond/szse/declaration-snapshots``. - Method: ``GET``. - Documented endpoint: ``szse_convertible_bond_declaration_snapshots``. - - Args: - security_code: 六位可转债证券代码,例如 `123001`。 (type: string; required: N). - trade_date: 单个交易日,格式 `YYYYMMDD`;不能与 `start_date`、`end_date` 同时使用。 (type: integer; required: N). - start_date: 查询开始日期,格式 `YYYYMMDD`。 (type: integer; required: N). - end_date: 查询结束日期,格式 `YYYYMMDD`。 (type: integer; required: N). - page: Page number, starting from 1. If omitted, the server default is used unless ``limit`` or ``all_pages`` is set. - page_size: Rows per page. The SDK validates this against the endpoint-specific maximum. - limit: Maximum number of rows to return. The SDK may fetch multiple pages to satisfy this limit. - all_pages: Fetch and combine pages until the server reports the last page. - max_pages: Optional safety cap for ``all_pages``. - raw: Return the decoded JSON payload without tabular extraction. - fields: Optional field list or comma-separated field string applied after extraction. - as_dataframe: Return a pandas ``DataFrame`` by default; set to ``False`` for Python rows. - **kwargs: Extra request parameters forwarded unchanged. Useful when the service adds parameters before the SDK is regenerated. - - Returns: - A pandas ``DataFrame`` by default, Python rows when - ``as_dataframe=False``, raw JSON when ``raw=True``, or raw page - payloads when multi-page fetching is used with ``raw=True``. - """ - request_params = {'security_code': security_code, 'trade_date': trade_date, 'start_date': start_date, 'end_date': end_date} - request_params.update(kwargs) - path = ENDPOINTS['szse_convertible_bond_declaration_snapshots'].path - 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, - **request_params, - ) diff --git a/src/ftshare/apis/stock.py b/src/ftshare/apis/stock.py index 24daadb..619572d 100644 --- a/src/ftshare/apis/stock.py +++ b/src/ftshare/apis/stock.py @@ -1287,6 +1287,66 @@ def eastmoney_dapan_flow( **request_params, ) + def eastmoney_etf_flow( + self, + symbol: Any | None = None, + trade_date: Any | None = None, + start_date: Any | None = None, + end_date: Any | None = None, + page: int | None = None, + page_size: int | 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: + """东方财富ETF资金流. + + Endpoint: ``api/v1/market/data/eastmoney-etf-flow``. + Method: ``GET``. + Documented endpoint: ``get_eastmoney_etf_flow``. + + Args: + symbol: ETF 代码,如 159231;也支持带交易所后缀的代码,如 159231.SZ (type: string; required: N). + trade_date: 交易日 YYYYMMDD (type: string; required: N). + start_date: 区间起始日 YYYYMMDD;需与 end_date 同时提供 (type: string; required: N). + end_date: 区间结束日 YYYYMMDD;需与 start_date 同时提供 (type: string; required: N). + page: Page number, starting from 1. If omitted, the server default is used unless ``limit`` or ``all_pages`` is set. + page_size: Rows per page. The SDK validates this against the endpoint-specific maximum. + limit: Maximum number of rows to return. The SDK may fetch multiple pages to satisfy this limit. + all_pages: Fetch and combine pages until the server reports the last page. + max_pages: Optional safety cap for ``all_pages``. + raw: Return the decoded JSON payload without tabular extraction. + fields: Optional field list or comma-separated field string applied after extraction. + as_dataframe: Return a pandas ``DataFrame`` by default; set to ``False`` for Python rows. + **kwargs: Extra request parameters forwarded unchanged. Useful when the service adds parameters before the SDK is regenerated. + + Returns: + A pandas ``DataFrame`` by default, Python rows when + ``as_dataframe=False``, raw JSON when ``raw=True``, or raw page + payloads when multi-page fetching is used with ``raw=True``. + """ + request_params = {'symbol': symbol, 'trade_date': trade_date, 'start_date': start_date, 'end_date': end_date} + request_params.update(kwargs) + path = ENDPOINTS['eastmoney_etf_flow'].path + return self.get_paginated( + path, + page=page, + page_size=page_size, + limit=limit, + all_pages=all_pages, + max_pages=max_pages, + max_page_size=ENDPOINTS['eastmoney_etf_flow'].max_page_size, + raw=raw, + fields=fields, + as_dataframe=as_dataframe, + **request_params, + ) + def eastmoney_market_valuation( self, market_code: Any | None = None, @@ -4510,6 +4570,13 @@ def ashare_rating_factor_snapshot(self, trade_code: Any | None = None, date: Any return self._call_endpoint('ashare_rating_factor_snapshot', raw=raw, fields=fields, as_dataframe=as_dataframe, **params) + def stock_minute_seal(self, trade_date: Any | None = None, symbol: Any | None = None, *, raw: bool = False, fields: Sequence[str] | str | None = None, as_dataframe: bool = True, **kwargs: Any) -> Any: + """股票分钟封单金额.""" + params = {'trade_date': trade_date, 'symbol': symbol} + params.update(kwargs) + return self._call_endpoint('stock_minute_seal', raw=raw, fields=fields, as_dataframe=as_dataframe, **params) + + def stock_minutes(self, symbol: Any | None = None, interval_value: Any | None = None, adjust_kind: Any | None = None, since_ts_millis: Any | None = None, until_ts_millis: Any | None = None, limit: Any | None = None, *, raw: bool = False, fields: Sequence[str] | str | None = None, as_dataframe: bool = True, **kwargs: Any) -> Any: """股票历史分钟行情.""" params = {'symbol': symbol, 'interval_value': interval_value, 'adjust_kind': adjust_kind, 'since_ts_millis': since_ts_millis, 'until_ts_millis': until_ts_millis, 'limit': limit} diff --git a/src/ftshare/endpoints/bond.py b/src/ftshare/endpoints/bond.py index b23a85c..3e6c4af 100644 --- a/src/ftshare/endpoints/bond.py +++ b/src/ftshare/endpoints/bond.py @@ -71,14 +71,6 @@ 'params': ('security_code', 'trade_date', 'start_date', 'end_date', 'page', 'page_size'), }, - 'szse_convertible_bond_declaration_snapshots': { - 'path': 'api/v1/market/data/convertible-bond/szse/declaration-snapshots', - 'title': '深交所可转债申报快照', - 'doc_file': '深交所可转债申报快照.md', - 'original_api': 'szse_convertible_bond_declaration_snapshots', - 'params': ('security_code', 'trade_date', 'start_date', 'end_date', 'page', 'page_size'), - }, - 'cb_lists': { 'path': 'api/v1/market/data/cb/cb-lists', 'title': '可转债列表', diff --git a/src/ftshare/endpoints/stock.py b/src/ftshare/endpoints/stock.py index 3509e0d..4995c6f 100644 --- a/src/ftshare/endpoints/stock.py +++ b/src/ftshare/endpoints/stock.py @@ -106,6 +106,14 @@ 'original_api': 'get_eastmoney_dapan_flow', 'params': ('trade_date', 'start_date', 'end_date', 'page', 'page_size'), }, + 'eastmoney_etf_flow': { + 'path': 'api/v1/market/data/eastmoney-etf-flow', + 'title': '东方财富ETF资金流', + 'doc_file': '东方财富ETF资金流.md', + 'original_api': 'get_eastmoney_etf_flow', + 'params': ('symbol', 'trade_date', 'start_date', 'end_date', 'page', 'page_size'), + 'max_page_size': 1000, + }, 'eastmoney_market_valuation': { 'path': 'api/v1/market/data/eastmoney-market-valuation', 'title': '东方财富市场估值', @@ -789,6 +797,14 @@ 'params': ('trade_code', 'date', 'top_k'), }, + 'stock_minute_seal': { + 'path': 'api/v2/market/data/stock-minute-seal', + 'title': '股票分钟封单金额', + 'doc_file': '股票分钟封单金额.md', + 'original_api': 'stock_minute_seal', + 'params': ('trade_date', 'symbol'), + }, + 'stock_minutes': { 'path': 'api/v2/market/data/stock_minutes', 'title': '股票历史分钟行情', diff --git a/tests/endpoint_cases.py b/tests/endpoint_cases.py index 807bd1e..f7666d3 100644 --- a/tests/endpoint_cases.py +++ b/tests/endpoint_cases.py @@ -229,7 +229,6 @@ "stock_realtime_day_kline": {"symbols": '["600519.SH"]'}, "stock_realtime_minute_kline": {"symbols": '["600519.SH"]'}, "stock_unlock": {"stock_code": None, "start_date": "20260701", "end_date": "20260717", "page": 1, "page_size": 5}, - "szse_convertible_bond_declaration_snapshots": {"security_code": "113000.SZ", "trade_date": "20260717", "start_date": None, "end_date": None, "page": 1, "page_size": 5}, "szse_convertible_bond_directed_trades": {"security_code": "113000.SZ", "trade_date": "20260717", "start_date": None, "end_date": None, "page": 1, "page_size": 5}, "szse_convertible_bond_matching_trades": {"security_code": "113000.SZ", "trade_date": "20260717", "start_date": None, "end_date": None, "page": 1, "page_size": 5}, "szse_convertible_bond_negotiated_trades": {"security_code": "113000.SZ", "trade_date": "20260717", "start_date": None, "end_date": None, "page": 1, "page_size": 5}, @@ -291,6 +290,7 @@ def _millis(day: str, time: str = "00:00:00") -> int: "bullion_price": {"symbol": "XAUUSD", "start_date": 20260101, "end_date": 20260918, "page": 1, "page_size": 5}, "china_futures_base_data": {"trade_date": None, "symbol": None}, "company_list": {"stock_name": None, "stock_code": None, "page": 1, "page_size": 5}, + "eastmoney_etf_flow": {"symbol": "159231.SZ", "trade_date": "20260921", "start_date": None, "end_date": None, "page": 1, "page_size": 5}, "eastmoney_futures_position": {"exchange": None, "variety_code": None, "contract_code": None, "trade_date": None, "start_date": None, "end_date": None, "member_name_abbr": None, "page": 1, "page_size": 5}, "eastmoney_rank": {"rank_group": "hot", "market": "A", "trade_date": None}, "eastmoney_sector_flow": {"board_code": None, "board_type": None, "board_level": None, "trade_date": None, "start_date": None, "end_date": None, "page": 1, "page_size": 5}, @@ -318,9 +318,9 @@ def _millis(day: str, time: str = "00:00:00") -> int: "stock_dividends": {"symbol": "600519.SH", "since_date": None, "until_date": None, "page": 1, "page_size": 5}, "stock_dividends_effective": {"symbol": "600519.SH", "since_date": None, "until_date": None, "page": 1, "page_size": 5}, "stock_ggmx": {"stock_code": None, "change_direction": None, "start_date": None, "end_date": None, "page": 1, "page_size": 5}, + "stock_minute_seal": {"trade_date": "20260923", "symbol": "000560.SZ"}, "sw_industry_constituent_history": {"industry_code": "801010.SI"}, "sw_industry_daily_metrics": {"level": None, "start_date": "20260901", "end_date": "20260918", "industry_code": "801010.SI", "page": 1, "page_size": 5}, - "szse_convertible_bond_declaration_snapshots": {"security_code": None, "trade_date": None, "start_date": None, "end_date": None, "page": 1, "page_size": 5}, "szse_convertible_bond_directed_trades": {"security_code": None, "trade_date": None, "start_date": None, "end_date": None, "page": 1, "page_size": 5}, "szse_convertible_bond_matching_trades": {"security_code": None, "trade_date": None, "start_date": None, "end_date": None, "page": 1, "page_size": 5}, "szse_convertible_bond_negotiated_trades": {"security_code": None, "trade_date": None, "start_date": None, "end_date": None, "page": 1, "page_size": 5}, diff --git a/tests/test_client.py b/tests/test_client.py index d416563..b446036 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -292,6 +292,7 @@ def test_requested_endpoint_api_versions(): "stock_prospectuses": "api/v2/market/data/announcements/stock-prospectuses", "stock_reports": "api/v2/market/data/report/stock-reports", "stock_minutes": "api/v2/market/data/stock_minutes", + "stock_minute_seal": "api/v2/market/data/stock-minute-seal", "futures_minutes": "api/v2/market/data/futures_minutes", "etf_minutes": "api/v2/market/data/etf_minutes", "index_minutes": "api/v2/market/data/index_minutes", @@ -344,6 +345,7 @@ def test_requested_endpoint_api_versions(): "ths_stock_daily_flow": "api/v1/market/data/ths-stock-daily-flow", "ths_concept_daily_flow": "api/v1/market/data/ths-concept-daily-flow", "ths_industry_daily_flow": "api/v1/market/data/ths-industry-daily-flow", + "eastmoney_etf_flow": "api/v1/market/data/eastmoney-etf-flow", } assert {name: ENDPOINTS[name].path for name in expected_paths} == expected_paths @@ -438,6 +440,36 @@ def test_new_batch_endpoints_forward_symbols_and_documented_parameters(): assert session.calls[0]["params"] == kwargs +def test_eastmoney_etf_flow_allows_page_size_up_to_1000(): + session = FakeSession([FakeResponse(payload=paginated_records([]))]) + client = FtshareClient(session=session) + + client.eastmoney_etf_flow(page=1, page_size=1000, as_dataframe=False) + + assert session.calls[0]["url"] == "https://market.ft.tech/gateway/api/v1/market/data/eastmoney-etf-flow" + assert session.calls[0]["params"] == {"page": 1, "page_size": 1000} + + with pytest.raises(ValueError, match="page_size must be between 1 and 1000"): + client.eastmoney_etf_flow(page_size=1001) + + +def test_stock_minute_seal_forwards_documented_parameters(): + session = FakeSession([ + FakeResponse(payload={"code": 200, "message": "success", "data": []}), + FakeResponse(payload={"code": 200, "message": "success", "data": []}), + ]) + client = FtshareClient(session=session) + + client.stock_minute_seal(trade_date="20260923", symbol="600825.SH", as_dataframe=False) + + assert session.calls[0]["url"] == "https://market.ft.tech/gateway/api/v2/market/data/stock-minute-seal" + assert session.calls[0]["params"] == {"trade_date": "20260923", "symbol": "600825.SH"} + + client.stock_minute_seal(trade_date="20260923", as_dataframe=False) + + assert session.calls[1]["params"] == {"trade_date": "20260923"} + + def test_stock_description_uses_paginated_route_and_filters(): session = FakeSession([FakeResponse(payload=paginated_records([{"symbol": "600000.SH"}]))]) client = FtshareClient(session=session) diff --git a/tests/test_integration_market.py b/tests/test_integration_market.py index 3159fd0..986fca0 100644 --- a/tests/test_integration_market.py +++ b/tests/test_integration_market.py @@ -20,7 +20,6 @@ KNOWN_SERVER_ISSUES: dict[str, str] = { "ashare_news_sentiment_factors": "HTTP 502 下游服务请求失败 for every parameter combination", "futures_minutes_batch": "HTTP 404 请求的资源不存在 — route absent on the test server", - "szse_convertible_bond_declaration_snapshots": "HTTP 200 but empty for every date range, while sibling exchange tables return rows", }