trade-republic-uapi 1.0.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.
- trade_republic_uapi-1.0.0/LICENSE +21 -0
- trade_republic_uapi-1.0.0/PKG-INFO +429 -0
- trade_republic_uapi-1.0.0/README.md +394 -0
- trade_republic_uapi-1.0.0/pyproject.toml +49 -0
- trade_republic_uapi-1.0.0/setup.cfg +4 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi/__init__.py +1 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi/api_server.py +898 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi/auth.py +31 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi/cli.py +382 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi/fetch.py +112 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi/preferences.py +121 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi.egg-info/PKG-INFO +429 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi.egg-info/SOURCES.txt +15 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi.egg-info/dependency_links.txt +1 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi.egg-info/entry_points.txt +2 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi.egg-info/requires.txt +10 -0
- trade_republic_uapi-1.0.0/trade_republic_uapi.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 4strium
|
|
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,429 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trade-republic-uapi
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Lightweight & Fast unofficial REST API for Trade Republic
|
|
5
|
+
Author: 4strium
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/4strium/trade-republic-uapi
|
|
8
|
+
Project-URL: Repository, https://github.com/4strium/trade-republic-uapi
|
|
9
|
+
Keywords: trade-republic,api,unofficial,fastapi,fintech
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: fastapi==0.140.0
|
|
25
|
+
Requires-Dist: httpx==0.28.1
|
|
26
|
+
Requires-Dist: playwright==1.61.0
|
|
27
|
+
Requires-Dist: prompt_toolkit==3.0.52
|
|
28
|
+
Requires-Dist: pydantic==2.13.4
|
|
29
|
+
Requires-Dist: qrcode==8.2
|
|
30
|
+
Requires-Dist: questionary==2.1.1
|
|
31
|
+
Requires-Dist: rich==15.0.0
|
|
32
|
+
Requires-Dist: uvicorn==0.51.0
|
|
33
|
+
Requires-Dist: websockets==16.1.1
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# Trade Republic Unofficial API
|
|
37
|
+
|
|
38
|
+
> ⚠️ **Disclaimer**: this project is **not affiliated with Trade Republic Bank GmbH**. Use it at your own risk, especially for endpoints that place real orders.
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<img src="https://github.com/4strium/trade-republic-uapi/blob/main/ressources/TradeRepublicUAPI_demo.gif?raw=true" width="80%" alt="CLI demonstration">
|
|
42
|
+
</p>
|
|
43
|
+
|
|
44
|
+
Lightweight & Fast unofficial REST API for Trade Republic
|
|
45
|
+
|
|
46
|
+
## How it works
|
|
47
|
+
|
|
48
|
+
1. The main program launches a headless Chromium browser and guides you through the official Trade Republic login flow.
|
|
49
|
+
2. Once authenticated, it starts a local FastAPI server in the background, reusing that authenticated session to call Trade Republic's private REST and WebSocket APIs.
|
|
50
|
+
3. You then interact with your own account through simple, well-documented HTTP endpoints exposed by that local server.
|
|
51
|
+
|
|
52
|
+
## Install and start the API server
|
|
53
|
+
|
|
54
|
+
### Option 1: via pip (recommended)
|
|
55
|
+
```bash
|
|
56
|
+
pip install trade-republic-uapi
|
|
57
|
+
traderep-uapi
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Option 2: from source (development)
|
|
61
|
+
```bash
|
|
62
|
+
python3 -m venv .venv
|
|
63
|
+
source .venv/bin/activate
|
|
64
|
+
pip install -r requirements.txt
|
|
65
|
+
python3 -m trade_republic_uapi.cli
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Follow the on-screen instructions to scan the QR code with the Trade Republic app. Once authenticated, the API server starts automatically.
|
|
69
|
+
|
|
70
|
+
## Interactive API documentation
|
|
71
|
+
|
|
72
|
+
Once the server is running, interactive documentation where you can browse every endpoint, see the request/response schemas, try requests live, and view example payloads is available at:
|
|
73
|
+
|
|
74
|
+
- Swagger UI: `http://127.0.0.1:8000/docs`
|
|
75
|
+
- ReDoc: `http://127.0.0.1:8000/redoc`
|
|
76
|
+
- Raw OpenAPI schema: `http://127.0.0.1:8000/openapi.json`
|
|
77
|
+
|
|
78
|
+
## Endpoints reference
|
|
79
|
+
|
|
80
|
+
All endpoints are served from the base URL of your running instance (e.g. `http://127.0.0.1:8000`). `GET` endpoints take no body; `POST` endpoints take a JSON body as described.
|
|
81
|
+
|
|
82
|
+
| Method | Path | Tag | Description | Body schema |
|
|
83
|
+
|--------|--------------------------|--------------|----------------------------------------------------------------------------|---------------------------|
|
|
84
|
+
| GET | `/api/personal-details` | Account | Personal details + banking info (IBAN/BIC) of the customer | — |
|
|
85
|
+
| GET | `/api/tickets` | Account | Open and closed support tickets | — |
|
|
86
|
+
| GET | `/api/card` | Card | Debit card details (status, cardholder, security settings...) | — |
|
|
87
|
+
| GET | `/api/interests` | Account | Interest rate applied to cash in the default account | — |
|
|
88
|
+
| GET | `/api/orders` | Orders | Last 500 orders per securities account | — |
|
|
89
|
+
| GET | `/api/transactions` | Account | Last 500 timeline transactions (trades, dividends, payments...) | — |
|
|
90
|
+
| GET | `/api/portfolio` | Portfolio | Current positions per account, enriched with stock details | — |
|
|
91
|
+
| GET | `/api/accounts` | Account | Accounts with cash balances (`cashAmount`, `availableCashAmount`) | — |
|
|
92
|
+
| GET | `/api/price-alarms` | Price Alarms | List all configured price alarms | — |
|
|
93
|
+
| GET | `/api/accounts-activity` | Account | Timeline activity log (logins, actions...) | — |
|
|
94
|
+
| POST | `/api/schedule-exchange` | Instruments | Trading schedule of an exchange | [`ExchangeSymbol`](#exchangesymbol) |
|
|
95
|
+
| POST | `/api/accounts-history` | Portfolio | Historical portfolio value per account, over a time range | [`AccountHistoryRequest`](#accounthistoryrequest) |
|
|
96
|
+
| POST | `/api/instrument-history`| Instruments | Historical price series of an instrument, over a time range | [`InstrumentHistory`](#instrumenthistory) |
|
|
97
|
+
| POST | `/api/instrument` | Instruments | General details about an instrument (name, type, exchanges...) | [`Instrument`](#instrument) |
|
|
98
|
+
| POST | `/api/tr-instrument` | Instruments | Trade Republic's home exchange for an instrument | [`Instrument`](#instrument) |
|
|
99
|
+
| POST | `/api/order-price` | Orders | Live buy/sell price quote for an instrument | [`OrderPrice`](#orderprice) |
|
|
100
|
+
| POST | `/api/order-fees` | Orders | Simulates an order and returns its fees (no order is placed) | [`Order`](#order) (`validity` optional) |
|
|
101
|
+
| POST | `/api/place-order` | Orders | **Places a real order** ⚠️ | [`Order`](#order) (`validity` required) |
|
|
102
|
+
| POST | `/api/cancel-order` | Orders | Cancels an open order | [`OrderId`](#orderid) |
|
|
103
|
+
| POST | `/api/set-price-alarm` | Price Alarms | Creates a new price alarm | [`PriceAlarm`](#pricealarm) |
|
|
104
|
+
| POST | `/api/delete-price-alarm`| Price Alarms | Deletes an existing price alarm | [`PriceAlarmId`](#pricealarmid) |
|
|
105
|
+
|
|
106
|
+
### Schemas
|
|
107
|
+
|
|
108
|
+
#### ExchangeSymbol
|
|
109
|
+
```jsonc
|
|
110
|
+
{ "symbol": "XETR" } // one of: LSX, TDG, TIB, XETR, XMIL, XPAR, XWBO
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### InstrumentHistory
|
|
114
|
+
```jsonc
|
|
115
|
+
{ "id": "US0378331005", "range": "1m" } // range: 1d, 5d, 1m, 1y, max
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### Instrument
|
|
119
|
+
```jsonc
|
|
120
|
+
{ "id": "US0378331005" } // ISIN
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### AccountHistoryRequest
|
|
124
|
+
```jsonc
|
|
125
|
+
{ "range": "1y" } // range: 1d, 5d, 1m, 1y, max
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### OrderPrice
|
|
129
|
+
```jsonc
|
|
130
|
+
{ "exchange": "XETR", "instrument": "US0378331005" }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### Order
|
|
134
|
+
```jsonc
|
|
135
|
+
{
|
|
136
|
+
"account_nb": "DE1234567890123456",
|
|
137
|
+
"exchange": "XETR",
|
|
138
|
+
"instrument": "US0378331005",
|
|
139
|
+
"mode": "limit", // stopMarket, market, limit
|
|
140
|
+
"quantity": 10,
|
|
141
|
+
"stop": null, // required if mode = stopMarket
|
|
142
|
+
"limit": 145.5, // required if mode = limit
|
|
143
|
+
"type": "buy", // buy, sell
|
|
144
|
+
"validity": "GTC" // GFD, GTD, GTC — required for /api/place-order
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### OrderId
|
|
149
|
+
```jsonc
|
|
150
|
+
{ "orderId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### PriceAlarm
|
|
154
|
+
```jsonc
|
|
155
|
+
{ "instrument": "US0378331005", "targetPrice": 180.0 }
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### PriceAlarmId
|
|
159
|
+
```jsonc
|
|
160
|
+
{ "alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321" }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Usage examples
|
|
164
|
+
|
|
165
|
+
The examples below use fictitious values (fake ISIN, account number, order IDs). Replace them with your own data. All examples assume the server runs on `http://127.0.0.1:8000`.
|
|
166
|
+
|
|
167
|
+
### curl
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Personal details
|
|
171
|
+
curl -s -X GET "http://127.0.0.1:8000/api/personal-details"
|
|
172
|
+
|
|
173
|
+
# Support tickets
|
|
174
|
+
curl -s -X GET "http://127.0.0.1:8000/api/tickets"
|
|
175
|
+
|
|
176
|
+
# Debit card details
|
|
177
|
+
curl -s -X GET "http://127.0.0.1:8000/api/card"
|
|
178
|
+
|
|
179
|
+
# Interest rate on cash
|
|
180
|
+
curl -s -X GET "http://127.0.0.1:8000/api/interests"
|
|
181
|
+
|
|
182
|
+
# Orders per account
|
|
183
|
+
curl -s -X GET "http://127.0.0.1:8000/api/orders"
|
|
184
|
+
|
|
185
|
+
# Transactions timeline
|
|
186
|
+
curl -s -X GET "http://127.0.0.1:8000/api/transactions"
|
|
187
|
+
|
|
188
|
+
# Portfolio positions
|
|
189
|
+
curl -s -X GET "http://127.0.0.1:8000/api/portfolio"
|
|
190
|
+
|
|
191
|
+
# Accounts + cash balances
|
|
192
|
+
curl -s -X GET "http://127.0.0.1:8000/api/accounts"
|
|
193
|
+
|
|
194
|
+
# Price alarms
|
|
195
|
+
curl -s -X GET "http://127.0.0.1:8000/api/price-alarms"
|
|
196
|
+
|
|
197
|
+
# Account activity log
|
|
198
|
+
curl -s -X GET "http://127.0.0.1:8000/api/accounts-activity"
|
|
199
|
+
|
|
200
|
+
# Exchange trading schedule
|
|
201
|
+
curl -s -X POST "http://127.0.0.1:8000/api/schedule-exchange" \
|
|
202
|
+
-H "Content-Type: application/json" \
|
|
203
|
+
-d '{"symbol": "XETR"}'
|
|
204
|
+
|
|
205
|
+
# Portfolio value history
|
|
206
|
+
curl -s -X POST "http://127.0.0.1:8000/api/accounts-history" \
|
|
207
|
+
-H "Content-Type: application/json" \
|
|
208
|
+
-d '{"range": "1y"}'
|
|
209
|
+
|
|
210
|
+
# Instrument price history
|
|
211
|
+
curl -s -X POST "http://127.0.0.1:8000/api/instrument-history" \
|
|
212
|
+
-H "Content-Type: application/json" \
|
|
213
|
+
-d '{"id": "US0378331005", "range": "1m"}'
|
|
214
|
+
|
|
215
|
+
# Global instrument details
|
|
216
|
+
curl -s -X POST "http://127.0.0.1:8000/api/instrument" \
|
|
217
|
+
-H "Content-Type: application/json" \
|
|
218
|
+
-d '{"id": "US0378331005"}'
|
|
219
|
+
|
|
220
|
+
# Trade Republic home exchange for an instrument
|
|
221
|
+
curl -s -X POST "http://127.0.0.1:8000/api/tr-instrument" \
|
|
222
|
+
-H "Content-Type: application/json" \
|
|
223
|
+
-d '{"id": "US0378331005"}'
|
|
224
|
+
|
|
225
|
+
# Live order price (buy/sell quote)
|
|
226
|
+
curl -s -X POST "http://127.0.0.1:8000/api/order-price" \
|
|
227
|
+
-H "Content-Type: application/json" \
|
|
228
|
+
-d '{"exchange": "XETR", "instrument": "US0378331005", "unit": "EUR"}'
|
|
229
|
+
|
|
230
|
+
# Get order fees
|
|
231
|
+
curl -s -X POST "http://127.0.0.1:8000/api/order-fees" \
|
|
232
|
+
-H "Content-Type: application/json" \
|
|
233
|
+
-d '{
|
|
234
|
+
"account_nb": "DE1234567890123456",
|
|
235
|
+
"exchange": "XETR",
|
|
236
|
+
"instrument": "US0378331005",
|
|
237
|
+
"mode": "limit",
|
|
238
|
+
"quantity": 10,
|
|
239
|
+
"limit": 145.5,
|
|
240
|
+
"type": "buy"
|
|
241
|
+
}'
|
|
242
|
+
|
|
243
|
+
# Place a real order ⚠️
|
|
244
|
+
curl -s -X POST "http://127.0.0.1:8000/api/place-order" \
|
|
245
|
+
-H "Content-Type: application/json" \
|
|
246
|
+
-d '{
|
|
247
|
+
"account_nb": "DE1234567890123456",
|
|
248
|
+
"exchange": "XETR",
|
|
249
|
+
"instrument": "US0378331005",
|
|
250
|
+
"mode": "limit",
|
|
251
|
+
"quantity": 10,
|
|
252
|
+
"limit": 145.5,
|
|
253
|
+
"type": "buy",
|
|
254
|
+
"validity": "GTC"
|
|
255
|
+
}'
|
|
256
|
+
|
|
257
|
+
# Cancel an order
|
|
258
|
+
curl -s -X POST "http://127.0.0.1:8000/api/cancel-order" \
|
|
259
|
+
-H "Content-Type: application/json" \
|
|
260
|
+
-d '{"orderId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}'
|
|
261
|
+
|
|
262
|
+
# Create a price alarm
|
|
263
|
+
curl -s -X POST "http://127.0.0.1:8000/api/set-price-alarm" \
|
|
264
|
+
-H "Content-Type: application/json" \
|
|
265
|
+
-d '{"instrument": "US0378331005", "targetPrice": 180.0}'
|
|
266
|
+
|
|
267
|
+
# Delete a price alarm
|
|
268
|
+
curl -s -X POST "http://127.0.0.1:8000/api/delete-price-alarm" \
|
|
269
|
+
-H "Content-Type: application/json" \
|
|
270
|
+
-d '{"alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321"}'
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Python
|
|
274
|
+
|
|
275
|
+
Using the [`requests`](https://pypi.org/project/requests/) library (`pip install requests`):
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
import requests
|
|
279
|
+
|
|
280
|
+
BASE_URL = "http://127.0.0.1:8000"
|
|
281
|
+
|
|
282
|
+
# --- Simple GET endpoints -------------------------------------------------
|
|
283
|
+
portfolio = requests.get(f"{BASE_URL}/api/portfolio").json()
|
|
284
|
+
accounts = requests.get(f"{BASE_URL}/api/accounts").json()
|
|
285
|
+
print(portfolio, accounts)
|
|
286
|
+
|
|
287
|
+
# --- Get the live price of an instrument ----------------------------------
|
|
288
|
+
price = requests.post(
|
|
289
|
+
f"{BASE_URL}/api/order-price",
|
|
290
|
+
json={
|
|
291
|
+
"exchange": "XETR",
|
|
292
|
+
"instrument": "US0378331005", # fictitious ISIN
|
|
293
|
+
"unit": "EUR",
|
|
294
|
+
},
|
|
295
|
+
).json()
|
|
296
|
+
print("Sell price:", price["sell"])
|
|
297
|
+
print("Buy price:", price["buy"])
|
|
298
|
+
|
|
299
|
+
# --- Simulate an order and check its fees before placing it ---------------
|
|
300
|
+
order_payload = {
|
|
301
|
+
"account_nb": "DE1234567890123456", # fictitious securities account number
|
|
302
|
+
"exchange": "XETR",
|
|
303
|
+
"instrument": "US0378331005",
|
|
304
|
+
"mode": "limit",
|
|
305
|
+
"quantity": 10,
|
|
306
|
+
"limit": 145.5,
|
|
307
|
+
"type": "buy",
|
|
308
|
+
}
|
|
309
|
+
fees_response = requests.post(f"{BASE_URL}/api/order-fees", json=order_payload)
|
|
310
|
+
fees_response.raise_for_status()
|
|
311
|
+
print("Estimated fees:", fees_response.json())
|
|
312
|
+
|
|
313
|
+
# --- Place a real order (validity is required) ⚠️ --------------------------
|
|
314
|
+
order_payload["validity"] = "GTC"
|
|
315
|
+
place_response = requests.post(f"{BASE_URL}/api/place-order", json=order_payload)
|
|
316
|
+
if place_response.status_code == 200:
|
|
317
|
+
print("Order placed:", place_response.json())
|
|
318
|
+
else:
|
|
319
|
+
print("Error placing order:", place_response.status_code, place_response.json())
|
|
320
|
+
|
|
321
|
+
# --- Create and then delete a price alarm ----------------------------------
|
|
322
|
+
alarm = requests.post(
|
|
323
|
+
f"{BASE_URL}/api/set-price-alarm",
|
|
324
|
+
json={"instrument": "US0378331005", "targetPrice": 180.0},
|
|
325
|
+
).json()
|
|
326
|
+
print("Alarm created:", alarm)
|
|
327
|
+
|
|
328
|
+
requests.post(
|
|
329
|
+
f"{BASE_URL}/api/delete-price-alarm",
|
|
330
|
+
json={"alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321"},
|
|
331
|
+
)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Rust
|
|
335
|
+
|
|
336
|
+
Using [`reqwest`](https://crates.io/crates/reqwest) and [`serde_json`](https://crates.io/crates/serde_json). Add to `Cargo.toml`:
|
|
337
|
+
|
|
338
|
+
```toml
|
|
339
|
+
[dependencies]
|
|
340
|
+
reqwest = { version = "0.12", features = ["json", "blocking"] }
|
|
341
|
+
serde_json = "1"
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
```rust
|
|
345
|
+
use reqwest::blocking::Client;
|
|
346
|
+
use serde_json::json;
|
|
347
|
+
|
|
348
|
+
const BASE_URL: &str = "http://127.0.0.1:8000";
|
|
349
|
+
|
|
350
|
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
351
|
+
let client = Client::new();
|
|
352
|
+
|
|
353
|
+
// --- Simple GET endpoints ---------------------------------------------
|
|
354
|
+
let portfolio: serde_json::Value = client
|
|
355
|
+
.get(format!("{BASE_URL}/api/portfolio"))
|
|
356
|
+
.send()?
|
|
357
|
+
.json()?;
|
|
358
|
+
println!("Portfolio: {portfolio}");
|
|
359
|
+
|
|
360
|
+
let accounts: serde_json::Value = client
|
|
361
|
+
.get(format!("{BASE_URL}/api/accounts"))
|
|
362
|
+
.send()?
|
|
363
|
+
.json()?;
|
|
364
|
+
println!("Accounts: {accounts}");
|
|
365
|
+
|
|
366
|
+
// --- Get the live price of an instrument -------------------------------
|
|
367
|
+
let price: serde_json::Value = client
|
|
368
|
+
.post(format!("{BASE_URL}/api/order-price"))
|
|
369
|
+
.json(&json!({
|
|
370
|
+
"exchange": "XETR",
|
|
371
|
+
"instrument": "US0378331005", // fictitious ISIN
|
|
372
|
+
"unit": "EUR"
|
|
373
|
+
}))
|
|
374
|
+
.send()?
|
|
375
|
+
.json()?;
|
|
376
|
+
println!("Sell price: {}", price["sell"]);
|
|
377
|
+
println!("Buy price: {}", price["buy"]);
|
|
378
|
+
|
|
379
|
+
// --- Simulate an order and check its fees before placing it -----------
|
|
380
|
+
let mut order_payload = json!({
|
|
381
|
+
"account_nb": "DE1234567890123456", // fictitious securities account number
|
|
382
|
+
"exchange": "XETR",
|
|
383
|
+
"instrument": "US0378331005",
|
|
384
|
+
"mode": "limit",
|
|
385
|
+
"quantity": 10,
|
|
386
|
+
"limit": 145.5,
|
|
387
|
+
"type": "buy"
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
let fees: serde_json::Value = client
|
|
391
|
+
.post(format!("{BASE_URL}/api/order-fees"))
|
|
392
|
+
.json(&order_payload)
|
|
393
|
+
.send()?
|
|
394
|
+
.json()?;
|
|
395
|
+
println!("Estimated fees: {fees}");
|
|
396
|
+
|
|
397
|
+
// --- Place a real order (validity is required) ⚠️ -----------------------
|
|
398
|
+
order_payload["validity"] = json!("GTC");
|
|
399
|
+
let response = client
|
|
400
|
+
.post(format!("{BASE_URL}/api/place-order"))
|
|
401
|
+
.json(&order_payload)
|
|
402
|
+
.send()?;
|
|
403
|
+
|
|
404
|
+
if response.status().is_success() {
|
|
405
|
+
println!("Order placed: {:?}", response.json::<serde_json::Value>()?);
|
|
406
|
+
} else {
|
|
407
|
+
println!(
|
|
408
|
+
"Error placing order ({}): {:?}",
|
|
409
|
+
response.status(),
|
|
410
|
+
response.json::<serde_json::Value>()?
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// --- Create and then delete a price alarm ------------------------------
|
|
415
|
+
let alarm: serde_json::Value = client
|
|
416
|
+
.post(format!("{BASE_URL}/api/set-price-alarm"))
|
|
417
|
+
.json(&json!({ "instrument": "US0378331005", "targetPrice": 180.0 }))
|
|
418
|
+
.send()?
|
|
419
|
+
.json()?;
|
|
420
|
+
println!("Alarm created: {alarm}");
|
|
421
|
+
|
|
422
|
+
client
|
|
423
|
+
.post(format!("{BASE_URL}/api/delete-price-alarm"))
|
|
424
|
+
.json(&json!({ "alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321" }))
|
|
425
|
+
.send()?;
|
|
426
|
+
|
|
427
|
+
Ok(())
|
|
428
|
+
}
|
|
429
|
+
```
|