unique-quartr 0.1.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.
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2025-08-18
9
+ - Initial release of `unique_quartr`.
@@ -0,0 +1 @@
1
+ `unique_toolkit` is covered by the [`Unique License v1`](https://github.com/Unique-AG/license/releases/tag/unique-license.v1), unless the/a header or a nested LICENSE specifies another license.
@@ -0,0 +1,480 @@
1
+ Metadata-Version: 2.3
2
+ Name: unique_quartr
3
+ Version: 0.1.0
4
+ Summary:
5
+ License: Proprietary
6
+ Author: Rami Azouz
7
+ Author-email: rami.ext@unique.ch
8
+ Requires-Python: >=3.12,<4.0
9
+ Classifier: License :: Other/Proprietary License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: pydantic (>=2.12.4,<3.0.0)
14
+ Requires-Dist: unique-toolkit (>=1.24.1,<2.0.0)
15
+ Description-Content-Type: text/markdown
16
+
17
+ # Unique Quartr Connector
18
+
19
+ A Python connector library for the [Quartr API](https://quartr.com), providing easy access to company events, documents, and financial data.
20
+
21
+ ## Features
22
+
23
+ - 🔍 Fetch company earnings calls and events
24
+ - 📄 Retrieve event documents (transcripts, reports, slides, etc.)
25
+ - 🎯 Type-safe API with Pydantic models
26
+ - 🔄 Automatic pagination handling
27
+ - 📊 Support for multiple document and event types
28
+ - 🔐 Secure API key authentication
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ poetry add unique_quartr
34
+ ```
35
+
36
+ Or using pip:
37
+
38
+ ```bash
39
+ pip install unique_quartr
40
+ ```
41
+
42
+ ## Configuration
43
+
44
+ ### Environment Variables
45
+
46
+ Create a `.env` file in your project root with your Quartr API credentials:
47
+
48
+ ```env
49
+ QUARTR_API_CREDS='{"api_key": "your_api_key_here", "valid_to": "2025-12-31"}'
50
+ QUARTR_API_ACTIVATED_COMPANIES='["company_id_1", "company_id_2"]'
51
+ ```
52
+
53
+ ### Test Environment
54
+
55
+ For testing, create `tests/test.env`:
56
+
57
+ ```env
58
+ QUARTR_API_CREDS='{"api_key": "test_api_key", "valid_to": "2025-12-31"}'
59
+ QUARTR_API_ACTIVATED_COMPANIES='["test_company"]'
60
+ ```
61
+
62
+ ## Quick Start
63
+
64
+ ### Basic Usage
65
+
66
+ ```python
67
+ from unique_quartr.service import QuartrService
68
+ from unique_quartr.constants.event_types import EventType
69
+ from unique_quartr.constants.document_types import DocumentType
70
+ from unique_toolkit._common.endpoint_requestor import RequestorType
71
+
72
+ # Initialize the service
73
+ service = QuartrService(
74
+ company_id="your_company_id",
75
+ requestor_type=RequestorType.REQUESTS,
76
+ )
77
+
78
+ # Define the event types you want to fetch
79
+ event_types = [EventType.EARNINGS_CALL]
80
+ event_ids = service.get_event_subtype_ids_from_event_types(event_types)
81
+
82
+ # Fetch company events
83
+ events = service.fetch_company_events(
84
+ ticker="AAPL",
85
+ exchange="NasdaqGS",
86
+ country="US",
87
+ event_ids=event_ids,
88
+ start_date="2024-01-01",
89
+ end_date="2024-12-31",
90
+ )
91
+
92
+ print(f"Found {len(events)} events")
93
+ for event in events:
94
+ print(f"Event: {event['title']} - {event['date']}")
95
+ ```
96
+
97
+ ### Fetching Documents
98
+
99
+ ```python
100
+ # Get event IDs from the events you fetched
101
+ event_ids = [event["id"] for event in events]
102
+
103
+ # Define document types you want
104
+ document_types = [DocumentType.TRANSCRIPT, DocumentType.SLIDES]
105
+ document_ids = service.get_document_ids_from_document_types(document_types)
106
+
107
+ # Fetch documents for these events
108
+ documents = service.fetch_event_documents(
109
+ event_ids=event_ids,
110
+ document_ids=document_ids,
111
+ )
112
+
113
+ print(f"Found {len(documents)} documents")
114
+ for doc in documents:
115
+ print(f"Document: {doc['type_id']} - {doc['file_url']}")
116
+ ```
117
+
118
+ ## Event Types
119
+
120
+ The library supports the following event types:
121
+
122
+ - **Earnings Call**: Q1, Q2, Q3, Q4, H1, H2
123
+ - **Analyst Day**
124
+ - **Annual General Meeting**: AGM, Scheme Meeting
125
+ - **Business Combination**
126
+ - **C-level Sitdown**: C-level Sitdown, CEO Sitdown
127
+ - **Capital Markets Day**
128
+ - **Capital Raise**
129
+ - **Conference**
130
+ - **Extraordinary General Meeting**
131
+ - **FDA Announcement**
132
+ - **Fireside Chat**
133
+ - **Investor Day**
134
+ - **M&A Announcement**
135
+ - **Outlook / Guidance Update**
136
+ - **Partnerships / Collaborations**: Partnership, Collaboration
137
+ - **Product / Service Launch**: Product Launch, Service Launch
138
+ - **Slides**: Investor Presentation, Corporate Presentation, Company Presentation
139
+ - **Trading Update**
140
+ - **Update / Briefing**: Status Update, Investor Update, ESG Update, Study Update, Study Result, KOL Event
141
+
142
+ ### Example: Getting Earnings Call Event IDs
143
+
144
+ ```python
145
+ from unique_quartr.constants.event_types import EventType
146
+
147
+ event_types = [EventType.EARNINGS_CALL]
148
+ event_ids = QuartrService.get_event_subtype_ids_from_event_types(event_types)
149
+ # Returns: [26, 27, 28, 29, 35, 36] (Q1, Q2, Q3, Q4, H1, H2)
150
+ ```
151
+
152
+ ## Document Types
153
+
154
+ The library supports various document types:
155
+
156
+ - **Slides** 📊
157
+ - **Report** 📄
158
+ - **Quarterly Report (10-Q)** 📑
159
+ - **Earnings Release (8-K)** 📢
160
+ - **Annual Report (10-K)** 📘
161
+ - **Annual Report (20-F)** 📙
162
+ - **Annual Report (40-F)** 📕
163
+ - **Earnings Release (6-K)** 📣
164
+ - **Transcript** 🗒️
165
+ - **Interim Report** 📜
166
+ - **Press Release** 🗞️
167
+ - **Earnings Release** 💰
168
+ - **In-house Transcript** 🎤
169
+
170
+ ### Example: Getting Document Type Information
171
+
172
+ ```python
173
+ from unique_quartr.constants.document_types import DocumentType
174
+
175
+ doc_type = DocumentType.QUARTERLY_REPORT_10Q
176
+
177
+ print(doc_type.name) # "Quarterly report"
178
+ print(doc_type.form) # "10-Q"
179
+ print(doc_type.emoji) # "📑"
180
+ print(doc_type.get_file_prefix()) # "Quarterly report (10-Q)"
181
+ ```
182
+
183
+ ## Advanced Usage
184
+
185
+ ### Custom Pagination
186
+
187
+ Control pagination parameters for large datasets:
188
+
189
+ ```python
190
+ events = service.fetch_company_events(
191
+ ticker="AAPL",
192
+ exchange="NasdaqGS",
193
+ country="US",
194
+ event_ids=event_ids,
195
+ limit=100, # Items per page (max 500)
196
+ max_iteration=10, # Maximum number of pages
197
+ )
198
+ ```
199
+
200
+ ### Filtering by Date Range
201
+
202
+ ```python
203
+ events = service.fetch_company_events(
204
+ ticker="AAPL",
205
+ exchange="NasdaqGS",
206
+ country="US",
207
+ event_ids=event_ids,
208
+ start_date="2024-01-01T00:00:00Z", # ISO format
209
+ end_date="2024-03-31T23:59:59Z",
210
+ )
211
+ ```
212
+
213
+ ### Fetching Multiple Event Types
214
+
215
+ ```python
216
+ from unique_quartr.constants.event_types import EventType
217
+
218
+ # Combine multiple event types
219
+ event_types = [
220
+ EventType.EARNINGS_CALL,
221
+ EventType.ANALYST_DAY,
222
+ EventType.INVESTOR_DAY,
223
+ ]
224
+
225
+ event_ids = QuartrService.get_event_subtype_ids_from_event_types(event_types)
226
+
227
+ events = service.fetch_company_events(
228
+ ticker="AAPL",
229
+ exchange="NasdaqGS",
230
+ country="US",
231
+ event_ids=event_ids,
232
+ )
233
+ ```
234
+
235
+ ## API Reference
236
+
237
+ ### QuartrService
238
+
239
+ ```python
240
+ class QuartrService:
241
+ def __init__(
242
+ self,
243
+ *,
244
+ company_id: str,
245
+ requestor_type: RequestorType,
246
+ ):
247
+ """
248
+ Initialize the Quartr service.
249
+
250
+ Args:
251
+ company_id: Company identifier for API access
252
+ requestor_type: Type of requestor (SYNC or ASYNC)
253
+ """
254
+ ```
255
+
256
+ #### Methods
257
+
258
+ ##### fetch_company_events
259
+
260
+ ```python
261
+ def fetch_company_events(
262
+ self,
263
+ ticker: str,
264
+ exchange: str,
265
+ country: str,
266
+ event_ids: list[int],
267
+ start_date: str | None = None,
268
+ end_date: str | None = None,
269
+ limit: int = 500,
270
+ max_iteration: int = 20,
271
+ ) -> list[EventDto]:
272
+ """
273
+ Retrieve events for a given company.
274
+
275
+ Args:
276
+ ticker: Company ticker symbol (e.g., 'AAPL', 'AMZN')
277
+ exchange: Exchange code (e.g., 'NasdaqGS', 'NYSE')
278
+ country: Country code (e.g., 'US', 'CA')
279
+ event_ids: List of event type IDs to filter
280
+ start_date: Optional start date in ISO format
281
+ end_date: Optional end date in ISO format
282
+ limit: Items per request (max 500)
283
+ max_iteration: Maximum number of pagination iterations
284
+
285
+ Returns:
286
+ List of event dictionaries
287
+ """
288
+ ```
289
+
290
+ ##### fetch_event_documents
291
+
292
+ ```python
293
+ def fetch_event_documents(
294
+ self,
295
+ event_ids: list[int],
296
+ document_ids: list[int],
297
+ limit: int = 500,
298
+ max_iteration: int = 20,
299
+ ) -> list[DocumentDto]:
300
+ """
301
+ Retrieve documents for a list of events.
302
+
303
+ Args:
304
+ event_ids: List of event IDs
305
+ document_ids: List of document type IDs to filter
306
+ limit: Items per request (max 500)
307
+ max_iteration: Maximum number of pagination iterations
308
+
309
+ Returns:
310
+ List of document dictionaries
311
+ """
312
+ ```
313
+
314
+ ##### Static Methods
315
+
316
+ ```python
317
+ @staticmethod
318
+ def get_event_subtype_ids_from_event_types(
319
+ event_types: list[EventType],
320
+ ) -> list[int]:
321
+ """
322
+ Convert EventType enums to Quartr API event subtype IDs.
323
+
324
+ Args:
325
+ event_types: List of EventType enums
326
+
327
+ Returns:
328
+ List of event subtype IDs
329
+ """
330
+
331
+ @staticmethod
332
+ def get_document_ids_from_document_types(
333
+ document_types: list[DocumentType],
334
+ ) -> list[int]:
335
+ """
336
+ Convert DocumentType enums to Quartr API document type IDs.
337
+
338
+ Args:
339
+ document_types: List of DocumentType enums
340
+
341
+ Returns:
342
+ List of document type IDs
343
+ """
344
+ ```
345
+
346
+ ## Response Models
347
+
348
+ ### EventDto
349
+
350
+ ```python
351
+ {
352
+ "company_id": float,
353
+ "date": datetime,
354
+ "id": float,
355
+ "title": str,
356
+ "type_id": float,
357
+ "fiscal_year": float | None,
358
+ "fiscal_period": str | None,
359
+ "backlink_url": str,
360
+ "updated_at": datetime,
361
+ "created_at": datetime,
362
+ }
363
+ ```
364
+
365
+ ### DocumentDto
366
+
367
+ ```python
368
+ {
369
+ "company_id": float | None,
370
+ "event_id": float | None,
371
+ "file_url": str,
372
+ "id": float,
373
+ "type_id": float,
374
+ "updated_at": datetime,
375
+ "created_at": datetime,
376
+ }
377
+ ```
378
+
379
+ ## Testing
380
+
381
+ Run the test suite:
382
+
383
+ ```bash
384
+ poetry run pytest
385
+ ```
386
+
387
+ Run with coverage:
388
+
389
+ ```bash
390
+ poetry run pytest --cov=unique_quartr --cov-report=html
391
+ ```
392
+
393
+ Run specific test files:
394
+
395
+ ```bash
396
+ poetry run pytest tests/test_service.py
397
+ poetry run pytest tests/test_constants.py
398
+ ```
399
+
400
+ ## Error Handling
401
+
402
+ The library will raise exceptions in the following cases:
403
+
404
+ - **Missing API Credentials**: `ValueError` when `QUARTR_API_CREDS` is not set
405
+ - **Company Not Activated**: `ValueError` when the company_id is not in `QUARTR_API_ACTIVATED_COMPANIES`
406
+ - **API Errors**: Various HTTP errors from the Quartr API
407
+
408
+ ### Example Error Handling
409
+
410
+ ```python
411
+ from unique_quartr.service import QuartrService
412
+
413
+ try:
414
+ service = QuartrService(
415
+ company_id="invalid_company",
416
+ requestor_type=RequestorType.SYNC,
417
+ )
418
+ except ValueError as e:
419
+ print(f"Configuration error: {e}")
420
+ ```
421
+
422
+ ## Development
423
+
424
+ ### Setup Development Environment
425
+
426
+ ```bash
427
+ # Clone the repository
428
+ git clone <repository_url>
429
+ cd unique_quartr
430
+
431
+ # Install dependencies
432
+ poetry install
433
+
434
+ # Run linting
435
+ poetry run ruff check .
436
+
437
+ # Run formatting
438
+ poetry run ruff format .
439
+ ```
440
+
441
+ ### Project Structure
442
+
443
+ ```
444
+ unique_quartr/
445
+ ├── constants/
446
+ │ ├── document_types.py # Document type enums and mappings
447
+ │ └── event_types.py # Event type enums and mappings
448
+ ├── endpoints/
449
+ │ ├── api.py # API endpoint definitions
450
+ │ └── schemas.py # Pydantic models for API requests/responses
451
+ ├── helpers.py # Helper utilities
452
+ ├── service.py # Main service class
453
+ └── settings.py # Configuration and settings
454
+ ```
455
+
456
+ ## License
457
+
458
+ Proprietary
459
+
460
+ ## Authors
461
+
462
+ - Rami Azouz <rami.ext@unique.ch>
463
+
464
+ ## Support
465
+
466
+ For issues and questions, please contact the maintainers or refer to the [Quartr API documentation](https://quartr.com/api).
467
+
468
+ ## Changelog
469
+
470
+ See [CHANGELOG.md](CHANGELOG.md) for version history and updates.
471
+
472
+ # Changelog
473
+
474
+ All notable changes to this project will be documented in this file.
475
+
476
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
477
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
478
+
479
+ ## [0.1.0] - 2025-08-18
480
+ - Initial release of `unique_quartr`.