reportify-sdk 0.2.9__tar.gz → 0.3.0__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.
Files changed (25) hide show
  1. {reportify_sdk-0.2.9/reportify_sdk.egg-info → reportify_sdk-0.3.0}/PKG-INFO +102 -7
  2. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/README.md +101 -6
  3. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/pyproject.toml +1 -1
  4. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/__init__.py +1 -1
  5. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/chat.py +1 -1
  6. reportify_sdk-0.3.0/reportify_sdk/client.py +262 -0
  7. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/docs.py +4 -4
  8. reportify_sdk-0.3.0/reportify_sdk/search.py +357 -0
  9. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/stock.py +2 -2
  10. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0/reportify_sdk.egg-info}/PKG-INFO +102 -7
  11. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk.egg-info/SOURCES.txt +1 -0
  12. reportify_sdk-0.2.9/reportify_sdk/client.py +0 -580
  13. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/LICENSE +0 -0
  14. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/agent.py +0 -0
  15. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/channels.py +0 -0
  16. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/concepts.py +0 -0
  17. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/exceptions.py +0 -0
  18. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/kb.py +0 -0
  19. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/quant.py +0 -0
  20. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/timeline.py +0 -0
  21. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk/user.py +0 -0
  22. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk.egg-info/dependency_links.txt +0 -0
  23. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk.egg-info/requires.txt +0 -0
  24. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/reportify_sdk.egg-info/top_level.txt +0 -0
  25. {reportify_sdk-0.2.9 → reportify_sdk-0.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reportify-sdk
3
- Version: 0.2.9
3
+ Version: 0.3.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
@@ -75,19 +75,18 @@ balance = client.stock.balance_sheet("US:AAPL")
75
75
  cashflow = client.stock.cashflow_statement("US:AAPL")
76
76
 
77
77
  # Price data
78
- prices = client.stock.prices("US:AAPL", limit=30)
79
- kline = client.stock.kline("US:TSLA", interval="1d", limit=100)
78
+ prices = client.stock.prices("US:AAPL", start_date="2024-01-01")
80
79
 
81
- # Real-time quotes
82
- quotes = client.stock.quote(["US:AAPL", "US:MSFT"])
80
+ # Real-time quote
81
+ quote = client.stock.quote("US:AAPL")
83
82
 
84
83
  # Company info
85
84
  overview = client.stock.overview("US:AAPL")
86
85
  shareholders = client.stock.shareholders("US:AAPL")
87
86
 
88
87
  # Screening and calendar
89
- stocks = client.stock.screener(market="US", min_market_cap=1e10)
90
- earnings = client.stock.earnings_calendar(area="us", start_date="2024-01-01")
88
+ stocks = client.stock.screener(country="US", market_cap_more_than=1e10)
89
+ earnings = client.stock.earnings_calendar(market="us", start_date="2024-01-01", end_date="2024-01-31")
91
90
  ```
92
91
 
93
92
  ### Timeline
@@ -118,6 +117,102 @@ summary = client.docs.summary("doc_id")
118
117
  # List and search documents
119
118
  docs = client.docs.list(symbols=["US:AAPL"], page_size=10)
120
119
  chunks = client.docs.search_chunks("revenue breakdown", num=5)
120
+
121
+ # Upload documents
122
+ result = client.docs.upload([
123
+ {"url": "https://example.com/report.pdf", "name": "Annual Report"}
124
+ ])
125
+ ```
126
+
127
+ ### Quant (Quantitative Analysis)
128
+
129
+ ```python
130
+ # Compute technical indicators
131
+ df = client.quant.compute_indicators(["000001"], "RSI(14)")
132
+ df = client.quant.compute_indicators(["000001"], "MACD()")
133
+
134
+ # Screen stocks by formula
135
+ stocks = client.quant.screen(formula="RSI(14) < 30")
136
+ stocks = client.quant.screen(formula="CROSS(MA(5), MA(20))")
137
+
138
+ # Get OHLCV data
139
+ ohlcv = client.quant.ohlcv("000001", start_date="2024-01-01")
140
+ ohlcv_batch = client.quant.ohlcv_batch(["000001", "600519"])
141
+
142
+ # Backtest strategy
143
+ result = client.quant.backtest(
144
+ start_date="2023-01-01",
145
+ end_date="2024-01-01",
146
+ symbol="000001",
147
+ entry_formula="CROSS(MA(5), MA(20))",
148
+ exit_formula="CROSSDOWN(MA(5), MA(20))"
149
+ )
150
+ print(f"Total Return: {result['total_return_pct']:.2%}")
151
+ ```
152
+
153
+ ### Concepts
154
+
155
+ ```python
156
+ # Get latest concepts
157
+ concepts = client.concepts.latest()
158
+ for c in concepts:
159
+ print(c["concept_name"])
160
+
161
+ # Get today's concept feeds
162
+ feeds = client.concepts.today()
163
+ ```
164
+
165
+ ### Channels
166
+
167
+ ```python
168
+ # Search channels
169
+ result = client.channels.search("Goldman Sachs")
170
+
171
+ # Get followed channels
172
+ followings = client.channels.followings()
173
+
174
+ # Follow/unfollow a channel
175
+ client.channels.follow("channel_id")
176
+ client.channels.unfollow("channel_id")
177
+ ```
178
+
179
+ ### Chat
180
+
181
+ ```python
182
+ # Chat completion based on documents
183
+ response = client.chat.completion(
184
+ "What are Tesla's revenue projections?",
185
+ symbols=["US:TSLA"],
186
+ mode="comprehensive" # concise, comprehensive, deepresearch
187
+ )
188
+ print(response["message"])
189
+ ```
190
+
191
+ ### Agent
192
+
193
+ ```python
194
+ # Create agent conversation
195
+ conv = client.agent.create_conversation(agent_id=11887655289749510)
196
+
197
+ # Chat with agent
198
+ response = client.agent.chat(
199
+ conversation_id=conv["id"],
200
+ message="Analyze NVIDIA's latest earnings"
201
+ )
202
+
203
+ # Get agent-generated file
204
+ file_content = client.agent.get_file("file_id")
205
+ with open("output.xlsx", "wb") as f:
206
+ f.write(file_content)
207
+ ```
208
+
209
+ ### User
210
+
211
+ ```python
212
+ # Get followed companies
213
+ companies = client.user.followed_companies()
214
+ for company in companies:
215
+ print(f"{company['symbol']}: {company['name']}")
121
216
  ```
122
217
 
123
218
  ## Error Handling
@@ -46,19 +46,18 @@ balance = client.stock.balance_sheet("US:AAPL")
46
46
  cashflow = client.stock.cashflow_statement("US:AAPL")
47
47
 
48
48
  # Price data
49
- prices = client.stock.prices("US:AAPL", limit=30)
50
- kline = client.stock.kline("US:TSLA", interval="1d", limit=100)
49
+ prices = client.stock.prices("US:AAPL", start_date="2024-01-01")
51
50
 
52
- # Real-time quotes
53
- quotes = client.stock.quote(["US:AAPL", "US:MSFT"])
51
+ # Real-time quote
52
+ quote = client.stock.quote("US:AAPL")
54
53
 
55
54
  # Company info
56
55
  overview = client.stock.overview("US:AAPL")
57
56
  shareholders = client.stock.shareholders("US:AAPL")
58
57
 
59
58
  # Screening and calendar
60
- stocks = client.stock.screener(market="US", min_market_cap=1e10)
61
- earnings = client.stock.earnings_calendar(area="us", start_date="2024-01-01")
59
+ stocks = client.stock.screener(country="US", market_cap_more_than=1e10)
60
+ earnings = client.stock.earnings_calendar(market="us", start_date="2024-01-01", end_date="2024-01-31")
62
61
  ```
63
62
 
64
63
  ### Timeline
@@ -89,6 +88,102 @@ summary = client.docs.summary("doc_id")
89
88
  # List and search documents
90
89
  docs = client.docs.list(symbols=["US:AAPL"], page_size=10)
91
90
  chunks = client.docs.search_chunks("revenue breakdown", num=5)
91
+
92
+ # Upload documents
93
+ result = client.docs.upload([
94
+ {"url": "https://example.com/report.pdf", "name": "Annual Report"}
95
+ ])
96
+ ```
97
+
98
+ ### Quant (Quantitative Analysis)
99
+
100
+ ```python
101
+ # Compute technical indicators
102
+ df = client.quant.compute_indicators(["000001"], "RSI(14)")
103
+ df = client.quant.compute_indicators(["000001"], "MACD()")
104
+
105
+ # Screen stocks by formula
106
+ stocks = client.quant.screen(formula="RSI(14) < 30")
107
+ stocks = client.quant.screen(formula="CROSS(MA(5), MA(20))")
108
+
109
+ # Get OHLCV data
110
+ ohlcv = client.quant.ohlcv("000001", start_date="2024-01-01")
111
+ ohlcv_batch = client.quant.ohlcv_batch(["000001", "600519"])
112
+
113
+ # Backtest strategy
114
+ result = client.quant.backtest(
115
+ start_date="2023-01-01",
116
+ end_date="2024-01-01",
117
+ symbol="000001",
118
+ entry_formula="CROSS(MA(5), MA(20))",
119
+ exit_formula="CROSSDOWN(MA(5), MA(20))"
120
+ )
121
+ print(f"Total Return: {result['total_return_pct']:.2%}")
122
+ ```
123
+
124
+ ### Concepts
125
+
126
+ ```python
127
+ # Get latest concepts
128
+ concepts = client.concepts.latest()
129
+ for c in concepts:
130
+ print(c["concept_name"])
131
+
132
+ # Get today's concept feeds
133
+ feeds = client.concepts.today()
134
+ ```
135
+
136
+ ### Channels
137
+
138
+ ```python
139
+ # Search channels
140
+ result = client.channels.search("Goldman Sachs")
141
+
142
+ # Get followed channels
143
+ followings = client.channels.followings()
144
+
145
+ # Follow/unfollow a channel
146
+ client.channels.follow("channel_id")
147
+ client.channels.unfollow("channel_id")
148
+ ```
149
+
150
+ ### Chat
151
+
152
+ ```python
153
+ # Chat completion based on documents
154
+ response = client.chat.completion(
155
+ "What are Tesla's revenue projections?",
156
+ symbols=["US:TSLA"],
157
+ mode="comprehensive" # concise, comprehensive, deepresearch
158
+ )
159
+ print(response["message"])
160
+ ```
161
+
162
+ ### Agent
163
+
164
+ ```python
165
+ # Create agent conversation
166
+ conv = client.agent.create_conversation(agent_id=11887655289749510)
167
+
168
+ # Chat with agent
169
+ response = client.agent.chat(
170
+ conversation_id=conv["id"],
171
+ message="Analyze NVIDIA's latest earnings"
172
+ )
173
+
174
+ # Get agent-generated file
175
+ file_content = client.agent.get_file("file_id")
176
+ with open("output.xlsx", "wb") as f:
177
+ f.write(file_content)
178
+ ```
179
+
180
+ ### User
181
+
182
+ ```python
183
+ # Get followed companies
184
+ companies = client.user.followed_companies()
185
+ for company in companies:
186
+ print(f"{company['symbol']}: {company['name']}")
92
187
  ```
93
188
 
94
189
  ## Error Handling
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "reportify-sdk"
7
- version = "0.2.9"
7
+ version = "0.3.0"
8
8
  description = "Python SDK for Reportify API - Financial data and document search"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -20,7 +20,7 @@ from reportify_sdk.exceptions import (
20
20
  APIError,
21
21
  )
22
22
 
23
- __version__ = "0.2.9"
23
+ __version__ = "0.3.0"
24
24
  __all__ = [
25
25
  "Reportify",
26
26
  "ReportifyError",
@@ -54,7 +54,7 @@ class ChatModule:
54
54
  categories: Filter by document categories
55
55
  markets: Filter by markets (cn, hk, us)
56
56
  institutions: Filter by institutions
57
- symbols: Filter by stock symbols
57
+ symbols: Stock symbols in market:ticker format (e.g., US:AAPL, HK:00700, SH:600519, SZ:000001)
58
58
  tags: Filter by tags
59
59
  start_date: Start date filter (YYYY-MM-DD)
60
60
  end_date: End date filter (YYYY-MM-DD)
@@ -0,0 +1,262 @@
1
+ """
2
+ Reportify Client
3
+
4
+ Main client class for interacting with the Reportify API.
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ import httpx
10
+
11
+ from reportify_sdk.exceptions import (
12
+ APIError,
13
+ AuthenticationError,
14
+ NotFoundError,
15
+ RateLimitError,
16
+ )
17
+
18
+
19
+ class Reportify:
20
+ """
21
+ Reportify API Client
22
+
23
+ A user-friendly client for accessing financial data, document search,
24
+ and knowledge base through the Reportify API.
25
+
26
+ Args:
27
+ api_key: Your Reportify API key
28
+ base_url: Base URL for the API (default: https://api.reportify.cn)
29
+ timeout: Request timeout in seconds (default: 30)
30
+
31
+ Example:
32
+ >>> from reportify_sdk import Reportify
33
+ >>> client = Reportify(api_key="your-api-key")
34
+ >>> docs = client.search("Tesla earnings", num=10)
35
+ """
36
+
37
+ DEFAULT_BASE_URL = "https://api.reportify.cn"
38
+
39
+ def __init__(
40
+ self,
41
+ api_key: str,
42
+ base_url: str | None = None,
43
+ timeout: float = 30.0,
44
+ ):
45
+ if not api_key:
46
+ raise AuthenticationError("API key is required")
47
+
48
+ self.api_key = api_key
49
+ self.base_url = (base_url or self.DEFAULT_BASE_URL).rstrip("/")
50
+ self.timeout = timeout
51
+
52
+ self._client = httpx.Client(
53
+ base_url=self.base_url,
54
+ headers=self._get_headers(),
55
+ timeout=timeout,
56
+ )
57
+
58
+ # Initialize sub-modules (lazy loading)
59
+ self._stock = None
60
+ self._timeline = None
61
+ self._kb = None
62
+ self._docs = None
63
+ self._tools = None
64
+ self._quant = None
65
+ self._concepts = None
66
+ self._channels = None
67
+ self._chat = None
68
+ self._agent = None
69
+ self._user = None
70
+ self._search = None
71
+
72
+ def _get_headers(self) -> dict[str, str]:
73
+ """Get default headers for API requests"""
74
+ return {
75
+ "Authorization": f"Bearer {self.api_key}",
76
+ "Content-Type": "application/json",
77
+ "User-Agent": "reportify-sdk-python/0.3.0",
78
+ }
79
+
80
+ def _request(
81
+ self,
82
+ method: str,
83
+ path: str,
84
+ params: dict[str, Any] | None = None,
85
+ json: dict[str, Any] | None = None,
86
+ ) -> dict[str, Any]:
87
+ """
88
+ Make an HTTP request to the API
89
+
90
+ Args:
91
+ method: HTTP method (GET, POST, etc.)
92
+ path: API endpoint path
93
+ params: Query parameters
94
+ json: JSON body data
95
+
96
+ Returns:
97
+ Response data as dictionary
98
+
99
+ Raises:
100
+ AuthenticationError: If API key is invalid
101
+ RateLimitError: If rate limit is exceeded
102
+ NotFoundError: If resource is not found
103
+ APIError: For other API errors
104
+ """
105
+ try:
106
+ response = self._client.request(
107
+ method=method,
108
+ url=path,
109
+ params=params,
110
+ json=json,
111
+ )
112
+
113
+ # Handle error responses
114
+ if response.status_code == 401:
115
+ raise AuthenticationError()
116
+ elif response.status_code == 429:
117
+ raise RateLimitError()
118
+ elif response.status_code == 404:
119
+ raise NotFoundError()
120
+ elif response.status_code >= 400:
121
+ error_msg = response.text
122
+ try:
123
+ error_data = response.json()
124
+ error_msg = error_data.get("detail", error_data.get("message", error_msg))
125
+ except Exception:
126
+ pass
127
+ raise APIError(error_msg, status_code=response.status_code)
128
+
129
+ return response.json()
130
+
131
+ except httpx.TimeoutException:
132
+ raise APIError("Request timeout", status_code=408)
133
+ except httpx.RequestError as e:
134
+ raise APIError(f"Request failed: {str(e)}")
135
+
136
+ def _get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
137
+ """Make a GET request"""
138
+ return self._request("GET", path, params=params)
139
+
140
+ def _post(self, path: str, json: dict[str, Any] | None = None) -> dict[str, Any]:
141
+ """Make a POST request"""
142
+ return self._request("POST", path, json=json)
143
+
144
+ def _get_bytes(self, path: str) -> bytes:
145
+ """Make a GET request and return raw bytes (for file downloads)"""
146
+ try:
147
+ response = self._client.get(path)
148
+ response.raise_for_status()
149
+ return response.content
150
+ except httpx.HTTPStatusError as e:
151
+ status_code = e.response.status_code
152
+ if status_code == 401:
153
+ raise AuthenticationError("Invalid API key")
154
+ elif status_code == 404:
155
+ raise NotFoundError(f"Resource not found: {path}")
156
+ elif status_code == 429:
157
+ raise RateLimitError("Rate limit exceeded")
158
+ else:
159
+ raise APIError(f"API error: {status_code}")
160
+
161
+
162
+ # -------------------------------------------------------------------------
163
+ # Sub-modules (lazy loading)
164
+ # -------------------------------------------------------------------------
165
+
166
+ @property
167
+ def search(self):
168
+ """Search module for document search across all categories"""
169
+ if self._search is None:
170
+ from reportify_sdk.search import SearchModule
171
+ self._search = SearchModule(self)
172
+ return self._search
173
+
174
+ @property
175
+ def stock(self):
176
+ """Stock data module for financial statements, prices, etc."""
177
+ if self._stock is None:
178
+ from reportify_sdk.stock import StockModule
179
+ self._stock = StockModule(self)
180
+ return self._stock
181
+
182
+ @property
183
+ def timeline(self):
184
+ """Timeline module for following companies, topics, etc."""
185
+ if self._timeline is None:
186
+ from reportify_sdk.timeline import TimelineModule
187
+ self._timeline = TimelineModule(self)
188
+ return self._timeline
189
+
190
+ @property
191
+ def kb(self):
192
+ """Knowledge base module for searching user uploaded documents"""
193
+ if self._kb is None:
194
+ from reportify_sdk.kb import KBModule
195
+ self._kb = KBModule(self)
196
+ return self._kb
197
+
198
+ @property
199
+ def docs(self):
200
+ """Documents module for accessing document content and metadata"""
201
+ if self._docs is None:
202
+ from reportify_sdk.docs import DocsModule
203
+ self._docs = DocsModule(self)
204
+ return self._docs
205
+
206
+ @property
207
+ def quant(self):
208
+ """Quant module for indicators, factors, quotes, and backtesting"""
209
+ if self._quant is None:
210
+ from reportify_sdk.quant import QuantModule
211
+ self._quant = QuantModule(self)
212
+ return self._quant
213
+
214
+ @property
215
+ def concepts(self):
216
+ """Concepts module for accessing concept data and feeds"""
217
+ if self._concepts is None:
218
+ from reportify_sdk.concepts import ConceptsModule
219
+ self._concepts = ConceptsModule(self)
220
+ return self._concepts
221
+
222
+ @property
223
+ def channels(self):
224
+ """Channels module for searching and following channels"""
225
+ if self._channels is None:
226
+ from reportify_sdk.channels import ChannelsModule
227
+ self._channels = ChannelsModule(self)
228
+ return self._channels
229
+
230
+ @property
231
+ def chat(self):
232
+ """Chat module for document-based Q&A"""
233
+ if self._chat is None:
234
+ from reportify_sdk.chat import ChatModule
235
+ self._chat = ChatModule(self)
236
+ return self._chat
237
+
238
+ @property
239
+ def agent(self):
240
+ """Agent module for AI-powered conversations and workflows"""
241
+ if self._agent is None:
242
+ from reportify_sdk.agent import AgentModule
243
+ self._agent = AgentModule(self)
244
+ return self._agent
245
+
246
+ @property
247
+ def user(self):
248
+ """User module for user-related tools and data"""
249
+ if self._user is None:
250
+ from reportify_sdk.user import UserModule
251
+ self._user = UserModule(self)
252
+ return self._user
253
+
254
+ def close(self):
255
+ """Close the HTTP client"""
256
+ self._client.close()
257
+
258
+ def __enter__(self):
259
+ return self
260
+
261
+ def __exit__(self, exc_type, exc_val, exc_tb):
262
+ self.close()
@@ -101,7 +101,7 @@ class DocsModule:
101
101
  List documents with filters
102
102
 
103
103
  Args:
104
- symbols: Filter by stock symbols
104
+ symbols: Stock symbols in market:ticker format (e.g., US:AAPL, HK:00700, SH:600519, SZ:000001)
105
105
  categories: Filter by document categories (financials, transcripts, reports, news, files, filings, socials)
106
106
  markets: Filter by markets (cn, hk, us)
107
107
  institutions: Filter by institutions
@@ -176,7 +176,7 @@ class DocsModule:
176
176
 
177
177
  Args:
178
178
  query: Search query string
179
- symbols: Filter by stock symbols
179
+ symbols: Stock symbols in market:ticker format (e.g., US:AAPL, HK:00700, SH:600519, SZ:000001)
180
180
  categories: Filter by document categories (financials, transcripts, reports, news, filings, socials)
181
181
  markets: Filter by markets (cn, hk, us)
182
182
  institutions: Filter by institutions
@@ -251,7 +251,7 @@ class DocsModule:
251
251
  Query documents by stock symbols
252
252
 
253
253
  Args:
254
- symbols: Stock symbols to filter by (required)
254
+ symbols: Stock symbols in market:ticker format (required, e.g., US:AAPL, HK:00700, SH:600519, SZ:000001)
255
255
  categories: Filter by document categories
256
256
  markets: Filter by markets (cn, hk, us)
257
257
  start_date: Start date filter (YYYY-MM-DD)
@@ -345,7 +345,7 @@ class DocsModule:
345
345
 
346
346
  Args:
347
347
  query: Search query string
348
- symbols: Filter by stock symbols
348
+ symbols: Stock symbols in market:ticker format (e.g., US:AAPL, HK:00700, SH:600519, SZ:000001)
349
349
  categories: Filter by document categories
350
350
  markets: Filter by markets (cn, hk, us)
351
351
  institutions: Filter by institutions