reportify-sdk 0.1.0__tar.gz → 0.2.1__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reportify-sdk
3
- Version: 0.1.0
3
+ Version: 0.2.1
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "reportify-sdk"
7
- version = "0.1.0"
7
+ version = "0.2.1"
8
8
  description = "Python SDK for Reportify API - Financial data and document search"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -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()
@@ -0,0 +1,404 @@
1
+ """
2
+ Quant Module
3
+
4
+ Provides quantitative analysis tools including indicators, factors, quotes, and backtesting.
5
+ Based on Mai-language syntax compatible with TongDaXin/TongHuaShun.
6
+ """
7
+
8
+ from typing import Any, Literal
9
+
10
+ import pandas as pd
11
+
12
+
13
+ StockMarket = Literal["cn", "hk", "us"]
14
+
15
+
16
+ class QuantModule:
17
+ """
18
+ Quantitative analysis module
19
+
20
+ Access technical indicators, factors, OHLCV quotes, and backtesting functionality.
21
+ Uses Mai-language syntax for formulas.
22
+
23
+ Example:
24
+ >>> quant = client.quant
25
+ >>> # Compute RSI indicator
26
+ >>> df = quant.compute_indicators(["000001"], "RSI(14)")
27
+ >>> # Screen stocks by formula
28
+ >>> stocks = quant.screen(formula="RSI(14) < 30")
29
+ """
30
+
31
+ def __init__(self, client):
32
+ self._client = client
33
+
34
+ # -------------------------------------------------------------------------
35
+ # Indicators
36
+ # -------------------------------------------------------------------------
37
+
38
+ def list_indicators(self) -> list[dict[str, Any]]:
39
+ """
40
+ Get list of available technical indicators
41
+
42
+ Returns:
43
+ List of indicator definitions with name, description, and fields
44
+
45
+ Example:
46
+ >>> indicators = client.quant.list_indicators()
47
+ >>> for ind in indicators:
48
+ ... print(f"{ind['name']}: {ind['description']}")
49
+ ... print(f" Fields: {ind['fields']}")
50
+ """
51
+ return self._client._get("/v1/quant/indicators")
52
+
53
+ def compute_indicators(
54
+ self,
55
+ symbols: list[str],
56
+ formula: str,
57
+ *,
58
+ market: StockMarket = "cn",
59
+ start_date: str | None = None,
60
+ end_date: str | None = None,
61
+ ) -> pd.DataFrame:
62
+ """
63
+ Compute indicator values for given symbols
64
+
65
+ Args:
66
+ symbols: List of stock codes (e.g., ["000001", "600519"])
67
+ formula: Indicator formula (e.g., "RSI(14)", "MACD()", "MACD(12,26,9)")
68
+ market: Stock market ("cn", "hk", "us"), default "cn"
69
+ start_date: Start date (YYYY-MM-DD), default 3 months ago
70
+ end_date: End date (YYYY-MM-DD), default today
71
+
72
+ Returns:
73
+ DataFrame with indicator values
74
+
75
+ Example:
76
+ >>> # RSI indicator
77
+ >>> df = client.quant.compute_indicators(["000001"], "RSI(14)")
78
+ >>> print(df[["symbol", "date", "rsi"]])
79
+
80
+ >>> # MACD indicator
81
+ >>> df = client.quant.compute_indicators(["000001"], "MACD()")
82
+ >>> print(df[["symbol", "date", "dif", "dea", "macd"]])
83
+
84
+ >>> # KDJ indicator
85
+ >>> df = client.quant.compute_indicators(["000001"], "KDJ(9,3,3)")
86
+ >>> print(df[["symbol", "date", "k", "d", "j"]])
87
+ """
88
+ data: dict[str, Any] = {
89
+ "symbols": symbols,
90
+ "formula": formula,
91
+ "market": market,
92
+ }
93
+ if start_date:
94
+ data["start_date"] = start_date
95
+ if end_date:
96
+ data["end_date"] = end_date
97
+
98
+ response = self._client._post("/v1/quant/indicators/compute", json=data)
99
+ return self._to_dataframe(response.get("datas", []))
100
+
101
+ # -------------------------------------------------------------------------
102
+ # Factors
103
+ # -------------------------------------------------------------------------
104
+
105
+ def list_factors(self) -> list[dict[str, Any]]:
106
+ """
107
+ Get list of available factors (variables and functions)
108
+
109
+ Returns factors organized by level:
110
+ - Level 0 Variables: CLOSE, OPEN, HIGH, LOW, VOLUME
111
+ - Level 0 Functions: MA, EMA, REF, HHV, LLV, STD, etc.
112
+ - Level 1 Functions: CROSS, COUNT, EVERY, etc.
113
+ - Level 2 Functions: MACD, KDJ, RSI, BOLL, etc.
114
+
115
+ Returns:
116
+ List of factor definitions
117
+
118
+ Example:
119
+ >>> factors = client.quant.list_factors()
120
+ >>> for f in factors:
121
+ ... print(f"{f['name']} ({f['type']}, level {f['level']})")
122
+ """
123
+ return self._client._get("/v1/quant/factors")
124
+
125
+ def compute_factors(
126
+ self,
127
+ symbols: list[str],
128
+ formula: str,
129
+ *,
130
+ market: StockMarket = "cn",
131
+ start_date: str | None = None,
132
+ end_date: str | None = None,
133
+ ) -> pd.DataFrame:
134
+ """
135
+ Compute factor values for given symbols
136
+
137
+ Uses Mai-language syntax compatible with TongDaXin/TongHuaShun.
138
+
139
+ Args:
140
+ symbols: List of stock codes
141
+ formula: Factor formula using Mai-language syntax
142
+ market: Stock market ("cn", "hk", "us"), default "cn"
143
+ start_date: Start date (YYYY-MM-DD), default 3 months ago
144
+ end_date: End date (YYYY-MM-DD), default today
145
+
146
+ Returns:
147
+ DataFrame with factor values
148
+
149
+ Example:
150
+ >>> # Simple indicator
151
+ >>> df = client.quant.compute_factors(["000001"], "RSI(14)")
152
+
153
+ >>> # MACD DIF line
154
+ >>> df = client.quant.compute_factors(["000001"], "MACD().dif")
155
+
156
+ >>> # Close above 20-day MA (boolean)
157
+ >>> df = client.quant.compute_factors(["000001"], "CLOSE > MA(20)")
158
+
159
+ >>> # Deviation from MA20 in percent
160
+ >>> df = client.quant.compute_factors(["000001"], "(CLOSE - MA(20)) / MA(20) * 100")
161
+
162
+ Supported Operators:
163
+ - Comparison: >, <, >=, <=, ==, !=
164
+ - Logical AND: & (NOT "AND")
165
+ - Logical OR: | (NOT "OR")
166
+ - Arithmetic: +, -, *, /
167
+
168
+ Supported Variables:
169
+ - CLOSE, C: Close price
170
+ - OPEN, O: Open price
171
+ - HIGH, H: High price
172
+ - LOW, L: Low price
173
+ - VOLUME, V, VOL: Volume
174
+ """
175
+ data: dict[str, Any] = {
176
+ "symbols": symbols,
177
+ "formula": formula,
178
+ "market": market,
179
+ }
180
+ if start_date:
181
+ data["start_date"] = start_date
182
+ if end_date:
183
+ data["end_date"] = end_date
184
+
185
+ response = self._client._post("/v1/quant/factors/compute", json=data)
186
+ return self._to_dataframe(response.get("datas", []))
187
+
188
+ def screen(
189
+ self,
190
+ formula: str,
191
+ *,
192
+ market: StockMarket = "cn",
193
+ check_date: str | None = None,
194
+ symbols: list[str] | None = None,
195
+ ) -> pd.DataFrame:
196
+ """
197
+ Screen stocks based on factor formula
198
+
199
+ Returns stocks where the formula evaluates to True (for boolean formulas)
200
+ or non-null (for numeric formulas).
201
+
202
+ Args:
203
+ formula: Screening formula using Mai-language syntax
204
+ market: Stock market ("cn", "hk", "us"), default "cn"
205
+ check_date: Check date (YYYY-MM-DD), default latest trading day
206
+ symbols: Stock codes to screen (None = full market)
207
+
208
+ Returns:
209
+ DataFrame with stocks that passed the filter
210
+
211
+ Example:
212
+ >>> # RSI oversold
213
+ >>> stocks = client.quant.screen(formula="RSI(14) < 30")
214
+
215
+ >>> # Golden cross
216
+ >>> stocks = client.quant.screen(formula="CROSS(MA(5), MA(10))")
217
+
218
+ >>> # Uptrend
219
+ >>> stocks = client.quant.screen(formula="(CLOSE > MA(20)) & (MA(20) > MA(60))")
220
+
221
+ >>> # Above upper Bollinger Band
222
+ >>> stocks = client.quant.screen(formula="CLOSE > BOLL(20, 2).upper")
223
+
224
+ >>> # Screen specific stocks
225
+ >>> stocks = client.quant.screen(
226
+ ... formula="RSI(14) < 30",
227
+ ... symbols=["000001", "600519", "000002"]
228
+ ... )
229
+ """
230
+ data: dict[str, Any] = {
231
+ "formula": formula,
232
+ "market": market,
233
+ }
234
+ if check_date:
235
+ data["check_date"] = check_date
236
+ if symbols:
237
+ data["symbols"] = symbols
238
+
239
+ response = self._client._post("/v1/quant/factors/screen", json=data)
240
+ return self._to_dataframe(response.get("datas", []))
241
+
242
+ # -------------------------------------------------------------------------
243
+ # Quotes
244
+ # -------------------------------------------------------------------------
245
+
246
+ def ohlcv(
247
+ self,
248
+ symbol: str,
249
+ *,
250
+ market: StockMarket = "cn",
251
+ start_date: str | None = None,
252
+ end_date: str | None = None,
253
+ ) -> pd.DataFrame:
254
+ """
255
+ Get OHLCV (Open, High, Low, Close, Volume) daily data for a single symbol
256
+
257
+ Args:
258
+ symbol: Stock code
259
+ market: Stock market ("cn", "hk", "us"), default "cn"
260
+ start_date: Start date (YYYY-MM-DD), default 1 month ago
261
+ end_date: End date (YYYY-MM-DD), default today
262
+
263
+ Returns:
264
+ DataFrame with OHLCV data
265
+
266
+ Example:
267
+ >>> df = client.quant.ohlcv("000001")
268
+ >>> print(df[["open", "high", "low", "close", "volume"]])
269
+ """
270
+ params: dict[str, Any] = {
271
+ "symbol": symbol,
272
+ "market": market,
273
+ }
274
+ if start_date:
275
+ params["start_date"] = start_date
276
+ if end_date:
277
+ params["end_date"] = end_date
278
+
279
+ response = self._client._get("/v1/quant/quotes/ohlcv", params=params)
280
+ return self._to_dataframe(response.get("datas", []))
281
+
282
+ def ohlcv_batch(
283
+ self,
284
+ symbols: list[str],
285
+ *,
286
+ market: StockMarket = "cn",
287
+ start_date: str | None = None,
288
+ end_date: str | None = None,
289
+ ) -> pd.DataFrame:
290
+ """
291
+ Get OHLCV data for multiple symbols
292
+
293
+ Args:
294
+ symbols: List of stock codes
295
+ market: Stock market ("cn", "hk", "us"), default "cn"
296
+ start_date: Start date (YYYY-MM-DD), default 1 month ago
297
+ end_date: End date (YYYY-MM-DD), default today
298
+
299
+ Returns:
300
+ DataFrame with OHLCV data sorted by date (descending), then by symbol
301
+
302
+ Example:
303
+ >>> df = client.quant.ohlcv_batch(["000001", "600519"])
304
+ >>> print(df[["symbol", "date", "close", "volume"]])
305
+ """
306
+ data: dict[str, Any] = {
307
+ "symbols": symbols,
308
+ "market": market,
309
+ }
310
+ if start_date:
311
+ data["start_date"] = start_date
312
+ if end_date:
313
+ data["end_date"] = end_date
314
+
315
+ response = self._client._post("/v1/quant/quotes/ohlcv/batch", json=data)
316
+ return self._to_dataframe(response.get("datas", []))
317
+
318
+ # -------------------------------------------------------------------------
319
+ # Backtest
320
+ # -------------------------------------------------------------------------
321
+
322
+ def backtest(
323
+ self,
324
+ symbol: str,
325
+ formula: str,
326
+ start_date: str,
327
+ end_date: str,
328
+ *,
329
+ market: StockMarket = "cn",
330
+ initial_cash: float = 100000.0,
331
+ commission: float = 0.0,
332
+ stop_loss: float = 0.0,
333
+ sizer_percent: int = 99,
334
+ auto_close: bool = True,
335
+ ) -> dict[str, Any]:
336
+ """
337
+ Execute strategy backtest
338
+
339
+ Args:
340
+ symbol: Stock code
341
+ formula: Trading strategy formula using Mai-language syntax
342
+ start_date: Backtest start date (YYYY-MM-DD)
343
+ end_date: Backtest end date (YYYY-MM-DD)
344
+ market: Stock market ("cn", "hk", "us"), default "cn"
345
+ initial_cash: Initial capital (default: 100000.0)
346
+ commission: Commission rate (default: 0.0)
347
+ stop_loss: Stop loss setting (default: 0.0, no stop loss)
348
+ sizer_percent: Position percentage (default: 99%)
349
+ auto_close: Auto close positions (default: True)
350
+
351
+ Returns:
352
+ Backtest results including:
353
+ - success: Whether backtest succeeded
354
+ - initial_cash: Initial capital
355
+ - final_cash: Final capital
356
+ - total_return: Total return
357
+ - total_return_pct: Total return percentage
358
+ - max_drawdown: Maximum drawdown
359
+ - profit_factor: Profit factor
360
+ - win_rate: Win rate
361
+ - total_trades: Total number of trades
362
+ - trades: List of trade details
363
+
364
+ Example:
365
+ >>> result = client.quant.backtest(
366
+ ... symbol="000001",
367
+ ... formula="CROSS(MA(5), MA(20))", # Golden cross buy signal
368
+ ... start_date="2023-01-01",
369
+ ... end_date="2024-01-01",
370
+ ... initial_cash=100000
371
+ ... )
372
+ >>> print(f"Total Return: {result['total_return_pct']:.2%}")
373
+ >>> print(f"Max Drawdown: {result['max_drawdown']:.2%}")
374
+ >>> print(f"Win Rate: {result['win_rate']:.2%}")
375
+ """
376
+ data = {
377
+ "symbol": symbol,
378
+ "formula": formula,
379
+ "start_date": start_date,
380
+ "end_date": end_date,
381
+ "market": market,
382
+ "initial_cash": initial_cash,
383
+ "commission": commission,
384
+ "stop_loss": stop_loss,
385
+ "sizer_percent": sizer_percent,
386
+ "auto_close": auto_close,
387
+ }
388
+
389
+ return self._client._post("/v1/quant/backtest", json=data)
390
+
391
+ # -------------------------------------------------------------------------
392
+ # Helper Methods
393
+ # -------------------------------------------------------------------------
394
+
395
+ def _to_dataframe(self, data: list[dict[str, Any]]) -> pd.DataFrame:
396
+ """Convert API response to DataFrame"""
397
+ if not data:
398
+ return pd.DataFrame()
399
+ df = pd.DataFrame(data)
400
+ # Convert date columns if present
401
+ for col in ["date", "check_date", "trade_date"]:
402
+ if col in df.columns:
403
+ df[col] = pd.to_datetime(df[col])
404
+ 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.1
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
@@ -6,6 +6,7 @@ reportify_sdk/client.py
6
6
  reportify_sdk/docs.py
7
7
  reportify_sdk/exceptions.py
8
8
  reportify_sdk/kb.py
9
+ reportify_sdk/quant.py
9
10
  reportify_sdk/stock.py
10
11
  reportify_sdk/timeline.py
11
12
  reportify_sdk.egg-info/PKG-INFO
File without changes
File without changes
File without changes