Tepilora 0.3.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.
Files changed (47) hide show
  1. tepilora-0.3.1/LICENSE +21 -0
  2. tepilora-0.3.1/MANIFEST.in +13 -0
  3. tepilora-0.3.1/PKG-INFO +300 -0
  4. tepilora-0.3.1/README.md +265 -0
  5. tepilora-0.3.1/Tepilora/__init__.py +45 -0
  6. tepilora-0.3.1/Tepilora/_default_client.py +60 -0
  7. tepilora-0.3.1/Tepilora/_schema.py +7745 -0
  8. tepilora-0.3.1/Tepilora/analytics.py +503 -0
  9. tepilora-0.3.1/Tepilora/analytics.pyi +3770 -0
  10. tepilora-0.3.1/Tepilora/arrow.py +42 -0
  11. tepilora-0.3.1/Tepilora/capabilities.py +321 -0
  12. tepilora-0.3.1/Tepilora/client.py +630 -0
  13. tepilora-0.3.1/Tepilora/endpoints/__init__.py +82 -0
  14. tepilora-0.3.1/Tepilora/endpoints/_base.py +58 -0
  15. tepilora-0.3.1/Tepilora/endpoints/alerts.py +372 -0
  16. tepilora-0.3.1/Tepilora/endpoints/alternatives.py +470 -0
  17. tepilora-0.3.1/Tepilora/endpoints/billing.py +540 -0
  18. tepilora-0.3.1/Tepilora/endpoints/bonds.py +486 -0
  19. tepilora-0.3.1/Tepilora/endpoints/clients.py +360 -0
  20. tepilora-0.3.1/Tepilora/endpoints/data.py +64 -0
  21. tepilora-0.3.1/Tepilora/endpoints/documents.py +170 -0
  22. tepilora-0.3.1/Tepilora/endpoints/esg.py +238 -0
  23. tepilora-0.3.1/Tepilora/endpoints/exports.py +112 -0
  24. tepilora-0.3.1/Tepilora/endpoints/factors.py +482 -0
  25. tepilora-0.3.1/Tepilora/endpoints/fh.py +318 -0
  26. tepilora-0.3.1/Tepilora/endpoints/macro.py +330 -0
  27. tepilora-0.3.1/Tepilora/endpoints/news.py +372 -0
  28. tepilora-0.3.1/Tepilora/endpoints/options.py +396 -0
  29. tepilora-0.3.1/Tepilora/endpoints/portfolio.py +968 -0
  30. tepilora-0.3.1/Tepilora/endpoints/profiling.py +376 -0
  31. tepilora-0.3.1/Tepilora/endpoints/publications.py +250 -0
  32. tepilora-0.3.1/Tepilora/endpoints/queries.py +498 -0
  33. tepilora-0.3.1/Tepilora/endpoints/search.py +64 -0
  34. tepilora-0.3.1/Tepilora/endpoints/securities.py +592 -0
  35. tepilora-0.3.1/Tepilora/endpoints/stocks.py +446 -0
  36. tepilora-0.3.1/Tepilora/endpoints/workflows.py +126 -0
  37. tepilora-0.3.1/Tepilora/errors.py +20 -0
  38. tepilora-0.3.1/Tepilora/models.py +80 -0
  39. tepilora-0.3.1/Tepilora/py.typed +0 -0
  40. tepilora-0.3.1/Tepilora/version.py +1 -0
  41. tepilora-0.3.1/Tepilora.egg-info/PKG-INFO +300 -0
  42. tepilora-0.3.1/Tepilora.egg-info/SOURCES.txt +45 -0
  43. tepilora-0.3.1/Tepilora.egg-info/dependency_links.txt +1 -0
  44. tepilora-0.3.1/Tepilora.egg-info/requires.txt +12 -0
  45. tepilora-0.3.1/Tepilora.egg-info/top_level.txt +1 -0
  46. tepilora-0.3.1/pyproject.toml +59 -0
  47. tepilora-0.3.1/setup.cfg +4 -0
