finam-sdk 2.16.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.
- finam_sdk-2.16.0/LICENSE +21 -0
- finam_sdk-2.16.0/PKG-INFO +297 -0
- finam_sdk-2.16.0/README.md +260 -0
- finam_sdk-2.16.0/finam_sdk.egg-info/PKG-INFO +297 -0
- finam_sdk-2.16.0/finam_sdk.egg-info/SOURCES.txt +92 -0
- finam_sdk-2.16.0/finam_sdk.egg-info/dependency_links.txt +1 -0
- finam_sdk-2.16.0/finam_sdk.egg-info/requires.txt +12 -0
- finam_sdk-2.16.0/finam_sdk.egg-info/top_level.txt +1 -0
- finam_sdk-2.16.0/finam_trade_api/__init__.py +53 -0
- finam_sdk-2.16.0/finam_trade_api/_metadata.py +69 -0
- finam_sdk-2.16.0/finam_trade_api/accounts.py +37 -0
- finam_sdk-2.16.0/finam_trade_api/aio.py +280 -0
- finam_sdk-2.16.0/finam_trade_api/assets.py +64 -0
- finam_sdk-2.16.0/finam_trade_api/auth.py +229 -0
- finam_sdk-2.16.0/finam_trade_api/auth_messages.py +32 -0
- finam_sdk-2.16.0/finam_trade_api/client.py +254 -0
- finam_sdk-2.16.0/finam_trade_api/exceptions.py +99 -0
- finam_sdk-2.16.0/finam_trade_api/market_data.py +63 -0
- finam_sdk-2.16.0/finam_trade_api/metrics.py +14 -0
- finam_sdk-2.16.0/finam_trade_api/orders.py +59 -0
- finam_sdk-2.16.0/finam_trade_api/proto/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/annotations_pb2.py +37 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/annotations_pb2.pyi +55 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/annotations_pb2_grpc.py +24 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/annotations_pb2_grpc.pyi +20 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/openapiv2_pb2.py +148 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/openapiv2_pb2.pyi +1743 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/openapiv2_pb2_grpc.py +24 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/gateway/protoc_gen_openapiv2/options/openapiv2_pb2_grpc.pyi +20 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/accounts/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/accounts/accounts_service_pb2.py +79 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/accounts/accounts_service_pb2.pyi +568 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/accounts/accounts_service_pb2_grpc.py +250 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/accounts/accounts_service_pb2_grpc.pyi +154 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/assets/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/assets/assets_service_pb2.py +135 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/assets/assets_service_pb2.pyi +1104 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/assets/assets_service_pb2_grpc.py +485 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/assets/assets_service_pb2_grpc.pyi +285 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/auth/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/auth/auth_service_pb2.py +60 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/auth/auth_service_pb2.pyi +264 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/auth/auth_service_pb2_grpc.py +208 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/auth/auth_service_pb2_grpc.pyi +145 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/corporateactions/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/corporateactions/corporate_actions_service_pb2.py +76 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/corporateactions/corporate_actions_service_pb2.pyi +497 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/corporateactions/corporate_actions_service_pb2_grpc.py +233 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/corporateactions/corporate_actions_service_pb2_grpc.pyi +94 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/marketdata/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/marketdata/marketdata_service_pb2.py +107 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/marketdata/marketdata_service_pb2.pyi +1026 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/marketdata/marketdata_service_pb2_grpc.py +425 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/marketdata/marketdata_service_pb2_grpc.pyi +202 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/metrics/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/metrics/usage_metrics_service_pb2.py +48 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/metrics/usage_metrics_service_pb2.pyi +95 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/metrics/usage_metrics_service_pb2_grpc.py +110 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/metrics/usage_metrics_service_pb2_grpc.pyi +79 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/orders/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/orders/orders_service_pb2.py +103 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/orders/orders_service_pb2.pyi +887 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/orders/orders_service_pb2_grpc.py +469 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/orders/orders_service_pb2_grpc.pyi +348 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/reports/__init__.py +0 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/reports/reports_service_pb2.py +65 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/reports/reports_service_pb2.pyi +298 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/reports/reports_service_pb2_grpc.py +195 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/reports/reports_service_pb2_grpc.pyi +106 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/side_pb2.py +37 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/side_pb2.pyi +41 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/side_pb2_grpc.py +24 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/side_pb2_grpc.pyi +20 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/trade_pb2.py +40 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/trade_pb2.pyi +93 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/trade_pb2_grpc.py +24 -0
- finam_sdk-2.16.0/finam_trade_api/proto/grpc/tradeapi/v1/trade_pb2_grpc.pyi +20 -0
- finam_sdk-2.16.0/finam_trade_api/py.typed +0 -0
- finam_sdk-2.16.0/finam_trade_api/reports.py +33 -0
- finam_sdk-2.16.0/finam_trade_api/retry.py +204 -0
- finam_sdk-2.16.0/pyproject.toml +98 -0
- finam_sdk-2.16.0/setup.cfg +4 -0
- finam_sdk-2.16.0/tests/test_auth_manager.py +417 -0
- finam_sdk-2.16.0/tests/test_client_integration.py +348 -0
- finam_sdk-2.16.0/tests/test_exceptions.py +93 -0
- finam_sdk-2.16.0/tests/test_metadata.py +72 -0
- finam_sdk-2.16.0/tests/test_retry.py +341 -0
- finam_sdk-2.16.0/tests/test_shims.py +40 -0
finam_sdk-2.16.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Finam
|
|
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,297 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: finam-sdk
|
|
3
|
+
Version: 2.16.0
|
|
4
|
+
Summary: Official Python SDK for the Finam Trade API (gRPC)
|
|
5
|
+
Author-email: Finam <tradeapi@finam.ru>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/FinamWeb/finam-trade-api
|
|
8
|
+
Project-URL: Documentation, https://tradeapi.finam.ru/
|
|
9
|
+
Project-URL: Repository, https://github.com/FinamWeb/finam-trade-api
|
|
10
|
+
Keywords: finam,trading,grpc,trade-api,brokerage
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: grpcio>=1.60
|
|
26
|
+
Requires-Dist: protobuf>=4.25
|
|
27
|
+
Requires-Dist: googleapis-common-protos>=1.62
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=4; extra == "dev"
|
|
32
|
+
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
33
|
+
Requires-Dist: mypy-protobuf>=3.6; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.3; extra == "dev"
|
|
35
|
+
Requires-Dist: grpcio-tools>=1.60; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# Finam Trade API — Python SDK
|
|
39
|
+
|
|
40
|
+
Thin Python SDK for the [Finam Trade API](https://tradeapi.finam.ru/). Wraps
|
|
41
|
+
the generated gRPC stubs with:
|
|
42
|
+
|
|
43
|
+
- a single `FinamClient` / `AsyncFinamClient` entry point,
|
|
44
|
+
- automatic JWT issuance and background refresh (via `AuthService.SubscribeJwtRenewal`),
|
|
45
|
+
- typed exceptions mapped from gRPC status codes,
|
|
46
|
+
- exponential-backoff retries on transient failures (`UNAVAILABLE`, `RESOURCE_EXHAUSTED`).
|
|
47
|
+
|
|
48
|
+
Service methods are invoked directly on the generated stubs, so the full proto
|
|
49
|
+
surface is available without an extra translation layer.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
pip install finam-sdk
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> The PyPI distribution is `finam-sdk`; the Python import name is
|
|
58
|
+
> `finam_trade_api`. (The `finam-trade-api` name on PyPI is held by an
|
|
59
|
+
> unrelated third-party REST client.)
|
|
60
|
+
|
|
61
|
+
## Quickstart (sync)
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from finam_trade_api import FinamClient
|
|
65
|
+
from finam_trade_api.accounts import GetAccountRequest
|
|
66
|
+
from finam_trade_api.market_data import SubscribeQuoteRequest
|
|
67
|
+
|
|
68
|
+
with FinamClient(secret="YOUR_API_TOKEN") as client:
|
|
69
|
+
account = client.accounts.GetAccount(GetAccountRequest(account_id="A12345"))
|
|
70
|
+
print(account)
|
|
71
|
+
|
|
72
|
+
# Streaming RPCs return iterators.
|
|
73
|
+
for tick in client.market_data.SubscribeQuote(
|
|
74
|
+
SubscribeQuoteRequest(symbols=["SBER@MISX"])
|
|
75
|
+
):
|
|
76
|
+
print(tick)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Quickstart (asyncio)
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import asyncio
|
|
83
|
+
|
|
84
|
+
from finam_trade_api import AsyncFinamClient
|
|
85
|
+
from finam_trade_api.market_data import SubscribeQuoteRequest
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
async def main() -> None:
|
|
89
|
+
async with AsyncFinamClient(secret="YOUR_API_TOKEN") as client:
|
|
90
|
+
async for tick in client.market_data.SubscribeQuote(
|
|
91
|
+
SubscribeQuoteRequest(symbols=["SBER@MISX"])
|
|
92
|
+
):
|
|
93
|
+
print(tick)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
asyncio.run(main())
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Available services
|
|
100
|
+
|
|
101
|
+
The client exposes the full Trade API surface via sub-clients:
|
|
102
|
+
|
|
103
|
+
| Attribute | gRPC service | What it does |
|
|
104
|
+
| -------------------- | ---------------------- | --------------------------------------------- |
|
|
105
|
+
| `client.auth` | `AuthService` | Token issuance + details (usually automatic). |
|
|
106
|
+
| `client.accounts` | `AccountsService` | Accounts, positions, trades, transactions. |
|
|
107
|
+
| `client.assets` | `AssetsService` | Instruments, exchanges, schedules, options. |
|
|
108
|
+
| `client.market_data` | `MarketDataService` | Bars, quotes, order book, trade streams. |
|
|
109
|
+
| `client.orders` | `OrdersService` | Place / cancel orders, order + trade streams. |
|
|
110
|
+
| `client.reports` | `ReportsService` | Account reports. |
|
|
111
|
+
| `client.metrics` | `UsageMetricsService` | API usage / quota metrics. |
|
|
112
|
+
|
|
113
|
+
## API reference
|
|
114
|
+
|
|
115
|
+
Every RPC defined in the `.proto` files is exposed directly on the sub-client.
|
|
116
|
+
Request and response message types are re-exported from short, per-service
|
|
117
|
+
modules:
|
|
118
|
+
|
|
119
|
+
| Module | Use with |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| `finam_trade_api.accounts` | `client.accounts.*` |
|
|
122
|
+
| `finam_trade_api.assets` | `client.assets.*` |
|
|
123
|
+
| `finam_trade_api.market_data` | `client.market_data.*` |
|
|
124
|
+
| `finam_trade_api.orders` | `client.orders.*` (includes `Side`) |
|
|
125
|
+
| `finam_trade_api.reports` | `client.reports.*` |
|
|
126
|
+
| `finam_trade_api.metrics` | `client.metrics.*` |
|
|
127
|
+
| `finam_trade_api.auth_messages` | `client.auth.*` (rarely needed — JWT handled automatically) |
|
|
128
|
+
|
|
129
|
+
The original deeply-nested paths
|
|
130
|
+
(`finam_trade_api.proto.grpc.tradeapi.v1.<service>.<service>_service_pb2`)
|
|
131
|
+
still work and remain the source of truth.
|
|
132
|
+
|
|
133
|
+
Legend: ▶ unary · ⇉ server-stream · ⇄ bidi-stream
|
|
134
|
+
|
|
135
|
+
### `client.auth` — `AuthService`
|
|
136
|
+
|
|
137
|
+
| Method | Kind | Purpose |
|
|
138
|
+
| --- | :---: | --- |
|
|
139
|
+
| `Auth(AuthRequest)` | ▶ | Exchange API secret for a JWT. *Called for you on construction.* |
|
|
140
|
+
| `TokenDetails(TokenDetailsRequest)` | ▶ | Inspect a JWT — expiry, market-data permissions, visible account IDs. |
|
|
141
|
+
| `SubscribeJwtRenewal(SubscribeJwtRenewalRequest)` | ⇉ | Stream of refreshed JWTs. *Consumed for you in the background.* |
|
|
142
|
+
|
|
143
|
+
### `client.accounts` — `AccountsService`
|
|
144
|
+
|
|
145
|
+
| Method | Kind | Purpose |
|
|
146
|
+
| --- | :---: | --- |
|
|
147
|
+
| `GetAccount(GetAccountRequest)` | ▶ | Account info: equity, cash, positions, margin. |
|
|
148
|
+
| `Trades(TradesRequest)` | ▶ | Historical trades for an account. |
|
|
149
|
+
| `Transactions(TransactionsRequest)` | ▶ | Cash movements and other non-trade transactions. |
|
|
150
|
+
| `SubscribeAccount(GetAccountRequest)` | ⇉ | Streaming account updates. |
|
|
151
|
+
|
|
152
|
+
### `client.assets` — `AssetsService`
|
|
153
|
+
|
|
154
|
+
| Method | Kind | Purpose |
|
|
155
|
+
| --- | :---: | --- |
|
|
156
|
+
| `Exchanges(ExchangesRequest)` | ▶ | List of supported exchanges. |
|
|
157
|
+
| `Assets(AssetsRequest)` | ▶ | Tradable instruments (filtered). |
|
|
158
|
+
| `AllAssets(AllAssetsRequest)` | ▶ | Full instrument catalog. |
|
|
159
|
+
| `GetAsset(GetAssetRequest)` | ▶ | Single instrument by symbol. |
|
|
160
|
+
| `GetAssetParams(GetAssetParamsRequest)` | ▶ | Trading parameters for an instrument. |
|
|
161
|
+
| `OptionsChain(OptionsChainRequest)` | ▶ | Options chain for an underlying. |
|
|
162
|
+
| `Schedule(ScheduleRequest)` | ▶ | Trading session schedule. |
|
|
163
|
+
| `Clock(ClockRequest)` | ▶ | Server clock (use for time-aligned operations). |
|
|
164
|
+
| `GetConstituents(GetConstituentsRequest)` | ▶ | Index constituents. |
|
|
165
|
+
|
|
166
|
+
### `client.market_data` — `MarketDataService`
|
|
167
|
+
|
|
168
|
+
| Method | Kind | Purpose |
|
|
169
|
+
| --- | :---: | --- |
|
|
170
|
+
| `Bars(BarsRequest)` | ▶ | OHLC candles (any timeframe via `TimeFrame` enum). |
|
|
171
|
+
| `LastQuote(QuoteRequest)` | ▶ | Most recent quote snapshot. |
|
|
172
|
+
| `OrderBook(OrderBookRequest)` | ▶ | Order book snapshot. |
|
|
173
|
+
| `LatestTrades(LatestTradesRequest)` | ▶ | Most recent trades for a symbol. |
|
|
174
|
+
| `SubscribeQuote(SubscribeQuoteRequest)` | ⇉ | Live quote stream. |
|
|
175
|
+
| `SubscribeOrderBook(SubscribeOrderBookRequest)` | ⇉ | Live order-book updates. |
|
|
176
|
+
| `SubscribeLatestTrades(SubscribeLatestTradesRequest)` | ⇉ | Live trades stream. |
|
|
177
|
+
| `SubscribeBars(SubscribeBarsRequest)` | ⇉ | Live candle stream. |
|
|
178
|
+
|
|
179
|
+
### `client.orders` — `OrdersService`
|
|
180
|
+
|
|
181
|
+
| Method | Kind | Purpose |
|
|
182
|
+
| --- | :---: | --- |
|
|
183
|
+
| `PlaceOrder(Order)` | ▶ | Place market / limit / stop / stop-limit / multi-leg order. |
|
|
184
|
+
| `PlaceSLTPOrder(SLTPOrder)` | ▶ | Place an SL/TP (stop-loss + take-profit) order. |
|
|
185
|
+
| `CancelOrder(CancelOrderRequest)` | ▶ | Cancel an active order. |
|
|
186
|
+
| `GetOrders(OrdersRequest)` | ▶ | List active orders for an account. |
|
|
187
|
+
| `GetOrder(GetOrderRequest)` | ▶ | Single order by ID. |
|
|
188
|
+
| `SubscribeOrders(SubscribeOrdersRequest)` | ⇉ | Live order-state updates. |
|
|
189
|
+
| `SubscribeTrades(SubscribeTradesRequest)` | ⇉ | Live execution / fill stream. |
|
|
190
|
+
| `SubscribeOrderTrade(stream OrderTradeRequest)` | ⇄ | Bidi stream — order + trade events, request-driven. |
|
|
191
|
+
|
|
192
|
+
### `client.reports` — `ReportsService`
|
|
193
|
+
|
|
194
|
+
| Method | Kind | Purpose |
|
|
195
|
+
| --- | :---: | --- |
|
|
196
|
+
| `CreateAccountReport(CreateAccountReportRequest)` | ▶ | Generate an account report (async — returns a job handle). |
|
|
197
|
+
| `GetAccountReportInfo(GetAccountReportInfoRequest)` | ▶ | Poll report status. |
|
|
198
|
+
| `SubscribeAccountReportInfo(SubscribeAccountReportInfoRequest)` | ⇉ | Stream report status updates instead of polling. |
|
|
199
|
+
|
|
200
|
+
### `client.metrics` — `UsageMetricsService`
|
|
201
|
+
|
|
202
|
+
| Method | Kind | Purpose |
|
|
203
|
+
| --- | :---: | --- |
|
|
204
|
+
| `GetUsageMetrics(GetUsageMetricsRequest)` | ▶ | API usage / quota stats for the current token. |
|
|
205
|
+
|
|
206
|
+
### Client lifecycle
|
|
207
|
+
|
|
208
|
+
| Operation | Sync | Async |
|
|
209
|
+
| --- | --- | --- |
|
|
210
|
+
| Construct | `FinamClient(secret, *, endpoint=DEFAULT_ENDPOINT, retry_policy=DEFAULT_POLICY, channel_options=None)` | `AsyncFinamClient(secret, ...)` — same args |
|
|
211
|
+
| Start | *immediate, blocks for initial JWT* | `await client.start()` — or use `async with` |
|
|
212
|
+
| Current JWT | `client.get_token()` → `str \| None` | `client.get_token()` → `str \| None` (sync read of cached snapshot) |
|
|
213
|
+
| Close | `client.close()` | `await client.close()` |
|
|
214
|
+
| Context manager | `with FinamClient(...) as client:` | `async with AsyncFinamClient(...) as client:` |
|
|
215
|
+
| Testing (no TLS) | `FinamClient.for_testing(secret, endpoint="localhost:50051")` | `AsyncFinamClient.for_testing(secret, endpoint="localhost:50051")` |
|
|
216
|
+
|
|
217
|
+
> `for_testing(...)` opens an insecure (plaintext) channel against an in-process fake server. **Never use against `api.finam.ru`** — it sends your JWT in clear.
|
|
218
|
+
|
|
219
|
+
## Error handling
|
|
220
|
+
|
|
221
|
+
Wrap raw `grpc.RpcError` into a typed `FinamError`:
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
import grpc
|
|
225
|
+
from finam_trade_api import FinamClient, RateLimitError, from_rpc_error
|
|
226
|
+
|
|
227
|
+
with FinamClient(secret="...") as client:
|
|
228
|
+
try:
|
|
229
|
+
client.accounts.GetAccount(GetAccountRequest(account_id="A12345"))
|
|
230
|
+
except grpc.RpcError as raw:
|
|
231
|
+
err = from_rpc_error(raw)
|
|
232
|
+
if isinstance(err, RateLimitError):
|
|
233
|
+
...
|
|
234
|
+
raise err
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Exception classes: `AuthError` (401), `PermissionDeniedError` (403),
|
|
238
|
+
`InvalidArgumentError` (400), `NotFoundError` (404), `RateLimitError` (429),
|
|
239
|
+
`InternalError` (500), `ServiceUnavailableError` (503), `DeadlineExceededError` (504).
|
|
240
|
+
All inherit from `FinamError`.
|
|
241
|
+
|
|
242
|
+
## Retries
|
|
243
|
+
|
|
244
|
+
Unary RPCs are retried automatically on `UNAVAILABLE` and `RESOURCE_EXHAUSTED`
|
|
245
|
+
with exponential backoff + jitter. Streaming RPCs are *not* retried — the
|
|
246
|
+
caller is expected to handle reconnection at a meaningful boundary
|
|
247
|
+
(e.g. resuming from the last received bar).
|
|
248
|
+
|
|
249
|
+
Override the policy:
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
from finam_trade_api import FinamClient, RetryPolicy
|
|
253
|
+
|
|
254
|
+
policy = RetryPolicy(max_attempts=6, initial_backoff=0.5, max_backoff=10.0)
|
|
255
|
+
client = FinamClient(secret="...", retry_policy=policy)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Local build
|
|
259
|
+
|
|
260
|
+
From the repository root:
|
|
261
|
+
|
|
262
|
+
```sh
|
|
263
|
+
cd python
|
|
264
|
+
pip install -e ".[dev]"
|
|
265
|
+
./scripts/generate_proto.sh
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
`scripts/generate_proto.sh` compiles the `.proto` files in `../proto/` into
|
|
269
|
+
`finam_trade_api/proto/`. Re-run it whenever the protos change.
|
|
270
|
+
|
|
271
|
+
## Layout
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
python/
|
|
275
|
+
├── pyproject.toml
|
|
276
|
+
├── README.md
|
|
277
|
+
├── LICENSE
|
|
278
|
+
├── scripts/
|
|
279
|
+
│ └── generate_proto.sh # protoc invocation (contributors only)
|
|
280
|
+
├── examples/ # runnable scripts
|
|
281
|
+
└── finam_trade_api/
|
|
282
|
+
├── __init__.py
|
|
283
|
+
├── client.py # FinamClient (sync)
|
|
284
|
+
├── aio.py # AsyncFinamClient
|
|
285
|
+
├── auth.py # JWT lifecycle
|
|
286
|
+
├── retry.py # retry policy + interceptors
|
|
287
|
+
├── exceptions.py # typed errors
|
|
288
|
+
├── _metadata.py # Authorization header plumbing
|
|
289
|
+
├── accounts.py # message re-exports (per-service)
|
|
290
|
+
├── assets.py
|
|
291
|
+
├── auth_messages.py
|
|
292
|
+
├── market_data.py
|
|
293
|
+
├── orders.py
|
|
294
|
+
├── reports.py
|
|
295
|
+
├── metrics.py
|
|
296
|
+
└── proto/ # generated stubs (committed; ships in wheel)
|
|
297
|
+
```
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Finam Trade API — Python SDK
|
|
2
|
+
|
|
3
|
+
Thin Python SDK for the [Finam Trade API](https://tradeapi.finam.ru/). Wraps
|
|
4
|
+
the generated gRPC stubs with:
|
|
5
|
+
|
|
6
|
+
- a single `FinamClient` / `AsyncFinamClient` entry point,
|
|
7
|
+
- automatic JWT issuance and background refresh (via `AuthService.SubscribeJwtRenewal`),
|
|
8
|
+
- typed exceptions mapped from gRPC status codes,
|
|
9
|
+
- exponential-backoff retries on transient failures (`UNAVAILABLE`, `RESOURCE_EXHAUSTED`).
|
|
10
|
+
|
|
11
|
+
Service methods are invoked directly on the generated stubs, so the full proto
|
|
12
|
+
surface is available without an extra translation layer.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
pip install finam-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
> The PyPI distribution is `finam-sdk`; the Python import name is
|
|
21
|
+
> `finam_trade_api`. (The `finam-trade-api` name on PyPI is held by an
|
|
22
|
+
> unrelated third-party REST client.)
|
|
23
|
+
|
|
24
|
+
## Quickstart (sync)
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from finam_trade_api import FinamClient
|
|
28
|
+
from finam_trade_api.accounts import GetAccountRequest
|
|
29
|
+
from finam_trade_api.market_data import SubscribeQuoteRequest
|
|
30
|
+
|
|
31
|
+
with FinamClient(secret="YOUR_API_TOKEN") as client:
|
|
32
|
+
account = client.accounts.GetAccount(GetAccountRequest(account_id="A12345"))
|
|
33
|
+
print(account)
|
|
34
|
+
|
|
35
|
+
# Streaming RPCs return iterators.
|
|
36
|
+
for tick in client.market_data.SubscribeQuote(
|
|
37
|
+
SubscribeQuoteRequest(symbols=["SBER@MISX"])
|
|
38
|
+
):
|
|
39
|
+
print(tick)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quickstart (asyncio)
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
import asyncio
|
|
46
|
+
|
|
47
|
+
from finam_trade_api import AsyncFinamClient
|
|
48
|
+
from finam_trade_api.market_data import SubscribeQuoteRequest
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def main() -> None:
|
|
52
|
+
async with AsyncFinamClient(secret="YOUR_API_TOKEN") as client:
|
|
53
|
+
async for tick in client.market_data.SubscribeQuote(
|
|
54
|
+
SubscribeQuoteRequest(symbols=["SBER@MISX"])
|
|
55
|
+
):
|
|
56
|
+
print(tick)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
asyncio.run(main())
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Available services
|
|
63
|
+
|
|
64
|
+
The client exposes the full Trade API surface via sub-clients:
|
|
65
|
+
|
|
66
|
+
| Attribute | gRPC service | What it does |
|
|
67
|
+
| -------------------- | ---------------------- | --------------------------------------------- |
|
|
68
|
+
| `client.auth` | `AuthService` | Token issuance + details (usually automatic). |
|
|
69
|
+
| `client.accounts` | `AccountsService` | Accounts, positions, trades, transactions. |
|
|
70
|
+
| `client.assets` | `AssetsService` | Instruments, exchanges, schedules, options. |
|
|
71
|
+
| `client.market_data` | `MarketDataService` | Bars, quotes, order book, trade streams. |
|
|
72
|
+
| `client.orders` | `OrdersService` | Place / cancel orders, order + trade streams. |
|
|
73
|
+
| `client.reports` | `ReportsService` | Account reports. |
|
|
74
|
+
| `client.metrics` | `UsageMetricsService` | API usage / quota metrics. |
|
|
75
|
+
|
|
76
|
+
## API reference
|
|
77
|
+
|
|
78
|
+
Every RPC defined in the `.proto` files is exposed directly on the sub-client.
|
|
79
|
+
Request and response message types are re-exported from short, per-service
|
|
80
|
+
modules:
|
|
81
|
+
|
|
82
|
+
| Module | Use with |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `finam_trade_api.accounts` | `client.accounts.*` |
|
|
85
|
+
| `finam_trade_api.assets` | `client.assets.*` |
|
|
86
|
+
| `finam_trade_api.market_data` | `client.market_data.*` |
|
|
87
|
+
| `finam_trade_api.orders` | `client.orders.*` (includes `Side`) |
|
|
88
|
+
| `finam_trade_api.reports` | `client.reports.*` |
|
|
89
|
+
| `finam_trade_api.metrics` | `client.metrics.*` |
|
|
90
|
+
| `finam_trade_api.auth_messages` | `client.auth.*` (rarely needed — JWT handled automatically) |
|
|
91
|
+
|
|
92
|
+
The original deeply-nested paths
|
|
93
|
+
(`finam_trade_api.proto.grpc.tradeapi.v1.<service>.<service>_service_pb2`)
|
|
94
|
+
still work and remain the source of truth.
|
|
95
|
+
|
|
96
|
+
Legend: ▶ unary · ⇉ server-stream · ⇄ bidi-stream
|
|
97
|
+
|
|
98
|
+
### `client.auth` — `AuthService`
|
|
99
|
+
|
|
100
|
+
| Method | Kind | Purpose |
|
|
101
|
+
| --- | :---: | --- |
|
|
102
|
+
| `Auth(AuthRequest)` | ▶ | Exchange API secret for a JWT. *Called for you on construction.* |
|
|
103
|
+
| `TokenDetails(TokenDetailsRequest)` | ▶ | Inspect a JWT — expiry, market-data permissions, visible account IDs. |
|
|
104
|
+
| `SubscribeJwtRenewal(SubscribeJwtRenewalRequest)` | ⇉ | Stream of refreshed JWTs. *Consumed for you in the background.* |
|
|
105
|
+
|
|
106
|
+
### `client.accounts` — `AccountsService`
|
|
107
|
+
|
|
108
|
+
| Method | Kind | Purpose |
|
|
109
|
+
| --- | :---: | --- |
|
|
110
|
+
| `GetAccount(GetAccountRequest)` | ▶ | Account info: equity, cash, positions, margin. |
|
|
111
|
+
| `Trades(TradesRequest)` | ▶ | Historical trades for an account. |
|
|
112
|
+
| `Transactions(TransactionsRequest)` | ▶ | Cash movements and other non-trade transactions. |
|
|
113
|
+
| `SubscribeAccount(GetAccountRequest)` | ⇉ | Streaming account updates. |
|
|
114
|
+
|
|
115
|
+
### `client.assets` — `AssetsService`
|
|
116
|
+
|
|
117
|
+
| Method | Kind | Purpose |
|
|
118
|
+
| --- | :---: | --- |
|
|
119
|
+
| `Exchanges(ExchangesRequest)` | ▶ | List of supported exchanges. |
|
|
120
|
+
| `Assets(AssetsRequest)` | ▶ | Tradable instruments (filtered). |
|
|
121
|
+
| `AllAssets(AllAssetsRequest)` | ▶ | Full instrument catalog. |
|
|
122
|
+
| `GetAsset(GetAssetRequest)` | ▶ | Single instrument by symbol. |
|
|
123
|
+
| `GetAssetParams(GetAssetParamsRequest)` | ▶ | Trading parameters for an instrument. |
|
|
124
|
+
| `OptionsChain(OptionsChainRequest)` | ▶ | Options chain for an underlying. |
|
|
125
|
+
| `Schedule(ScheduleRequest)` | ▶ | Trading session schedule. |
|
|
126
|
+
| `Clock(ClockRequest)` | ▶ | Server clock (use for time-aligned operations). |
|
|
127
|
+
| `GetConstituents(GetConstituentsRequest)` | ▶ | Index constituents. |
|
|
128
|
+
|
|
129
|
+
### `client.market_data` — `MarketDataService`
|
|
130
|
+
|
|
131
|
+
| Method | Kind | Purpose |
|
|
132
|
+
| --- | :---: | --- |
|
|
133
|
+
| `Bars(BarsRequest)` | ▶ | OHLC candles (any timeframe via `TimeFrame` enum). |
|
|
134
|
+
| `LastQuote(QuoteRequest)` | ▶ | Most recent quote snapshot. |
|
|
135
|
+
| `OrderBook(OrderBookRequest)` | ▶ | Order book snapshot. |
|
|
136
|
+
| `LatestTrades(LatestTradesRequest)` | ▶ | Most recent trades for a symbol. |
|
|
137
|
+
| `SubscribeQuote(SubscribeQuoteRequest)` | ⇉ | Live quote stream. |
|
|
138
|
+
| `SubscribeOrderBook(SubscribeOrderBookRequest)` | ⇉ | Live order-book updates. |
|
|
139
|
+
| `SubscribeLatestTrades(SubscribeLatestTradesRequest)` | ⇉ | Live trades stream. |
|
|
140
|
+
| `SubscribeBars(SubscribeBarsRequest)` | ⇉ | Live candle stream. |
|
|
141
|
+
|
|
142
|
+
### `client.orders` — `OrdersService`
|
|
143
|
+
|
|
144
|
+
| Method | Kind | Purpose |
|
|
145
|
+
| --- | :---: | --- |
|
|
146
|
+
| `PlaceOrder(Order)` | ▶ | Place market / limit / stop / stop-limit / multi-leg order. |
|
|
147
|
+
| `PlaceSLTPOrder(SLTPOrder)` | ▶ | Place an SL/TP (stop-loss + take-profit) order. |
|
|
148
|
+
| `CancelOrder(CancelOrderRequest)` | ▶ | Cancel an active order. |
|
|
149
|
+
| `GetOrders(OrdersRequest)` | ▶ | List active orders for an account. |
|
|
150
|
+
| `GetOrder(GetOrderRequest)` | ▶ | Single order by ID. |
|
|
151
|
+
| `SubscribeOrders(SubscribeOrdersRequest)` | ⇉ | Live order-state updates. |
|
|
152
|
+
| `SubscribeTrades(SubscribeTradesRequest)` | ⇉ | Live execution / fill stream. |
|
|
153
|
+
| `SubscribeOrderTrade(stream OrderTradeRequest)` | ⇄ | Bidi stream — order + trade events, request-driven. |
|
|
154
|
+
|
|
155
|
+
### `client.reports` — `ReportsService`
|
|
156
|
+
|
|
157
|
+
| Method | Kind | Purpose |
|
|
158
|
+
| --- | :---: | --- |
|
|
159
|
+
| `CreateAccountReport(CreateAccountReportRequest)` | ▶ | Generate an account report (async — returns a job handle). |
|
|
160
|
+
| `GetAccountReportInfo(GetAccountReportInfoRequest)` | ▶ | Poll report status. |
|
|
161
|
+
| `SubscribeAccountReportInfo(SubscribeAccountReportInfoRequest)` | ⇉ | Stream report status updates instead of polling. |
|
|
162
|
+
|
|
163
|
+
### `client.metrics` — `UsageMetricsService`
|
|
164
|
+
|
|
165
|
+
| Method | Kind | Purpose |
|
|
166
|
+
| --- | :---: | --- |
|
|
167
|
+
| `GetUsageMetrics(GetUsageMetricsRequest)` | ▶ | API usage / quota stats for the current token. |
|
|
168
|
+
|
|
169
|
+
### Client lifecycle
|
|
170
|
+
|
|
171
|
+
| Operation | Sync | Async |
|
|
172
|
+
| --- | --- | --- |
|
|
173
|
+
| Construct | `FinamClient(secret, *, endpoint=DEFAULT_ENDPOINT, retry_policy=DEFAULT_POLICY, channel_options=None)` | `AsyncFinamClient(secret, ...)` — same args |
|
|
174
|
+
| Start | *immediate, blocks for initial JWT* | `await client.start()` — or use `async with` |
|
|
175
|
+
| Current JWT | `client.get_token()` → `str \| None` | `client.get_token()` → `str \| None` (sync read of cached snapshot) |
|
|
176
|
+
| Close | `client.close()` | `await client.close()` |
|
|
177
|
+
| Context manager | `with FinamClient(...) as client:` | `async with AsyncFinamClient(...) as client:` |
|
|
178
|
+
| Testing (no TLS) | `FinamClient.for_testing(secret, endpoint="localhost:50051")` | `AsyncFinamClient.for_testing(secret, endpoint="localhost:50051")` |
|
|
179
|
+
|
|
180
|
+
> `for_testing(...)` opens an insecure (plaintext) channel against an in-process fake server. **Never use against `api.finam.ru`** — it sends your JWT in clear.
|
|
181
|
+
|
|
182
|
+
## Error handling
|
|
183
|
+
|
|
184
|
+
Wrap raw `grpc.RpcError` into a typed `FinamError`:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
import grpc
|
|
188
|
+
from finam_trade_api import FinamClient, RateLimitError, from_rpc_error
|
|
189
|
+
|
|
190
|
+
with FinamClient(secret="...") as client:
|
|
191
|
+
try:
|
|
192
|
+
client.accounts.GetAccount(GetAccountRequest(account_id="A12345"))
|
|
193
|
+
except grpc.RpcError as raw:
|
|
194
|
+
err = from_rpc_error(raw)
|
|
195
|
+
if isinstance(err, RateLimitError):
|
|
196
|
+
...
|
|
197
|
+
raise err
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Exception classes: `AuthError` (401), `PermissionDeniedError` (403),
|
|
201
|
+
`InvalidArgumentError` (400), `NotFoundError` (404), `RateLimitError` (429),
|
|
202
|
+
`InternalError` (500), `ServiceUnavailableError` (503), `DeadlineExceededError` (504).
|
|
203
|
+
All inherit from `FinamError`.
|
|
204
|
+
|
|
205
|
+
## Retries
|
|
206
|
+
|
|
207
|
+
Unary RPCs are retried automatically on `UNAVAILABLE` and `RESOURCE_EXHAUSTED`
|
|
208
|
+
with exponential backoff + jitter. Streaming RPCs are *not* retried — the
|
|
209
|
+
caller is expected to handle reconnection at a meaningful boundary
|
|
210
|
+
(e.g. resuming from the last received bar).
|
|
211
|
+
|
|
212
|
+
Override the policy:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from finam_trade_api import FinamClient, RetryPolicy
|
|
216
|
+
|
|
217
|
+
policy = RetryPolicy(max_attempts=6, initial_backoff=0.5, max_backoff=10.0)
|
|
218
|
+
client = FinamClient(secret="...", retry_policy=policy)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Local build
|
|
222
|
+
|
|
223
|
+
From the repository root:
|
|
224
|
+
|
|
225
|
+
```sh
|
|
226
|
+
cd python
|
|
227
|
+
pip install -e ".[dev]"
|
|
228
|
+
./scripts/generate_proto.sh
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
`scripts/generate_proto.sh` compiles the `.proto` files in `../proto/` into
|
|
232
|
+
`finam_trade_api/proto/`. Re-run it whenever the protos change.
|
|
233
|
+
|
|
234
|
+
## Layout
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
python/
|
|
238
|
+
├── pyproject.toml
|
|
239
|
+
├── README.md
|
|
240
|
+
├── LICENSE
|
|
241
|
+
├── scripts/
|
|
242
|
+
│ └── generate_proto.sh # protoc invocation (contributors only)
|
|
243
|
+
├── examples/ # runnable scripts
|
|
244
|
+
└── finam_trade_api/
|
|
245
|
+
├── __init__.py
|
|
246
|
+
├── client.py # FinamClient (sync)
|
|
247
|
+
├── aio.py # AsyncFinamClient
|
|
248
|
+
├── auth.py # JWT lifecycle
|
|
249
|
+
├── retry.py # retry policy + interceptors
|
|
250
|
+
├── exceptions.py # typed errors
|
|
251
|
+
├── _metadata.py # Authorization header plumbing
|
|
252
|
+
├── accounts.py # message re-exports (per-service)
|
|
253
|
+
├── assets.py
|
|
254
|
+
├── auth_messages.py
|
|
255
|
+
├── market_data.py
|
|
256
|
+
├── orders.py
|
|
257
|
+
├── reports.py
|
|
258
|
+
├── metrics.py
|
|
259
|
+
└── proto/ # generated stubs (committed; ships in wheel)
|
|
260
|
+
```
|