reportify-sdk 0.2.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.2.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.2.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"
@@ -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.2.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
@@ -1,371 +0,0 @@
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
File without changes
File without changes
File without changes