reportify-sdk 0.1.0__py3-none-any.whl → 0.2.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.
reportify_sdk/client.py CHANGED
@@ -61,6 +61,7 @@ class Reportify:
61
61
  self._kb = None
62
62
  self._docs = None
63
63
  self._tools = None
64
+ self._quant = None
64
65
 
65
66
  def _get_headers(self) -> dict[str, str]:
66
67
  """Get default headers for API requests"""
@@ -351,6 +352,14 @@ class Reportify:
351
352
  self._docs = DocsModule(self)
352
353
  return self._docs
353
354
 
355
+ @property
356
+ def quant(self):
357
+ """Quant module for indicators, factors, quotes, and backtesting"""
358
+ if self._quant is None:
359
+ from reportify_sdk.quant import QuantModule
360
+ self._quant = QuantModule(self)
361
+ return self._quant
362
+
354
363
  def close(self):
355
364
  """Close the HTTP client"""
356
365
  self._client.close()
reportify_sdk/quant.py ADDED
@@ -0,0 +1,371 @@
1
+ """
2
+ Quant Module
3
+
4
+ Provides quantitative analysis tools including indicators, factors, quotes, and backtesting.
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ import pandas as pd
10
+
11
+
12
+ class QuantModule:
13
+ """
14
+ Quantitative analysis module
15
+
16
+ Access technical indicators, factors, quotes, and backtesting functionality.
17
+
18
+ Example:
19
+ >>> quant = client.quant
20
+ >>> indicators = quant.indicators(symbols=["US:AAPL"], indicators=["ma", "rsi"])
21
+ """
22
+
23
+ def __init__(self, client):
24
+ self._client = client
25
+
26
+ # -------------------------------------------------------------------------
27
+ # Indicators
28
+ # -------------------------------------------------------------------------
29
+
30
+ def indicators(
31
+ self,
32
+ symbols: list[str],
33
+ indicators: list[str],
34
+ *,
35
+ start_date: str | None = None,
36
+ end_date: str | None = None,
37
+ interval: str = "1d",
38
+ params: dict[str, Any] | None = None,
39
+ ) -> pd.DataFrame:
40
+ """
41
+ Get technical indicators for given symbols
42
+
43
+ Args:
44
+ symbols: List of stock symbols (e.g., ["US:AAPL", "US:MSFT"])
45
+ indicators: List of indicator names (e.g., ["ma", "rsi", "macd", "bollinger"])
46
+ start_date: Start date (YYYY-MM-DD)
47
+ end_date: End date (YYYY-MM-DD)
48
+ interval: Data interval ("1d", "1w", "1m")
49
+ params: Additional indicator parameters (e.g., {"ma_period": 20})
50
+
51
+ Returns:
52
+ DataFrame with indicator values
53
+
54
+ Example:
55
+ >>> df = client.quant.indicators(
56
+ ... symbols=["US:AAPL"],
57
+ ... indicators=["ma", "rsi"],
58
+ ... params={"ma_period": 20, "rsi_period": 14}
59
+ ... )
60
+ >>> print(df[["close", "ma_20", "rsi_14"]])
61
+ """
62
+ data: dict[str, Any] = {
63
+ "symbols": symbols,
64
+ "indicators": indicators,
65
+ "interval": interval,
66
+ }
67
+ if start_date:
68
+ data["start_date"] = start_date
69
+ if end_date:
70
+ data["end_date"] = end_date
71
+ if params:
72
+ data["params"] = params
73
+
74
+ response = self._client._post("/v2/quant/indicators", json=data)
75
+ return self._to_dataframe(response.get("data", []))
76
+
77
+ def indicator_list(self) -> list[dict[str, Any]]:
78
+ """
79
+ Get list of available technical indicators
80
+
81
+ Returns:
82
+ List of indicator definitions with name, description, and parameters
83
+
84
+ Example:
85
+ >>> indicators = client.quant.indicator_list()
86
+ >>> for ind in indicators:
87
+ ... print(f"{ind['name']}: {ind['description']}")
88
+ """
89
+ response = self._client._get("/v2/quant/indicators")
90
+ return response.get("indicators", [])
91
+
92
+ # -------------------------------------------------------------------------
93
+ # Factors
94
+ # -------------------------------------------------------------------------
95
+
96
+ def factors(
97
+ self,
98
+ symbols: list[str],
99
+ factors: list[str],
100
+ *,
101
+ start_date: str | None = None,
102
+ end_date: str | None = None,
103
+ frequency: str = "daily",
104
+ ) -> pd.DataFrame:
105
+ """
106
+ Get factor data for given symbols
107
+
108
+ Args:
109
+ symbols: List of stock symbols
110
+ factors: List of factor names (e.g., ["momentum", "value", "quality", "size"])
111
+ start_date: Start date (YYYY-MM-DD)
112
+ end_date: End date (YYYY-MM-DD)
113
+ frequency: Data frequency ("daily", "weekly", "monthly")
114
+
115
+ Returns:
116
+ DataFrame with factor values
117
+
118
+ Example:
119
+ >>> df = client.quant.factors(
120
+ ... symbols=["US:AAPL", "US:MSFT"],
121
+ ... factors=["momentum", "value"],
122
+ ... frequency="monthly"
123
+ ... )
124
+ """
125
+ data: dict[str, Any] = {
126
+ "symbols": symbols,
127
+ "factors": factors,
128
+ "frequency": frequency,
129
+ }
130
+ if start_date:
131
+ data["start_date"] = start_date
132
+ if end_date:
133
+ data["end_date"] = end_date
134
+
135
+ response = self._client._post("/v2/quant/factors", json=data)
136
+ return self._to_dataframe(response.get("data", []))
137
+
138
+ def factor_list(self) -> list[dict[str, Any]]:
139
+ """
140
+ Get list of available factors
141
+
142
+ Returns:
143
+ List of factor definitions
144
+
145
+ Example:
146
+ >>> factors = client.quant.factor_list()
147
+ >>> for f in factors:
148
+ ... print(f"{f['name']}: {f['category']}")
149
+ """
150
+ response = self._client._get("/v2/quant/factors")
151
+ return response.get("factors", [])
152
+
153
+ def factor_exposure(
154
+ self,
155
+ symbols: list[str],
156
+ *,
157
+ date: str | None = None,
158
+ ) -> pd.DataFrame:
159
+ """
160
+ Get factor exposure for given symbols
161
+
162
+ Args:
163
+ symbols: List of stock symbols
164
+ date: Specific date (YYYY-MM-DD), defaults to latest
165
+
166
+ Returns:
167
+ DataFrame with factor exposures for each symbol
168
+
169
+ Example:
170
+ >>> exposure = client.quant.factor_exposure(["US:AAPL", "US:GOOGL"])
171
+ >>> print(exposure[["symbol", "momentum", "value", "quality"]])
172
+ """
173
+ data: dict[str, Any] = {"symbols": symbols}
174
+ if date:
175
+ data["date"] = date
176
+
177
+ response = self._client._post("/v2/quant/factors/exposure", json=data)
178
+ return self._to_dataframe(response.get("data", []))
179
+
180
+ # -------------------------------------------------------------------------
181
+ # Quotes
182
+ # -------------------------------------------------------------------------
183
+
184
+ def quotes(
185
+ self,
186
+ symbols: list[str],
187
+ *,
188
+ fields: list[str] | None = None,
189
+ ) -> pd.DataFrame:
190
+ """
191
+ Get real-time quotes for given symbols
192
+
193
+ Args:
194
+ symbols: List of stock symbols
195
+ fields: Specific fields to return (default: all)
196
+
197
+ Returns:
198
+ DataFrame with quote data
199
+
200
+ Example:
201
+ >>> quotes = client.quant.quotes(["US:AAPL", "US:MSFT"])
202
+ >>> print(quotes[["symbol", "price", "change", "volume"]])
203
+ """
204
+ data: dict[str, Any] = {"symbols": symbols}
205
+ if fields:
206
+ data["fields"] = fields
207
+
208
+ response = self._client._post("/v2/quant/quotes", json=data)
209
+ return self._to_dataframe(response.get("data", []))
210
+
211
+ def quotes_history(
212
+ self,
213
+ symbols: list[str],
214
+ *,
215
+ start_date: str | None = None,
216
+ end_date: str | None = None,
217
+ interval: str = "1d",
218
+ adjust: str = "forward",
219
+ limit: int = 100,
220
+ ) -> pd.DataFrame:
221
+ """
222
+ Get historical quotes data
223
+
224
+ Args:
225
+ symbols: List of stock symbols
226
+ start_date: Start date (YYYY-MM-DD)
227
+ end_date: End date (YYYY-MM-DD)
228
+ interval: Data interval ("1d", "1w", "1m")
229
+ adjust: Adjustment type ("forward", "backward", "none")
230
+ limit: Maximum records per symbol
231
+
232
+ Returns:
233
+ DataFrame with historical OHLCV data
234
+
235
+ Example:
236
+ >>> history = client.quant.quotes_history(
237
+ ... ["US:AAPL"],
238
+ ... start_date="2024-01-01",
239
+ ... interval="1d"
240
+ ... )
241
+ """
242
+ data: dict[str, Any] = {
243
+ "symbols": symbols,
244
+ "interval": interval,
245
+ "adjust": adjust,
246
+ "limit": limit,
247
+ }
248
+ if start_date:
249
+ data["start_date"] = start_date
250
+ if end_date:
251
+ data["end_date"] = end_date
252
+
253
+ response = self._client._post("/v2/quant/quotes/history", json=data)
254
+ return self._to_dataframe(response.get("data", []))
255
+
256
+ # -------------------------------------------------------------------------
257
+ # Backtest
258
+ # -------------------------------------------------------------------------
259
+
260
+ def backtest(
261
+ self,
262
+ strategy: dict[str, Any],
263
+ *,
264
+ start_date: str,
265
+ end_date: str,
266
+ initial_capital: float = 1000000.0,
267
+ benchmark: str | None = None,
268
+ ) -> dict[str, Any]:
269
+ """
270
+ Run a backtest for a given strategy
271
+
272
+ Args:
273
+ strategy: Strategy definition dict
274
+ start_date: Backtest start date (YYYY-MM-DD)
275
+ end_date: Backtest end date (YYYY-MM-DD)
276
+ initial_capital: Starting capital (default: 1,000,000)
277
+ benchmark: Benchmark symbol for comparison (e.g., "US:SPY")
278
+
279
+ Returns:
280
+ Backtest results including returns, metrics, and trades
281
+
282
+ Example:
283
+ >>> result = client.quant.backtest(
284
+ ... strategy={
285
+ ... "type": "momentum",
286
+ ... "universe": ["US:AAPL", "US:MSFT", "US:GOOGL"],
287
+ ... "rebalance": "monthly",
288
+ ... "top_n": 2
289
+ ... },
290
+ ... start_date="2020-01-01",
291
+ ... end_date="2024-01-01",
292
+ ... benchmark="US:SPY"
293
+ ... )
294
+ >>> print(f"Total Return: {result['metrics']['total_return']:.2%}")
295
+ """
296
+ data = {
297
+ "strategy": strategy,
298
+ "start_date": start_date,
299
+ "end_date": end_date,
300
+ "initial_capital": initial_capital,
301
+ }
302
+ if benchmark:
303
+ data["benchmark"] = benchmark
304
+
305
+ return self._client._post("/v2/quant/backtest", json=data)
306
+
307
+ def backtest_result(self, backtest_id: str) -> dict[str, Any]:
308
+ """
309
+ Get backtest result by ID
310
+
311
+ Args:
312
+ backtest_id: Backtest job ID
313
+
314
+ Returns:
315
+ Backtest results
316
+
317
+ Example:
318
+ >>> result = client.quant.backtest_result("bt_abc123")
319
+ """
320
+ return self._client._get(f"/v2/quant/backtest/{backtest_id}")
321
+
322
+ def backtest_returns(self, backtest_id: str) -> pd.DataFrame:
323
+ """
324
+ Get backtest return series
325
+
326
+ Args:
327
+ backtest_id: Backtest job ID
328
+
329
+ Returns:
330
+ DataFrame with daily returns
331
+
332
+ Example:
333
+ >>> returns = client.quant.backtest_returns("bt_abc123")
334
+ >>> print(returns[["date", "portfolio_value", "daily_return"]])
335
+ """
336
+ response = self._client._get(f"/v2/quant/backtest/{backtest_id}/returns")
337
+ return self._to_dataframe(response.get("data", []))
338
+
339
+ def backtest_trades(self, backtest_id: str) -> pd.DataFrame:
340
+ """
341
+ Get backtest trade history
342
+
343
+ Args:
344
+ backtest_id: Backtest job ID
345
+
346
+ Returns:
347
+ DataFrame with all trades
348
+
349
+ Example:
350
+ >>> trades = client.quant.backtest_trades("bt_abc123")
351
+ >>> print(trades[["date", "symbol", "action", "quantity", "price"]])
352
+ """
353
+ response = self._client._get(f"/v2/quant/backtest/{backtest_id}/trades")
354
+ return self._to_dataframe(response.get("data", []))
355
+
356
+ # -------------------------------------------------------------------------
357
+ # Helper Methods
358
+ # -------------------------------------------------------------------------
359
+
360
+ def _to_dataframe(self, data: list[dict[str, Any]]) -> pd.DataFrame:
361
+ """Convert API response to DataFrame"""
362
+ if not data:
363
+ return pd.DataFrame()
364
+ df = pd.DataFrame(data)
365
+ # Convert date columns if present
366
+ for col in ["date", "timestamp", "trade_date"]:
367
+ if col in df.columns:
368
+ df[col] = pd.to_datetime(df[col])
369
+ df = df.set_index(col)
370
+ break
371
+ return df
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reportify-sdk
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Python SDK for Reportify API - Financial data and document search
5
5
  Author-email: Reportify <support@reportify.cn>
6
6
  License-Expression: MIT
@@ -1,12 +1,13 @@
1
1
  reportify_sdk/__init__.py,sha256=f2bq8Exeuf5g7hAhEQ3qrS7wMVqZRXP7xmQEYA3Nvso,662
2
- reportify_sdk/client.py,sha256=JUptNGdgg-PnTrc7-g553KtNf3bl1uS51MkSyesSXic,10721
2
+ reportify_sdk/client.py,sha256=P56qBme48UPkZhMb9BlDnLMLXwHK-DjU7qDhGFFxMI0,11019
3
3
  reportify_sdk/docs.py,sha256=O30I1J4qTC8zpkVP_qu1cgT8nv6ysXNClqvaiRb0lhY,4957
4
4
  reportify_sdk/exceptions.py,sha256=r2_C_kTh6tCrQnfA3UozSqMMA-2OBnoP3pGpgYeqcdU,1049
5
5
  reportify_sdk/kb.py,sha256=-4UHWtudFncGRBB42B4YEoMPsEHr4QOtY55_8hKyogE,2240
6
+ reportify_sdk/quant.py,sha256=xXh4mz4B_iUh4PRbc0KI5e2FVtO0Hawvw_TMP_5rji4,11658
6
7
  reportify_sdk/stock.py,sha256=NcEhV9JfIQm2BsfYM1k-JVcxHhnnil32dp-bedGG4BU,13513
7
8
  reportify_sdk/timeline.py,sha256=b5Zj5SjXT4gP0dvEl8gXCWDZJHemyU7NSYahet2nHhc,4075
8
- reportify_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=zBUq4DL4lE-fZU_PMkr0gnxkYS1LhdRHFw8_LmCb-ek,1066
9
- reportify_sdk-0.1.0.dist-info/METADATA,sha256=1aUAHUgYmTjraaI3QAn_9Mxc7qfXohZqCuqwtkc6_IQ,4311
10
- reportify_sdk-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
- reportify_sdk-0.1.0.dist-info/top_level.txt,sha256=tc_dzCSWIDsNbHSi-FlyEEX8xwinhN9gl-CwyLRE4B0,14
12
- reportify_sdk-0.1.0.dist-info/RECORD,,
9
+ reportify_sdk-0.2.0.dist-info/licenses/LICENSE,sha256=zBUq4DL4lE-fZU_PMkr0gnxkYS1LhdRHFw8_LmCb-ek,1066
10
+ reportify_sdk-0.2.0.dist-info/METADATA,sha256=kmE-VtAC7lDLy6E4X8mWMVcq8gBpv-ukuFKple3J0F8,4311
11
+ reportify_sdk-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ reportify_sdk-0.2.0.dist-info/top_level.txt,sha256=tc_dzCSWIDsNbHSi-FlyEEX8xwinhN9gl-CwyLRE4B0,14
13
+ reportify_sdk-0.2.0.dist-info/RECORD,,