tepilora-0.3.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Tepilora
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ # Include package files
2
+ recursive-include Tepilora *.py *.pyi py.typed
3
+
4
+ # Exclude dev/internal files from distribution
5
+ exclude CLAUDE.md
6
+ exclude RELEASING.md
7
+ prune scripts
8
+ prune schema
9
+ prune tests
10
+ prune examples
11
+ global-exclude __pycache__
12
+ global-exclude *.py[cod]
13
+ global-exclude .git*
@@ -0,0 +1,300 @@
1
+ Metadata-Version: 2.2
2
+ Name: Tepilora
3
+ Version: 0.3.1
4
+ Summary: Python SDK for Tepilora API v3
5
+ Author-email: Tepilora <info@tepiloradata.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://tepiloradata.com
8
+ Project-URL: Repository, https://github.com/Admintepilora/tepilora-python
9
+ Project-URL: Issues, https://github.com/Admintepilora/tepilora-python/issues
10
+ Keywords: tepilora,finance,api,sdk,portfolio,analytics
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Financial and Insurance Industry
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Office/Business :: Financial
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: httpx>=0.26.0
27
+ Provides-Extra: arrow
28
+ Requires-Dist: pyarrow>=12; extra == "arrow"
29
+ Provides-Extra: polars
30
+ Requires-Dist: polars>=0.20; extra == "polars"
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7; extra == "dev"
33
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
34
+ Requires-Dist: httpx>=0.26.0; extra == "dev"
35
+
36
+ # Tepilora SDK (Python)
37
+
38
+ SDK Python (sync + async) per Tepilora API v3.
39
+
40
+ **218 operazioni** in **23 namespace** auto-generati dal registry.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install Tepilora
46
+ ```
47
+
48
+ Optional extras:
49
+ ```bash
50
+ pip install 'Tepilora[arrow]' # PyArrow per formati binari
51
+ pip install 'Tepilora[polars]' # Polars DataFrame support
52
+ ```
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ import Tepilora as T
58
+
59
+ client = T.TepiloraClient(api_key="YOUR_KEY")
60
+
61
+ # Typed endpoints (IDE autocomplete)
62
+ securities = client.securities.search(query="MSCI ETF", limit=10)
63
+ print(securities["totalCount"])
64
+
65
+ # Raw call
66
+ resp = client.call("securities.search", params={"query": "MSCI", "limit": 5})
67
+ print(resp.data)
68
+ ```
69
+
70
+ ## Async
71
+
72
+ ```python
73
+ import asyncio
74
+ import Tepilora as T
75
+
76
+ async def main():
77
+ async with T.AsyncTepiloraClient(api_key="YOUR_KEY") as client:
78
+ data = await client.securities.search(query="MSCI", limit=10)
79
+ print(data)
80
+
81
+ asyncio.run(main())
82
+ ```
83
+
84
+ ## Namespaces
85
+
86
+ | Namespace | Operazioni | Descrizione |
87
+ |-----------|------------|-------------|
88
+ | `securities` | 12 | Search, filter, history, facets, MiFID, fees |
89
+ | `news` | 7 | Search, latest, trending, details |
90
+ | `publications` | 5 | Research reports and publications |
91
+ | `portfolio` | 19 | CRUD, returns, attribution, optimization |
92
+ | `analytics` | 68 | Rolling metrics, ratios, risk, factors |
93
+ | `alerts` | 9 | Alert rules CRUD, evaluate, history |
94
+ | `macro` | 6 | Economic indicators, calendar |
95
+ | `stocks` | 9 | Technicals, screening, peers, signals |
96
+ | `bonds` | 7 | Analyze, screen, ladder, curve, spread |
97
+ | `options` | 6 | Pricing, Greeks, IV, strategies |
98
+ | `esg` | 5 | ESG scores, screening, comparison |
99
+ | `factors` | 3 | Fama-French, momentum, factor loading |
100
+ | `fh` | 7 | Fundamentals history, financials |
101
+ | `clients` | 8 | B2B client management |
102
+ | `profiling` | 10 | MiFID questionnaires, suitability |
103
+ | `billing` | 10 | Fee calculations, schedules, records |
104
+ | `documents` | 4 | Document parsing, classification |
105
+ | `alternatives` | 9 | Alternative investments |
106
+ | `queries` | 8 | Saved queries CRUD, execute |
107
+ | `search` | 1 | Global search |
108
+ | `data` | 1 | Raw data access |
109
+ | `exports` | 2 | Data export to file formats |
110
+
111
+ ## Esempi per Namespace
112
+
113
+ ### Securities
114
+
115
+ ```python
116
+ # Search
117
+ results = client.securities.search(query="MSCI World", limit=20)
118
+
119
+ # Get details
120
+ details = client.securities.description(identifier="IE00B4L5Y983EURXMIL")
121
+
122
+ # Price history
123
+ history = client.securities.history(
124
+ identifiers=["IE00B4L5Y983EURXMIL", "FR0010655712EURXPAR"],
125
+ start_date="2024-01-01",
126
+ limit=1000
127
+ )
128
+
129
+ # Filter by criteria
130
+ filtered = client.securities.filter(filters={"Currency": "EUR", "TepiloraType": "ETF"})
131
+
132
+ # Get facets for building filters
133
+ facets = client.securities.facets(fields=["Currency", "TepiloraType", "Country"])
134
+ ```
135
+
136
+ ### Portfolio
137
+
138
+ ```python
139
+ # Create portfolio
140
+ portfolio = client.portfolio.create(
141
+ name="My Portfolio",
142
+ input_type="fixed_weights",
143
+ input_data={"IE00B4L5Y983EURXMIL": 0.6, "FR0010655712EURXPAR": 0.4}
144
+ )
145
+
146
+ # Get returns
147
+ returns = client.portfolio.returns(
148
+ id=portfolio["id"],
149
+ start_date="2024-01-01",
150
+ return_method="twr"
151
+ )
152
+
153
+ # Performance attribution
154
+ attribution = client.portfolio.attribution(id=portfolio["id"])
155
+
156
+ # Optimize
157
+ optimized = client.portfolio.optimize(
158
+ id=portfolio["id"],
159
+ objective="max_sharpe",
160
+ constraints={"max_weight": 0.3}
161
+ )
162
+ ```
163
+
164
+ ### Analytics
165
+
166
+ ```python
167
+ # List available functions
168
+ functions = client.analytics.list()
169
+
170
+ # Get function help
171
+ help_info = client.analytics.help("rolling_volatility")
172
+
173
+ # Calculate rolling volatility
174
+ vol = client.analytics.rolling_volatility(
175
+ identifiers="IE00B4L5Y983EURXMIL",
176
+ period=252,
177
+ start_date="2023-01-01"
178
+ )
179
+
180
+ # Rolling Sharpe ratio
181
+ sharpe = client.analytics.rolling_sharpe(
182
+ identifiers="IE00B4L5Y983EURXMIL",
183
+ period=252,
184
+ rf=0.02
185
+ )
186
+
187
+ # Factor regression
188
+ factors = client.analytics.factor_regression(
189
+ identifiers="IE00B4L5Y983EURXMIL",
190
+ model="FF5"
191
+ )
192
+ ```
193
+
194
+ ### News & Publications
195
+
196
+ ```python
197
+ # Search news
198
+ news = client.news.search(query="bitcoin", limit=20)
199
+
200
+ # Latest news
201
+ latest = client.news.latest(limit=10)
202
+
203
+ # Trending topics
204
+ trending = client.news.trending(limit=50, finance_only=True)
205
+
206
+ # Search publications
207
+ pubs = client.publications.search(query="market outlook", limit=10)
208
+ ```
209
+
210
+ ### Alerts
211
+
212
+ ```python
213
+ # Create alert
214
+ alert = client.alerts.create(
215
+ name="Price Alert",
216
+ condition={"type": "price_change", "threshold": 5.0},
217
+ action={"type": "webhook", "url": "https://..."}
218
+ )
219
+
220
+ # List alerts
221
+ alerts = client.alerts.list(enabled=True)
222
+
223
+ # Evaluate manually
224
+ result = client.alerts.evaluate(rule_id=alert["id"])
225
+ ```
226
+
227
+ ### Bonds
228
+
229
+ ```python
230
+ # Analyze bond
231
+ analysis = client.bonds.analyze(
232
+ identifier="XS1234567890",
233
+ price=98.5,
234
+ settlement_date="2024-02-01"
235
+ )
236
+
237
+ # Screen bonds
238
+ bonds = client.bonds.screen(
239
+ criteria={"min_yield": 4.0, "max_duration": 5.0},
240
+ limit=50
241
+ )
242
+
243
+ # Get yield curve
244
+ curve = client.bonds.curve(currency="EUR", date="2024-01-15")
245
+ ```
246
+
247
+ ## Arrow/Binary Formats
248
+
249
+ ```python
250
+ from Tepilora.arrow import read_ipc_stream
251
+
252
+ # Request Arrow format
253
+ resp = client.call_arrow_ipc_stream("securities.search", params={"query": "ETF", "limit": 1000})
254
+ table = read_ipc_stream(resp.content)
255
+ print(table.to_pandas())
256
+ ```
257
+
258
+ ## Module-Level API
259
+
260
+ ```python
261
+ import Tepilora as T
262
+
263
+ # Configure globally
264
+ T.configure(api_key="YOUR_KEY")
265
+
266
+ # Use without client instance
267
+ T.analytics.rolling_volatility(identifiers="IE00B4L5Y983EURXMIL")
268
+ ```
269
+
270
+ Or via environment variables:
271
+ ```bash
272
+ export TEPILORA_API_KEY=your_key
273
+ export TEPILORA_BASE_URL=https://tepiloradata.com
274
+ ```
275
+
276
+ ## Error Handling
277
+
278
+ ```python
279
+ from Tepilora.errors import TepiloraAPIError
280
+
281
+ try:
282
+ data = client.securities.search(query="invalid")
283
+ except TepiloraAPIError as e:
284
+ print(f"Error: {e.message}")
285
+ print(f"Code: {e.code}")
286
+ ```
287
+
288
+ ## API Endpoints
289
+
290
+ - `POST /T-Api/v3` - Unified action router (all operations)
291
+ - `GET /T-Api/v3/health` - Health check
292
+ - `GET /T-Api/v3/pricing` - Pricing info
293
+ - `GET /T-Api/v3/logs/status` - Logs status
294
+
295
+ ## Version
296
+
297
+ ```python
298
+ import Tepilora
299
+ print(Tepilora.__version__) # 0.3.0
300
+ ```
@@ -0,0 +1,265 @@
1
+ # Tepilora SDK (Python)
2
+
3
+ SDK Python (sync + async) per Tepilora API v3.
4
+
5
+ **218 operazioni** in **23 namespace** auto-generati dal registry.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install Tepilora
11
+ ```
12
+
13
+ Optional extras:
14
+ ```bash
15
+ pip install 'Tepilora[arrow]' # PyArrow per formati binari
16
+ pip install 'Tepilora[polars]' # Polars DataFrame support
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```python
22
+ import Tepilora as T
23
+
24
+ client = T.TepiloraClient(api_key="YOUR_KEY")
25
+
26
+ # Typed endpoints (IDE autocomplete)
27
+ securities = client.securities.search(query="MSCI ETF", limit=10)
28
+ print(securities["totalCount"])
29
+
30
+ # Raw call
31
+ resp = client.call("securities.search", params={"query": "MSCI", "limit": 5})
32
+ print(resp.data)
33
+ ```
34
+
35
+ ## Async
36
+
37
+ ```python
38
+ import asyncio
39
+ import Tepilora as T
40
+
41
+ async def main():
42
+ async with T.AsyncTepiloraClient(api_key="YOUR_KEY") as client:
43
+ data = await client.securities.search(query="MSCI", limit=10)
44
+ print(data)
45
+
46
+ asyncio.run(main())
47
+ ```
48
+
49
+ ## Namespaces
50
+
51
+ | Namespace | Operazioni | Descrizione |
52
+ |-----------|------------|-------------|
53
+ | `securities` | 12 | Search, filter, history, facets, MiFID, fees |
54
+ | `news` | 7 | Search, latest, trending, details |
55
+ | `publications` | 5 | Research reports and publications |
56
+ | `portfolio` | 19 | CRUD, returns, attribution, optimization |
57
+ | `analytics` | 68 | Rolling metrics, ratios, risk, factors |
58
+ | `alerts` | 9 | Alert rules CRUD, evaluate, history |
59
+ | `macro` | 6 | Economic indicators, calendar |
60
+ | `stocks` | 9 | Technicals, screening, peers, signals |
61
+ | `bonds` | 7 | Analyze, screen, ladder, curve, spread |
62
+ | `options` | 6 | Pricing, Greeks, IV, strategies |
63
+ | `esg` | 5 | ESG scores, screening, comparison |
64
+ | `factors` | 3 | Fama-French, momentum, factor loading |
65
+ | `fh` | 7 | Fundamentals history, financials |
66
+ | `clients` | 8 | B2B client management |
67
+ | `profiling` | 10 | MiFID questionnaires, suitability |
68
+ | `billing` | 10 | Fee calculations, schedules, records |
69
+ | `documents` | 4 | Document parsing, classification |
70
+ | `alternatives` | 9 | Alternative investments |
71
+ | `queries` | 8 | Saved queries CRUD, execute |
72
+ | `search` | 1 | Global search |
73
+ | `data` | 1 | Raw data access |
74
+ | `exports` | 2 | Data export to file formats |
75
+
76
+ ## Esempi per Namespace
77
+
78
+ ### Securities
79
+
80
+ ```python
81
+ # Search
82
+ results = client.securities.search(query="MSCI World", limit=20)
83
+
84
+ # Get details
85
+ details = client.securities.description(identifier="IE00B4L5Y983EURXMIL")
86
+
87
+ # Price history
88
+ history = client.securities.history(
89
+ identifiers=["IE00B4L5Y983EURXMIL", "FR0010655712EURXPAR"],
90
+ start_date="2024-01-01",
91
+ limit=1000
92
+ )
93
+
94
+ # Filter by criteria
95
+ filtered = client.securities.filter(filters={"Currency": "EUR", "TepiloraType": "ETF"})
96
+
97
+ # Get facets for building filters
98
+ facets = client.securities.facets(fields=["Currency", "TepiloraType", "Country"])
99
+ ```
100
+
101
+ ### Portfolio
102
+
103
+ ```python
104
+ # Create portfolio
105
+ portfolio = client.portfolio.create(
106
+ name="My Portfolio",
107
+ input_type="fixed_weights",
108
+ input_data={"IE00B4L5Y983EURXMIL": 0.6, "FR0010655712EURXPAR": 0.4}
109
+ )
110
+
111
+ # Get returns
112
+ returns = client.portfolio.returns(
113
+ id=portfolio["id"],
114
+ start_date="2024-01-01",
115
+ return_method="twr"
116
+ )
117
+
118
+ # Performance attribution
119
+ attribution = client.portfolio.attribution(id=portfolio["id"])
120
+
121
+ # Optimize
122
+ optimized = client.portfolio.optimize(
123
+ id=portfolio["id"],
124
+ objective="max_sharpe",
125
+ constraints={"max_weight": 0.3}
126
+ )
127
+ ```
128
+
129
+ ### Analytics
130
+
131
+ ```python
132
+ # List available functions
133
+ functions = client.analytics.list()
134
+
135
+ # Get function help
136
+ help_info = client.analytics.help("rolling_volatility")
137
+
138
+ # Calculate rolling volatility
139
+ vol = client.analytics.rolling_volatility(
140
+ identifiers="IE00B4L5Y983EURXMIL",
141
+ period=252,
142
+ start_date="2023-01-01"
143
+ )
144
+
145
+ # Rolling Sharpe ratio
146
+ sharpe = client.analytics.rolling_sharpe(
147
+ identifiers="IE00B4L5Y983EURXMIL",
148
+ period=252,
149
+ rf=0.02
150
+ )
151
+
152
+ # Factor regression
153
+ factors = client.analytics.factor_regression(
154
+ identifiers="IE00B4L5Y983EURXMIL",
155
+ model="FF5"
156
+ )
157
+ ```
158
+
159
+ ### News & Publications
160
+
161
+ ```python
162
+ # Search news
163
+ news = client.news.search(query="bitcoin", limit=20)
164
+
165
+ # Latest news
166
+ latest = client.news.latest(limit=10)
167
+
168
+ # Trending topics
169
+ trending = client.news.trending(limit=50, finance_only=True)
170
+
171
+ # Search publications
172
+ pubs = client.publications.search(query="market outlook", limit=10)
173
+ ```
174
+
175
+ ### Alerts
176
+
177
+ ```python
178
+ # Create alert
179
+ alert = client.alerts.create(
180
+ name="Price Alert",
181
+ condition={"type": "price_change", "threshold": 5.0},
182
+ action={"type": "webhook", "url": "https://..."}
183
+ )
184
+
185
+ # List alerts
186
+ alerts = client.alerts.list(enabled=True)
187
+
188
+ # Evaluate manually
189
+ result = client.alerts.evaluate(rule_id=alert["id"])
190
+ ```
191
+
192
+ ### Bonds
193
+
194
+ ```python
195
+ # Analyze bond
196
+ analysis = client.bonds.analyze(
197
+ identifier="XS1234567890",
198
+ price=98.5,
199
+ settlement_date="2024-02-01"
200
+ )
201
+
202
+ # Screen bonds
203
+ bonds = client.bonds.screen(
204
+ criteria={"min_yield": 4.0, "max_duration": 5.0},
205
+ limit=50
206
+ )
207
+
208
+ # Get yield curve
209
+ curve = client.bonds.curve(currency="EUR", date="2024-01-15")
210
+ ```
211
+
212
+ ## Arrow/Binary Formats
213
+
214
+ ```python
215
+ from Tepilora.arrow import read_ipc_stream
216
+
217
+ # Request Arrow format
218
+ resp = client.call_arrow_ipc_stream("securities.search", params={"query": "ETF", "limit": 1000})
219
+ table = read_ipc_stream(resp.content)
220
+ print(table.to_pandas())
221
+ ```
222
+
223
+ ## Module-Level API
224
+
225
+ ```python
226
+ import Tepilora as T
227
+
228
+ # Configure globally
229
+ T.configure(api_key="YOUR_KEY")
230
+
231
+ # Use without client instance
232
+ T.analytics.rolling_volatility(identifiers="IE00B4L5Y983EURXMIL")
233
+ ```
234
+
235
+ Or via environment variables:
236
+ ```bash
237
+ export TEPILORA_API_KEY=your_key
238
+ export TEPILORA_BASE_URL=https://tepiloradata.com
239
+ ```
240
+
241
+ ## Error Handling
242
+
243
+ ```python
244
+ from Tepilora.errors import TepiloraAPIError
245
+
246
+ try:
247
+ data = client.securities.search(query="invalid")
248
+ except TepiloraAPIError as e:
249
+ print(f"Error: {e.message}")
250
+ print(f"Code: {e.code}")
251
+ ```
252
+
253
+ ## API Endpoints
254
+
255
+ - `POST /T-Api/v3` - Unified action router (all operations)
256
+ - `GET /T-Api/v3/health` - Health check
257
+ - `GET /T-Api/v3/pricing` - Pricing info
258
+ - `GET /T-Api/v3/logs/status` - Logs status
259
+
260
+ ## Version
261
+
262
+ ```python
263
+ import Tepilora
264
+ print(Tepilora.__version__) # 0.3.0
265
+ ```
@@ -0,0 +1,45 @@
1
+ from .client import AsyncTepiloraClient, TepiloraClient
2
+ from ._default_client import close_default_client, configure_default_client
3
+ from .errors import TepiloraAPIError, TepiloraError
4
+ from .models import V3BinaryMeta, V3BinaryResponse, V3Meta, V3Request, V3Response
5
+ from .version import __version__
6
+
7
+ from .analytics import AnalyticsAPI, AnalyticsFunction, analytics
8
+ from .capabilities import (
9
+ capabilities,
10
+ list_namespaces,
11
+ list_operations,
12
+ get_operation_info,
13
+ )
14
+
15
+
16
+ def configure(**kwargs) -> TepiloraClient:
17
+ """
18
+ Configure the module-level default client used by `Tepilora.analytics.*`.
19
+
20
+ Args are passed to `TepiloraClient(...)` (e.g. api_key, base_url, timeout).
21
+ """
22
+ return configure_default_client(**kwargs)
23
+
24
+
25
+ __all__ = [
26
+ "AsyncTepiloraClient",
27
+ "AnalyticsAPI",
28
+ "AnalyticsFunction",
29
+ "TepiloraAPIError",
30
+ "TepiloraClient",
31
+ "TepiloraError",
32
+ "V3BinaryMeta",
33
+ "V3BinaryResponse",
34
+ "V3Meta",
35
+ "V3Request",
36
+ "V3Response",
37
+ "__version__",
38
+ "analytics",
39
+ "capabilities",
40
+ "configure",
41
+ "close_default_client",
42
+ "get_operation_info",
43
+ "list_namespaces",
44
+ "list_operations",
45
+ ]
@@ -0,0 +1,60 @@
1
+ from __future__ import annotations
2
+
3
+ import threading
4
+ from typing import Optional
5
+
6
+ from .client import TepiloraClient
7
+
8
+ _lock = threading.RLock()
9
+ _default_client: Optional[TepiloraClient] = None
10
+
11
+
12
+ def get_default_client() -> TepiloraClient:
13
+ """
14
+ Get or create the default global client (thread-safe).
15
+
16
+ Uses double-check locking pattern with RLock for thread safety.
17
+ """
18
+ global _default_client
19
+ if _default_client is None:
20
+ with _lock:
21
+ if _default_client is None: # Double-check
22
+ _default_client = TepiloraClient()
23
+ return _default_client
24
+
25
+
26
+ def configure_default_client(**kwargs) -> TepiloraClient:
27
+ """
28
+ Configure the module-level default client used by `Tepilora.analytics.*`.
29
+
30
+ Thread-safe: uses swap-close pattern to avoid closing while other threads use it.
31
+
32
+ Example:
33
+ import Tepilora as T
34
+ T.configure(api_key="...", base_url="https://api.tepiloradata.com")
35
+ T.analytics.rolling_volatility(...)
36
+ """
37
+ global _default_client
38
+ new_client = TepiloraClient(**kwargs)
39
+ with _lock:
40
+ old = _default_client
41
+ _default_client = new_client
42
+ # Close old client OUTSIDE the lock to avoid holding lock during I/O
43
+ if old is not None:
44
+ old.close()
45
+ return new_client
46
+
47
+
48
+ def close_default_client() -> None:
49
+ """
50
+ Close and clear the default client (thread-safe).
51
+
52
+ Uses swap-close pattern: swaps to None under lock, then closes outside lock.
53
+ """
54
+ global _default_client
55
+ with _lock:
56
+ old = _default_client
57
+ _default_client = None
58
+ # Close OUTSIDE the lock
59
+ if old is not None:
60
+ old.close()