tickflow 0.1.0__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,460 @@
1
+ """K-line (OHLCV) data resources for TickFlow API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Union, overload
6
+
7
+ from .._types import NOT_GIVEN, NotGiven
8
+ from ._base import AsyncResource, SyncResource
9
+
10
+ if TYPE_CHECKING:
11
+ import pandas as pd
12
+
13
+ from ..generated_model import CompactKlineData, Period
14
+
15
+
16
+ def _klines_to_dataframe(
17
+ data: "CompactKlineData", symbol: Optional[str] = None
18
+ ) -> "pd.DataFrame":
19
+ """Convert compact K-line data to a pandas DataFrame.
20
+
21
+ Parameters
22
+ ----------
23
+ data : CompactKlineData
24
+ Compact columnar K-line data from the API.
25
+ symbol : str, optional
26
+ Symbol code to include as a column.
27
+
28
+ Returns
29
+ -------
30
+ pd.DataFrame
31
+ DataFrame with columns: timestamp, open, high, low, close, volume, amount.
32
+ Index is set to timestamp converted to datetime.
33
+ """
34
+ import pandas as pd
35
+
36
+ df = pd.DataFrame(
37
+ {
38
+ "timestamp": data["timestamp"],
39
+ "open": data["open"],
40
+ "high": data["high"],
41
+ "low": data["low"],
42
+ "close": data["close"],
43
+ "volume": data["volume"],
44
+ "amount": data.get("amount", [0.0] * len(data["timestamp"])),
45
+ }
46
+ )
47
+
48
+ if symbol:
49
+ df.insert(0, "symbol", symbol)
50
+
51
+ # Convert timestamp (milliseconds) to datetime
52
+ df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
53
+ df.set_index("timestamp", inplace=True)
54
+
55
+ return df
56
+
57
+
58
+ def _batch_klines_to_dataframe(data: Dict[str, "CompactKlineData"]) -> "pd.DataFrame":
59
+ """Convert batch K-line data to a single pandas DataFrame.
60
+
61
+ Parameters
62
+ ----------
63
+ data : dict
64
+ Dictionary mapping symbol codes to compact K-line data.
65
+
66
+ Returns
67
+ -------
68
+ pd.DataFrame
69
+ Combined DataFrame with a 'symbol' column and MultiIndex (symbol, timestamp).
70
+ """
71
+ import pandas as pd
72
+
73
+ dfs = []
74
+ for symbol, kline_data in data.items():
75
+ df = _klines_to_dataframe(kline_data, symbol=symbol)
76
+ dfs.append(df)
77
+
78
+ if not dfs:
79
+ return pd.DataFrame()
80
+
81
+ combined = pd.concat(dfs)
82
+ combined.reset_index(inplace=True)
83
+ combined.set_index(["symbol", "timestamp"], inplace=True)
84
+ combined.sort_index(inplace=True)
85
+
86
+ return combined
87
+
88
+
89
+ class Klines(SyncResource):
90
+ """Synchronous interface for K-line (OHLCV) data endpoints.
91
+
92
+ Supports returning data as raw dicts or pandas DataFrames.
93
+
94
+ Examples
95
+ --------
96
+ >>> client = TickFlow(api_key="your-key")
97
+ >>>
98
+ >>> # Get raw K-line data
99
+ >>> klines = client.klines.get("600000.SH", count=100)
100
+ >>>
101
+ >>> # Get as DataFrame
102
+ >>> df = client.klines.get("600000.SH", count=100, as_dataframe=True)
103
+ >>> print(df.head())
104
+ """
105
+
106
+ @overload
107
+ def get(
108
+ self,
109
+ symbol: str,
110
+ *,
111
+ period: Union["Period", NotGiven] = NOT_GIVEN,
112
+ count: Union[int, NotGiven] = NOT_GIVEN,
113
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
114
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
115
+ as_dataframe: Literal[False] = False,
116
+ ) -> "CompactKlineData": ...
117
+
118
+ @overload
119
+ def get(
120
+ self,
121
+ symbol: str,
122
+ *,
123
+ period: Union["Period", NotGiven] = NOT_GIVEN,
124
+ count: Union[int, NotGiven] = NOT_GIVEN,
125
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
126
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
127
+ as_dataframe: Literal[True],
128
+ ) -> "pd.DataFrame": ...
129
+
130
+ def get(
131
+ self,
132
+ symbol: str,
133
+ *,
134
+ period: Union["Period", NotGiven] = NOT_GIVEN,
135
+ count: Union[int, NotGiven] = NOT_GIVEN,
136
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
137
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
138
+ as_dataframe: bool = False,
139
+ ) -> Union["CompactKlineData", "pd.DataFrame"]:
140
+ """Get K-line (OHLCV) data for a single symbol.
141
+
142
+ Parameters
143
+ ----------
144
+ symbol : str
145
+ Symbol code (e.g., "600000.SH", "AAPL.US").
146
+ period : str, optional
147
+ K-line period. One of: "1m", "5m", "10m", "15m", "30m", "60m",
148
+ "4h", "1d", "1w", "1M". Defaults to "1d".
149
+ count : int, optional
150
+ Number of K-lines to return. Default 100, max 10000.
151
+ start_time : int, optional
152
+ Start timestamp in milliseconds.
153
+ end_time : int, optional
154
+ End timestamp in milliseconds.
155
+ as_dataframe : bool, optional
156
+ If True, return a pandas DataFrame. If False (default), return
157
+ the raw compact columnar data.
158
+
159
+ Returns
160
+ -------
161
+ CompactKlineData or pd.DataFrame
162
+ If as_dataframe=False: dict with keys 'timestamp', 'open', 'high',
163
+ 'low', 'close', 'volume', 'amount' (each a list).
164
+ If as_dataframe=True: pandas DataFrame with datetime index.
165
+
166
+ Examples
167
+ --------
168
+ >>> # Get raw data
169
+ >>> data = client.klines.get("600000.SH", period="1d", count=10)
170
+ >>> print(data["close"][-1]) # Latest close price
171
+
172
+ >>> # Get as DataFrame for analysis
173
+ >>> df = client.klines.get("600000.SH", period="1d", count=100, as_dataframe=True)
174
+ >>> print(df.tail())
175
+ >>>
176
+ >>> # Calculate 20-day moving average
177
+ >>> df["ma20"] = df["close"].rolling(20).mean()
178
+ """
179
+ params = {"symbol": symbol}
180
+ if not isinstance(period, NotGiven):
181
+ params["period"] = period
182
+ if not isinstance(count, NotGiven):
183
+ params["count"] = count
184
+ if not isinstance(start_time, NotGiven) and start_time is not None:
185
+ params["start_time"] = start_time
186
+ if not isinstance(end_time, NotGiven) and end_time is not None:
187
+ params["end_time"] = end_time
188
+
189
+ response = self._client.get("/v1/klines", params=params)
190
+ data = response["data"]
191
+
192
+ if as_dataframe:
193
+ return _klines_to_dataframe(data, symbol=symbol)
194
+ return data
195
+
196
+ @overload
197
+ def batch(
198
+ self,
199
+ symbols: List[str],
200
+ *,
201
+ period: Union["Period", NotGiven] = NOT_GIVEN,
202
+ count: Union[int, NotGiven] = NOT_GIVEN,
203
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
204
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
205
+ as_dataframe: Literal[False] = False,
206
+ ) -> Dict[str, "CompactKlineData"]: ...
207
+
208
+ @overload
209
+ def batch(
210
+ self,
211
+ symbols: List[str],
212
+ *,
213
+ period: Union["Period", NotGiven] = NOT_GIVEN,
214
+ count: Union[int, NotGiven] = NOT_GIVEN,
215
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
216
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
217
+ as_dataframe: Literal[True],
218
+ ) -> "pd.DataFrame": ...
219
+
220
+ def batch(
221
+ self,
222
+ symbols: List[str],
223
+ *,
224
+ period: Union["Period", NotGiven] = NOT_GIVEN,
225
+ count: Union[int, NotGiven] = NOT_GIVEN,
226
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
227
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
228
+ as_dataframe: bool = False,
229
+ ) -> Union[Dict[str, "CompactKlineData"], "pd.DataFrame"]:
230
+ """Get K-line data for multiple symbols in a single request.
231
+
232
+ Parameters
233
+ ----------
234
+ symbols : list of str
235
+ List of symbol codes.
236
+ period : str, optional
237
+ K-line period. Defaults to "1d".
238
+ count : int, optional
239
+ Number of K-lines per symbol. Default 100.
240
+ start_time : int, optional
241
+ Start timestamp in milliseconds.
242
+ end_time : int, optional
243
+ End timestamp in milliseconds.
244
+ as_dataframe : bool, optional
245
+ If True, return a combined pandas DataFrame with MultiIndex.
246
+ If False (default), return a dict mapping symbols to K-line data.
247
+
248
+ Returns
249
+ -------
250
+ dict or pd.DataFrame
251
+ If as_dataframe=False: dict mapping symbol codes to CompactKlineData.
252
+ If as_dataframe=True: pandas DataFrame with MultiIndex (symbol, timestamp).
253
+
254
+ Examples
255
+ --------
256
+ >>> # Get raw data for multiple symbols
257
+ >>> data = client.klines.batch(["600000.SH", "000001.SZ"])
258
+ >>> for symbol, klines in data.items():
259
+ ... print(f"{symbol}: {len(klines['timestamp'])} bars")
260
+
261
+ >>> # Get as combined DataFrame
262
+ >>> df = client.klines.batch(["600000.SH", "000001.SZ"], as_dataframe=True)
263
+ >>> print(df.loc["600000.SH"].tail())
264
+ """
265
+ symbols_str = ",".join(symbols)
266
+ params = {"symbols": symbols_str}
267
+ if not isinstance(period, NotGiven):
268
+ params["period"] = period
269
+ if not isinstance(count, NotGiven):
270
+ params["count"] = count
271
+ if not isinstance(start_time, NotGiven) and start_time is not None:
272
+ params["start_time"] = start_time
273
+ if not isinstance(end_time, NotGiven) and end_time is not None:
274
+ params["end_time"] = end_time
275
+
276
+ response = self._client.get("/v1/klines/batch", params=params)
277
+ data = response["data"]
278
+
279
+ if as_dataframe:
280
+ return _batch_klines_to_dataframe(data)
281
+ return data
282
+
283
+
284
+ class AsyncKlines(AsyncResource):
285
+ """Asynchronous interface for K-line (OHLCV) data endpoints.
286
+
287
+ Supports returning data as raw dicts or pandas DataFrames.
288
+
289
+ Examples
290
+ --------
291
+ >>> async with AsyncTickFlow(api_key="your-key") as client:
292
+ ... # Get raw K-line data
293
+ ... klines = await client.klines.get("600000.SH", count=100)
294
+ ...
295
+ ... # Get as DataFrame
296
+ ... df = await client.klines.get("600000.SH", count=100, as_dataframe=True)
297
+ """
298
+
299
+ @overload
300
+ async def get(
301
+ self,
302
+ symbol: str,
303
+ *,
304
+ period: Union["Period", NotGiven] = NOT_GIVEN,
305
+ count: Union[int, NotGiven] = NOT_GIVEN,
306
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
307
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
308
+ as_dataframe: Literal[False] = False,
309
+ ) -> "CompactKlineData": ...
310
+
311
+ @overload
312
+ async def get(
313
+ self,
314
+ symbol: str,
315
+ *,
316
+ period: Union["Period", NotGiven] = NOT_GIVEN,
317
+ count: Union[int, NotGiven] = NOT_GIVEN,
318
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
319
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
320
+ as_dataframe: Literal[True],
321
+ ) -> "pd.DataFrame": ...
322
+
323
+ async def get(
324
+ self,
325
+ symbol: str,
326
+ *,
327
+ period: Union["Period", NotGiven] = NOT_GIVEN,
328
+ count: Union[int, NotGiven] = NOT_GIVEN,
329
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
330
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
331
+ as_dataframe: bool = False,
332
+ ) -> Union["CompactKlineData", "pd.DataFrame"]:
333
+ """Get K-line (OHLCV) data for a single symbol.
334
+
335
+ Parameters
336
+ ----------
337
+ symbol : str
338
+ Symbol code (e.g., "600000.SH", "AAPL.US").
339
+ period : str, optional
340
+ K-line period. One of: "1m", "5m", "10m", "15m", "30m", "60m",
341
+ "4h", "1d", "1w", "1M". Defaults to "1d".
342
+ count : int, optional
343
+ Number of K-lines to return. Default 100, max 10000.
344
+ start_time : int, optional
345
+ Start timestamp in milliseconds.
346
+ end_time : int, optional
347
+ End timestamp in milliseconds.
348
+ as_dataframe : bool, optional
349
+ If True, return a pandas DataFrame. If False (default), return
350
+ the raw compact columnar data.
351
+
352
+ Returns
353
+ -------
354
+ CompactKlineData or pd.DataFrame
355
+ If as_dataframe=False: dict with keys 'timestamp', 'open', 'high',
356
+ 'low', 'close', 'volume', 'amount' (each a list).
357
+ If as_dataframe=True: pandas DataFrame with datetime index.
358
+
359
+ Examples
360
+ --------
361
+ >>> df = await client.klines.get("600000.SH", period="1d", as_dataframe=True)
362
+ >>> print(df.tail())
363
+ """
364
+ params = {"symbol": symbol}
365
+ if not isinstance(period, NotGiven):
366
+ params["period"] = period
367
+ if not isinstance(count, NotGiven):
368
+ params["count"] = count
369
+ if not isinstance(start_time, NotGiven) and start_time is not None:
370
+ params["start_time"] = start_time
371
+ if not isinstance(end_time, NotGiven) and end_time is not None:
372
+ params["end_time"] = end_time
373
+
374
+ response = await self._client.get("/v1/klines", params=params)
375
+ data = response["data"]
376
+
377
+ if as_dataframe:
378
+ return _klines_to_dataframe(data, symbol=symbol)
379
+ return data
380
+
381
+ @overload
382
+ async def batch(
383
+ self,
384
+ symbols: List[str],
385
+ *,
386
+ period: Union["Period", NotGiven] = NOT_GIVEN,
387
+ count: Union[int, NotGiven] = NOT_GIVEN,
388
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
389
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
390
+ as_dataframe: Literal[False] = False,
391
+ ) -> Dict[str, "CompactKlineData"]: ...
392
+
393
+ @overload
394
+ async def batch(
395
+ self,
396
+ symbols: List[str],
397
+ *,
398
+ period: Union["Period", NotGiven] = NOT_GIVEN,
399
+ count: Union[int, NotGiven] = NOT_GIVEN,
400
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
401
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
402
+ as_dataframe: Literal[True],
403
+ ) -> "pd.DataFrame": ...
404
+
405
+ async def batch(
406
+ self,
407
+ symbols: List[str],
408
+ *,
409
+ period: Union["Period", NotGiven] = NOT_GIVEN,
410
+ count: Union[int, NotGiven] = NOT_GIVEN,
411
+ start_time: Union[int, None, NotGiven] = NOT_GIVEN,
412
+ end_time: Union[int, None, NotGiven] = NOT_GIVEN,
413
+ as_dataframe: bool = False,
414
+ ) -> Union[Dict[str, "CompactKlineData"], "pd.DataFrame"]:
415
+ """Get K-line data for multiple symbols in a single request.
416
+
417
+ Parameters
418
+ ----------
419
+ symbols : list of str
420
+ List of symbol codes.
421
+ period : str, optional
422
+ K-line period. Defaults to "1d".
423
+ count : int, optional
424
+ Number of K-lines per symbol. Default 100.
425
+ start_time : int, optional
426
+ Start timestamp in milliseconds.
427
+ end_time : int, optional
428
+ End timestamp in milliseconds.
429
+ as_dataframe : bool, optional
430
+ If True, return a combined pandas DataFrame with MultiIndex.
431
+ If False (default), return a dict mapping symbols to K-line data.
432
+
433
+ Returns
434
+ -------
435
+ dict or pd.DataFrame
436
+ If as_dataframe=False: dict mapping symbol codes to CompactKlineData.
437
+ If as_dataframe=True: pandas DataFrame with MultiIndex (symbol, timestamp).
438
+
439
+ Examples
440
+ --------
441
+ >>> df = await client.klines.batch(["600000.SH", "000001.SZ"], as_dataframe=True)
442
+ >>> print(df.loc["600000.SH"].tail())
443
+ """
444
+ symbols_str = ",".join(symbols)
445
+ params = {"symbols": symbols_str}
446
+ if not isinstance(period, NotGiven):
447
+ params["period"] = period
448
+ if not isinstance(count, NotGiven):
449
+ params["count"] = count
450
+ if not isinstance(start_time, NotGiven) and start_time is not None:
451
+ params["start_time"] = start_time
452
+ if not isinstance(end_time, NotGiven) and end_time is not None:
453
+ params["end_time"] = end_time
454
+
455
+ response = await self._client.get("/v1/klines/batch", params=params)
456
+ data = response["data"]
457
+
458
+ if as_dataframe:
459
+ return _batch_klines_to_dataframe(data)
460
+ return data