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.
- tepilora-0.3.1/LICENSE +21 -0
- tepilora-0.3.1/MANIFEST.in +13 -0
- tepilora-0.3.1/PKG-INFO +300 -0
- tepilora-0.3.1/README.md +265 -0
- tepilora-0.3.1/Tepilora/__init__.py +45 -0
- tepilora-0.3.1/Tepilora/_default_client.py +60 -0
- tepilora-0.3.1/Tepilora/_schema.py +7745 -0
- tepilora-0.3.1/Tepilora/analytics.py +503 -0
- tepilora-0.3.1/Tepilora/analytics.pyi +3770 -0
- tepilora-0.3.1/Tepilora/arrow.py +42 -0
- tepilora-0.3.1/Tepilora/capabilities.py +321 -0
- tepilora-0.3.1/Tepilora/client.py +630 -0
- tepilora-0.3.1/Tepilora/endpoints/__init__.py +82 -0
- tepilora-0.3.1/Tepilora/endpoints/_base.py +58 -0
- tepilora-0.3.1/Tepilora/endpoints/alerts.py +372 -0
- tepilora-0.3.1/Tepilora/endpoints/alternatives.py +470 -0
- tepilora-0.3.1/Tepilora/endpoints/billing.py +540 -0
- tepilora-0.3.1/Tepilora/endpoints/bonds.py +486 -0
- tepilora-0.3.1/Tepilora/endpoints/clients.py +360 -0
- tepilora-0.3.1/Tepilora/endpoints/data.py +64 -0
- tepilora-0.3.1/Tepilora/endpoints/documents.py +170 -0
- tepilora-0.3.1/Tepilora/endpoints/esg.py +238 -0
- tepilora-0.3.1/Tepilora/endpoints/exports.py +112 -0
- tepilora-0.3.1/Tepilora/endpoints/factors.py +482 -0
- tepilora-0.3.1/Tepilora/endpoints/fh.py +318 -0
- tepilora-0.3.1/Tepilora/endpoints/macro.py +330 -0
- tepilora-0.3.1/Tepilora/endpoints/news.py +372 -0
- tepilora-0.3.1/Tepilora/endpoints/options.py +396 -0
- tepilora-0.3.1/Tepilora/endpoints/portfolio.py +968 -0
- tepilora-0.3.1/Tepilora/endpoints/profiling.py +376 -0
- tepilora-0.3.1/Tepilora/endpoints/publications.py +250 -0
- tepilora-0.3.1/Tepilora/endpoints/queries.py +498 -0
- tepilora-0.3.1/Tepilora/endpoints/search.py +64 -0
- tepilora-0.3.1/Tepilora/endpoints/securities.py +592 -0
- tepilora-0.3.1/Tepilora/endpoints/stocks.py +446 -0
- tepilora-0.3.1/Tepilora/endpoints/workflows.py +126 -0
- tepilora-0.3.1/Tepilora/errors.py +20 -0
- tepilora-0.3.1/Tepilora/models.py +80 -0
- tepilora-0.3.1/Tepilora/py.typed +0 -0
- tepilora-0.3.1/Tepilora/version.py +1 -0
- tepilora-0.3.1/Tepilora.egg-info/PKG-INFO +300 -0
- tepilora-0.3.1/Tepilora.egg-info/SOURCES.txt +45 -0
- tepilora-0.3.1/Tepilora.egg-info/dependency_links.txt +1 -0
- tepilora-0.3.1/Tepilora.egg-info/requires.txt +12 -0
- tepilora-0.3.1/Tepilora.egg-info/top_level.txt +1 -0
- tepilora-0.3.1/pyproject.toml +59 -0
- 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*
|
tepilora-0.3.1/PKG-INFO
ADDED
|
@@ -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
|
+
```
|
tepilora-0.3.1/README.md
ADDED
|
@@ -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()
|