alphafeed 0.1.0.dev0__py3-none-any.whl

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.
@@ -0,0 +1,257 @@
1
+ """Real-time quote resources for AlphaFeed API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, List, Literal, Union, overload
6
+
7
+ import pandas as pd
8
+
9
+ from .._types import NOT_GIVEN, NotGiven
10
+ from ..utils import (
11
+ instrument_timestamp_to_trade_date,
12
+ instrument_timestamp_to_trade_time,
13
+ )
14
+ from ._base import SyncResource
15
+
16
+ if TYPE_CHECKING:
17
+ from ..models import Quote
18
+
19
+
20
+ def _quotes_to_dataframe(data: List["Quote"]) -> "pd.DataFrame":
21
+ """Convert quote data to a pandas DataFrame.
22
+
23
+ Parameters
24
+ ----------
25
+ data : list of Quote
26
+ List of quote dictionaries.
27
+
28
+ Returns
29
+ -------
30
+ pd.DataFrame
31
+ DataFrame with symbol as index. Includes trade_date, trade_time columns
32
+ and flattened ext fields with "ext." prefix (e.g., ext.limit_up, ext.change_pct).
33
+ """
34
+ if not data:
35
+ return pd.DataFrame()
36
+
37
+ rows = []
38
+ for q in data:
39
+ row = {k: v for k, v in q.items() if k not in ("ext", "session")}
40
+
41
+ row["trade_date"] = instrument_timestamp_to_trade_date(
42
+ q["symbol"], q["timestamp"], unit="ms"
43
+ )
44
+ row["trade_time"] = instrument_timestamp_to_trade_time(
45
+ q["symbol"], q["timestamp"], unit="ms"
46
+ )
47
+
48
+ ext = q.get("ext")
49
+ if ext:
50
+ for key, value in ext.items():
51
+ if value is not None and not isinstance(value, dict):
52
+ row[f"ext.{key}"] = value
53
+
54
+ rows.append(row)
55
+
56
+ df = pd.DataFrame(rows)
57
+ return df
58
+
59
+
60
+ class Quotes(SyncResource):
61
+ """Synchronous interface for real-time quote endpoints.
62
+
63
+ Supports querying quotes by symbol codes or universe IDs.
64
+
65
+ Examples
66
+ --------
67
+ >>> client = AlphaFeed(api_key="your-key")
68
+ >>>
69
+ >>> # Get quotes by symbols
70
+ >>> quotes = client.quotes.get(symbols=["600000.SH", "AAPL.US"])
71
+ >>>
72
+ >>> # Get quotes by universe
73
+ >>> quotes = client.quotes.get(universes=["CN_Stock"])
74
+ """
75
+
76
+ @overload
77
+ def get(
78
+ self,
79
+ *,
80
+ symbols: Union[List[str], str, None] = None,
81
+ universes: Union[List[str], str, None] = None,
82
+ to_dataframe: Literal[False] = False,
83
+ ) -> List["Quote"]: ...
84
+
85
+ @overload
86
+ def get(
87
+ self,
88
+ *,
89
+ symbols: Union[List[str], str, None] = None,
90
+ universes: Union[List[str], str, None] = None,
91
+ to_dataframe: Literal[True],
92
+ ) -> "pd.DataFrame": ...
93
+
94
+ def get(
95
+ self,
96
+ *,
97
+ symbols: Union[List[str], str, None] = None,
98
+ universes: Union[List[str], str, None] = None,
99
+ to_dataframe: bool = False,
100
+ ) -> Union[List["Quote"], "pd.DataFrame"]:
101
+ """Get real-time quotes for symbols or universes.
102
+
103
+ Must provide either `symbols` or `universes`, but not both.
104
+
105
+ Parameters
106
+ ----------
107
+ symbols : str or list of str, optional
108
+ Symbol code(s) to query. Can be a single symbol, comma-separated
109
+ string, or list of symbols.
110
+ universes : str or list of str, optional
111
+ Universe ID(s) to query. Can be a single ID, comma-separated
112
+ string, or list of IDs.
113
+ to_dataframe : bool, optional
114
+ If True, return a pandas DataFrame indexed by symbol.
115
+ If False (default), return a list of Quote dicts.
116
+
117
+ Returns
118
+ -------
119
+ list of Quote or pd.DataFrame
120
+ Quote data for the requested symbols.
121
+
122
+ Each Quote contains:
123
+ - symbol: Symbol code
124
+ - name: Symbol name
125
+ - region: Region code
126
+ - last_price: Latest price
127
+ - prev_close: Previous close
128
+ - open, high, low: OHLC prices
129
+ - volume: Trading volume
130
+ - amount: Trading amount
131
+ - timestamp: Quote timestamp (milliseconds)
132
+ - ext: Market-specific extension data
133
+
134
+ Raises
135
+ ------
136
+ ValueError
137
+ If neither or both of `symbols` and `universes` are provided.
138
+
139
+ Examples
140
+ --------
141
+ >>> # Query by symbols
142
+ >>> quotes = client.quotes.get(symbols=["600000.SH", "AAPL.US"])
143
+ >>> for q in quotes:
144
+ ... print(f"{q['symbol']}: {q['last_price']}")
145
+
146
+ >>> # Query by universe, as DataFrame
147
+ >>> df = client.quotes.get(universes="CN_Stock", to_dataframe=True)
148
+ >>> print(df[["last_price", "volume"]].head())
149
+
150
+ >>> # Find top gainers
151
+ >>> df["change_pct"] = (df["last_price"] - df["prev_close"]) / df["prev_close"] * 100
152
+ >>> top_gainers = df.nlargest(10, "change_pct")
153
+ """
154
+ if (symbols is None) == (universes is None):
155
+ raise ValueError(
156
+ "Must provide either 'symbols' or 'universes', but not both"
157
+ )
158
+
159
+ if symbols is not None:
160
+ if isinstance(symbols, str):
161
+ symbols_list = [s.strip() for s in symbols.split(",")]
162
+ else:
163
+ symbols_list = symbols
164
+
165
+ if len(symbols_list) <= 20:
166
+ response = self._client.get(
167
+ "/v1/quotes", params={"symbols": ",".join(symbols_list)}
168
+ )
169
+ else:
170
+ response = self._client.post(
171
+ "/v1/quotes", json={"symbols": symbols_list}
172
+ )
173
+ else:
174
+ if isinstance(universes, str):
175
+ universes_list = [u.strip() for u in universes.split(",")]
176
+ else:
177
+ universes_list = universes
178
+
179
+ if len(universes_list) <= 5:
180
+ response = self._client.get(
181
+ "/v1/quotes", params={"universes": ",".join(universes_list)}
182
+ )
183
+ else:
184
+ response = self._client.post(
185
+ "/v1/quotes", json={"universes": universes_list}
186
+ )
187
+
188
+ data = response["data"]
189
+
190
+ if to_dataframe:
191
+ return _quotes_to_dataframe(data)
192
+ return data
193
+
194
+ def get_by_symbols(
195
+ self,
196
+ symbols: List[str],
197
+ *,
198
+ to_dataframe: bool = False,
199
+ ) -> Union[List["Quote"], "pd.DataFrame"]:
200
+ """Get real-time quotes for a list of symbols.
201
+
202
+ This is a convenience method that always uses POST for batch queries.
203
+
204
+ Parameters
205
+ ----------
206
+ symbols : list of str
207
+ List of symbol codes.
208
+ to_dataframe : bool, optional
209
+ If True, return a pandas DataFrame.
210
+
211
+ Returns
212
+ -------
213
+ list of Quote or pd.DataFrame
214
+ Quote data for the requested symbols.
215
+
216
+ Examples
217
+ --------
218
+ >>> quotes = client.quotes.get_by_symbols(["600000.SH", "000001.SZ", "AAPL.US"])
219
+ """
220
+ response = self._client.post("/v1/quotes", json={"symbols": symbols})
221
+ data = response["data"]
222
+
223
+ if to_dataframe:
224
+ return _quotes_to_dataframe(data)
225
+ return data
226
+
227
+ def get_by_universes(
228
+ self,
229
+ universes: List[str],
230
+ *,
231
+ to_dataframe: bool = False,
232
+ ) -> Union[List["Quote"], "pd.DataFrame"]:
233
+ """Get real-time quotes for all symbols in the specified universes.
234
+
235
+ Parameters
236
+ ----------
237
+ universes : list of str
238
+ List of universe IDs.
239
+ to_dataframe : bool, optional
240
+ If True, return a pandas DataFrame.
241
+
242
+ Returns
243
+ -------
244
+ list of Quote or pd.DataFrame
245
+ Quote data for all symbols in the universes.
246
+
247
+ Examples
248
+ --------
249
+ >>> # Get all A-share quotes
250
+ >>> quotes = client.quotes.get_by_universes(["CN_Stock"], to_dataframe=True)
251
+ """
252
+ response = self._client.post("/v1/quotes", json={"universes": universes})
253
+ data = response["data"]
254
+
255
+ if to_dataframe:
256
+ return _quotes_to_dataframe(data)
257
+ return data
alphafeed/utils.py ADDED
@@ -0,0 +1,53 @@
1
+ import datetime
2
+ from zoneinfo import ZoneInfo
3
+
4
+ CN_TZ = ZoneInfo("Asia/Shanghai")
5
+ US_TZ = ZoneInfo("America/New_York")
6
+ HK_TZ = ZoneInfo("Asia/Hong_Kong")
7
+
8
+ symbol_suffix_region_map = {
9
+ "SH": "CN",
10
+ "SZ": "CN",
11
+ "BJ": "CN",
12
+ "US": "US",
13
+ "HK": "HK",
14
+ }
15
+
16
+ region_timezone_map = {
17
+ "CN": CN_TZ,
18
+ "US": US_TZ,
19
+ "HK": HK_TZ,
20
+ }
21
+
22
+
23
+ def get_instrument_region(symbol: str):
24
+ return symbol_suffix_region_map.get(
25
+ symbol.rsplit(".", 1)[-1],
26
+ )
27
+
28
+
29
+ def get_region_timezone(region: str):
30
+ return region_timezone_map.get(region)
31
+
32
+
33
+ def instrument_timestamp_to_datetime(symbol: str, timestamp: int, unit="ms"):
34
+ tz = get_region_timezone(get_instrument_region(symbol))
35
+ if tz is None:
36
+ return None
37
+
38
+ dt = (
39
+ datetime.datetime.fromtimestamp(timestamp / 1000, tz)
40
+ if unit == "ms"
41
+ else datetime.datetime.fromtimestamp(timestamp, tz)
42
+ )
43
+ return dt
44
+
45
+
46
+ def instrument_timestamp_to_trade_date(symbol: str, timestamp: int, unit="ms"):
47
+ dt = instrument_timestamp_to_datetime(symbol, timestamp, unit)
48
+ return dt.strftime("%Y-%m-%d")
49
+
50
+
51
+ def instrument_timestamp_to_trade_time(symbol: str, timestamp: int, unit="ms"):
52
+ dt = instrument_timestamp_to_datetime(symbol, timestamp, unit)
53
+ return dt.strftime("%Y-%m-%d %H:%M:%S")
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.4
2
+ Name: alphafeed
3
+ Version: 0.1.0.dev0
4
+ Summary: AlphaFeed Python SDK
5
+ Author: AlphaFeed
6
+ License: MIT
7
+ Project-URL: Documentation, https://docs.alphafeed.org
8
+ Keywords: finance,stock,market-data,quant,kline,alphafeed,a-share,us-stock,hk-stock,real-time-quotes
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Financial and Insurance Industry
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Office/Business :: Financial :: Investment
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: httpx>=0.25.0
24
+ Requires-Dist: typing-extensions>=4.0.0
25
+ Requires-Dist: pandas>=1.5.0
26
+ Requires-Dist: tqdm>=4.60.0
27
+
28
+ # AlphaFeed Python SDK
29
+
30
+ AlphaFeed Python SDK 是 AlphaFeed 金融市场数据 API 的 Python 客户端,支持 A 股、ETF、美股、港股。
31
+
32
+ > **完整文档**:<https://docs.alphafeed.org>
33
+
34
+ ---
35
+
36
+ ## 安装
37
+
38
+ ```bash
39
+ pip install alphafeed
40
+ ```
41
+
42
+ SDK 支持 Python 3.9+,推荐 3.10 或更高版本。内置 pandas 和 tqdm 支持。
43
+
44
+ ---
45
+
46
+ ## 初始化
47
+
48
+ ```python
49
+ from alphafeed import AlphaFeed
50
+
51
+ af = AlphaFeed(api_key="your-api-key")
52
+ ```
53
+
54
+ 也支持环境变量:
55
+
56
+ ```bash
57
+ export ALPHAFEED_API_KEY="your-api-key"
58
+ ```
59
+
60
+ ```python
61
+ from alphafeed import AlphaFeed
62
+ af = AlphaFeed() # 自动读取 ALPHAFEED_API_KEY
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 标的代码格式
68
+
69
+ | 示例 | 说明 |
70
+ |------|------|
71
+ | `600000.SH` | 上交所 |
72
+ | `000001.SZ` | 深交所 |
73
+ | `AAPL.US` | 美股 |
74
+ | `00700.HK` | 港股 |
75
+
76
+ ---
77
+
78
+ ## 基础用法
79
+
80
+ ### K 线获取
81
+
82
+ ```python
83
+ from alphafeed import AlphaFeed
84
+
85
+ af = AlphaFeed(api_key="your-api-key")
86
+
87
+ # 日 K 线,返回 DataFrame
88
+ df = af.klines.get("600000.SH", period="1d", count=100, to_dataframe=True)
89
+ print(df.tail())
90
+
91
+ # 分钟 K 线
92
+ df = af.klines.get("600000.SH", period="5m", count=100, to_dataframe=True)
93
+
94
+ # 前复权(默认)
95
+ df = af.klines.get("600519.SH", adjust="forward", to_dataframe=True)
96
+ ```
97
+
98
+ **批量获取**:多只标的一次拉取:
99
+
100
+ ```python
101
+ symbols = ["600000.SH", "000001.SZ", "600519.SH"]
102
+ dfs = af.klines.batch(symbols, period="1d", count=100, to_dataframe=True, show_progress=True)
103
+ print(dfs["600000.SH"].tail())
104
+ ```
105
+
106
+ ### 日内分时
107
+
108
+ ```python
109
+ # 当日分钟线
110
+ df = af.klines.intraday("600000.SH", to_dataframe=True)
111
+ print(df.tail())
112
+
113
+ # 批量日内分时
114
+ dfs = af.klines.intraday_batch(["600000.SH", "000001.SZ"], to_dataframe=True)
115
+ ```
116
+
117
+ ### 实时行情
118
+
119
+ **按标的代码查询**
120
+
121
+ ```python
122
+ quotes = af.quotes.get(symbols=["600000.SH", "000001.SZ", "00700.HK"], to_dataframe=True)
123
+ print(quotes)
124
+ ```
125
+
126
+ **按标的池查询**
127
+
128
+ ```python
129
+ # 全部 A 股行情
130
+ quotes_a = af.quotes.get(universes=["CN_Stock"], to_dataframe=True)
131
+ print(quotes_a)
132
+
133
+ # 全部 ETF 行情
134
+ quotes_etf = af.quotes.get(universes=["CN_ETF"], to_dataframe=True)
135
+ print(quotes_etf)
136
+ ```
137
+
138
+ 支持的标的池:`CN_Stock`(A股)、`US_Stock`(美股)、`HK_Stock`(港股)、`CN_ETF`(ETF)
139
+
140
+ ### 五档盘口
141
+
142
+ ```python
143
+ depth = af.depth.get("600000.SH")
144
+ print("买盘:", depth["bids"][:5])
145
+ print("卖盘:", depth["asks"][:5])
146
+ ```
147
+
148
+ ### 标的信息
149
+
150
+ ```python
151
+ instruments = af.instruments.batch(symbols=["600000.SH", "000001.SZ", "00700.HK"])
152
+ for inst in instruments:
153
+ print(f"{inst['symbol']}: {inst['name']}")
154
+ ```
155
+
156
+ ### 除权因子
157
+
158
+ ```python
159
+ factors = af.klines.ex_factors(symbols=["600000.SH", "600519.SH"], to_dataframe=True)
160
+ print(factors.tail())
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 更多文档
166
+
167
+ - [Python SDK 快速开始](https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart)
168
+ - [使用示例](https://docs.alphafeed.org/zh-Hans/sdk/python-examples)
169
+ - [HTTP API 说明](https://docs.alphafeed.org/zh-Hans/api-reference/introduction)
170
+
171
+ ---
172
+
173
+ ## License
174
+
175
+ MIT
@@ -0,0 +1,20 @@
1
+ alphafeed/__init__.py,sha256=rvVsIJV68pNsTSFB4IqrYD2WsZvUWZhb1lYN5nfoRxo,1071
2
+ alphafeed/__version__.py,sha256=WHizC8UzElmTH3641zjnMTLUHmP2rliWLTalgHU6vMA,75
3
+ alphafeed/_base_client.py,sha256=3R66eIZdyfeo-VWCNBhKh0dwoa2vNtDOdr57Lr5TOQw,9230
4
+ alphafeed/_batch.py,sha256=f2s8FVomnpoGpes1TqHBCE7Uj0R0Xbgrun9n_cq5tOg,2630
5
+ alphafeed/_cache.py,sha256=7NqTfFvtseEF6WfZEHuWLzEkkxSkUK--pbGRCfxSoXo,4383
6
+ alphafeed/_exceptions.py,sha256=C-hTGXkoUe5lhsbPN54naZU_GmLgN5WargeHT394HiA,3031
7
+ alphafeed/_types.py,sha256=Qgpp7UgF-R49ANuqetEhDszU-TXSS5ZMT4-jl5pPBeo,1191
8
+ alphafeed/client.py,sha256=eQFHNfx6jg5qYWP1oPu5R8P0zyGca6M6rfmxP6fe8O8,4198
9
+ alphafeed/models.py,sha256=EItKQNjdObo9YZ3EG1CusDcaTij2rDiYq4mBYs3jgzY,2014
10
+ alphafeed/utils.py,sha256=dOJoWw4QoAg3ufcch3JtRfFmzTBwhrFo0tI2WCUGVFM,1284
11
+ alphafeed/resources/__init__.py,sha256=GNt5jhqbFKlJYechYhjvbYksX4BEcDB-l4CuALXZglA,234
12
+ alphafeed/resources/_base.py,sha256=Ni3EM30Y-5DhABTfGaaeX2a-xmqwHll9FAqI10TdwIE,371
13
+ alphafeed/resources/depth.py,sha256=_ATcQvOzxWSfK_lLr0ABs5QxC5d_WPe-sIQmZG1Vq34,1232
14
+ alphafeed/resources/instruments.py,sha256=Eiljv8GPznLkqGyQfVNm-8jzrTVjJd7PyoMpExw3JCQ,3094
15
+ alphafeed/resources/klines.py,sha256=iNsYtyKohh6g3ml7TtCLZkuqtDQ1nKTDffJs0rY7lro,24927
16
+ alphafeed/resources/quotes.py,sha256=nsAhff0naw37HWnZVOeK6a71pc9ZZkYnIyYm_jWPDeI,7816
17
+ alphafeed-0.1.0.dev0.dist-info/METADATA,sha256=-h6PBH5Lf2Zj3bfKLFdk5IAkD-vU4ntrf1BXNcv3sb4,4038
18
+ alphafeed-0.1.0.dev0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
19
+ alphafeed-0.1.0.dev0.dist-info/top_level.txt,sha256=WkGzCvhzsoEoKS1iZmBwDLMM4P6M7eCU9zylBLi1iPc,10
20
+ alphafeed-0.1.0.dev0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ alphafeed