ctrader-api-client 0.1.0__py3-none-any.whl

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 (43) hide show
  1. ctrader_api_client/__init__.py +64 -0
  2. ctrader_api_client/_internal/__init__.py +26 -0
  3. ctrader_api_client/_internal/messages.py +348 -0
  4. ctrader_api_client/_internal/proto/OpenApiCommonMessages.py +42 -0
  5. ctrader_api_client/_internal/proto/OpenApiCommonModelMessages.py +30 -0
  6. ctrader_api_client/_internal/proto/OpenApiMessages.py +1112 -0
  7. ctrader_api_client/_internal/proto/OpenApiModelMessages.py +802 -0
  8. ctrader_api_client/_internal/proto/__init__.py +320 -0
  9. ctrader_api_client/_internal/serialization.py +84 -0
  10. ctrader_api_client/api/__init__.py +21 -0
  11. ctrader_api_client/api/accounts.py +71 -0
  12. ctrader_api_client/api/market_data.py +424 -0
  13. ctrader_api_client/api/symbols.py +171 -0
  14. ctrader_api_client/api/trading.py +506 -0
  15. ctrader_api_client/auth/__init__.py +14 -0
  16. ctrader_api_client/auth/credentials.py +72 -0
  17. ctrader_api_client/auth/manager.py +511 -0
  18. ctrader_api_client/client.py +475 -0
  19. ctrader_api_client/config.py +56 -0
  20. ctrader_api_client/connection/__init__.py +16 -0
  21. ctrader_api_client/connection/heartbeat.py +120 -0
  22. ctrader_api_client/connection/protocol.py +366 -0
  23. ctrader_api_client/connection/transport.py +123 -0
  24. ctrader_api_client/enums.py +138 -0
  25. ctrader_api_client/events/__init__.py +65 -0
  26. ctrader_api_client/events/emitter.py +254 -0
  27. ctrader_api_client/events/router.py +400 -0
  28. ctrader_api_client/events/types.py +340 -0
  29. ctrader_api_client/exceptions.py +231 -0
  30. ctrader_api_client/models/__init__.py +50 -0
  31. ctrader_api_client/models/_base.py +19 -0
  32. ctrader_api_client/models/account.py +177 -0
  33. ctrader_api_client/models/deal.py +242 -0
  34. ctrader_api_client/models/market_data.py +192 -0
  35. ctrader_api_client/models/order.py +262 -0
  36. ctrader_api_client/models/position.py +209 -0
  37. ctrader_api_client/models/requests.py +299 -0
  38. ctrader_api_client/models/symbol.py +194 -0
  39. ctrader_api_client/py.typed +0 -0
  40. ctrader_api_client-0.1.0.dist-info/METADATA +252 -0
  41. ctrader_api_client-0.1.0.dist-info/RECORD +43 -0
  42. ctrader_api_client-0.1.0.dist-info/WHEEL +4 -0
  43. ctrader_api_client-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,252 @@
1
+ Metadata-Version: 2.4
2
+ Name: ctrader-api-client
3
+ Version: 0.1.0
4
+ Summary: API Client to interact with the cTrader Open API spec
5
+ Author-email: Elio <elioachukri@pm.me>
6
+ License-File: LICENSE
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Natural Language :: English
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Python: >=3.12
14
+ Requires-Dist: anyio>=4.13.0
15
+ Requires-Dist: betterproto[compiler]>=1.2.5
16
+ Requires-Dist: pydantic>=2.12.5
17
+ Requires-Dist: tenacity>=9.1.4
18
+ Description-Content-Type: text/markdown
19
+
20
+ # cTrader API Client
21
+
22
+ A Python client for the cTrader Open API. Provides a high-level async interface for trading operations, market data subscriptions, and account management.
23
+
24
+ Documentation:
25
+ - [Library Docs](https://elioachukri.github.io/ctrader-api-client/)
26
+ - [cTrader Open API Docs](https://help.ctrader.com/open-api/)
27
+
28
+ > Note that this library is in early development. The API may change, and some features may be incomplete. Contributions and feedback are welcome!
29
+
30
+ ## Requirements
31
+
32
+ - Python 3.12+
33
+ - An activated cTrader Open API application with client ID and secret
34
+ - OAuth tokens for account authentication (see below)
35
+
36
+ ## Installation
37
+
38
+ **Using uv (recommended):**
39
+
40
+ ```bash
41
+ uv add ctrader-api-client
42
+ ```
43
+
44
+ **Using pip:**
45
+
46
+ ```bash
47
+ pip install ctrader-api-client
48
+ ```
49
+
50
+ ## Quick Start
51
+
52
+ ```python
53
+ import asyncio
54
+ from ctrader_api_client import CTraderClient, ClientConfig
55
+ from ctrader_api_client.events import ReadyEvent, SpotEvent
56
+
57
+ config = ClientConfig(
58
+ client_id="your_client_id",
59
+ client_secret="your_client_secret",
60
+ )
61
+
62
+ client = CTraderClient(config)
63
+
64
+
65
+ @client.on(SpotEvent, symbol_id=270) # US500.cash
66
+ async def on_price(event: SpotEvent):
67
+ print(f"Price update: {event.bid}/{event.ask}")
68
+
69
+
70
+ @client.on(ReadyEvent)
71
+ async def on_ready(event: ReadyEvent):
72
+ """Called when account is authenticated and ready."""
73
+ await client.market_data.subscribe_spots(event.account_id, [270])
74
+
75
+
76
+ async def main():
77
+ async with client:
78
+ await client.auth.authenticate_app()
79
+ await client.auth.authenticate_by_trader_login(
80
+ trader_login=12345678,
81
+ access_token="your_access_token",
82
+ refresh_token="your_refresh_token",
83
+ expires_at=1778617423,
84
+ )
85
+
86
+ # Keep running to receive events
87
+ await asyncio.Event().wait()
88
+
89
+
90
+ if __name__ == "__main__":
91
+ asyncio.run(main())
92
+ ```
93
+
94
+ ## OAuth Token Generation
95
+
96
+ This library requires OAuth tokens from cTrader. For simple use cases, you can use [ctrader-oauth-fetcher](https://github.com/ElioaChukri/ctrader-oauth-fetcher) to generate tokens:
97
+
98
+ ```bash
99
+ uvx ctrader-oauth-fetcher --client-id [ID] --client-secret [SECRET]
100
+ ```
101
+
102
+ This opens a browser for authorization and returns your access token, refresh token, and expiry time.
103
+
104
+ For production applications, implement the OAuth flow according to the [cTrader Open API documentation](https://help.ctrader.com/open-api/).
105
+
106
+ ## Features
107
+
108
+ ### Authentication
109
+
110
+ ```python
111
+ # Authenticate the application
112
+ await client.auth.authenticate_app()
113
+
114
+ # Authenticate a trading account
115
+ creds = await client.auth.authenticate_by_trader_login(
116
+ trader_login=12345678,
117
+ access_token="...",
118
+ refresh_token="...",
119
+ expires_at=1778617423,
120
+ )
121
+
122
+ # Tokens are automatically refreshed before expiry
123
+ ```
124
+
125
+ ### Market Data
126
+
127
+ ```python
128
+ # Subscribe to spot prices
129
+ await client.market_data.subscribe_spots(account_id, [symbol_id])
130
+
131
+ # Subscribe to candles
132
+ await client.market_data.subscribe_trendbars(account_id, symbol_id, TrendbarPeriod.M1)
133
+
134
+ # Get historical data
135
+ bars = await client.market_data.get_trendbars(
136
+ account_id, symbol_id, TrendbarPeriod.H1, from_ts, to_ts
137
+ )
138
+ ```
139
+
140
+ ### Trading
141
+
142
+ ```python
143
+ from ctrader_api_client.models import NewOrderRequest, ClosePositionRequest
144
+ from ctrader_api_client.enums import OrderType, OrderSide
145
+
146
+ # Place a market order
147
+ request = NewOrderRequest(
148
+ symbol_id=symbol_id,
149
+ order_type=OrderType.MARKET,
150
+ side=OrderSide.BUY,
151
+ volume=100000, # 1 lot in cents
152
+ )
153
+ result = await client.trading.create_order(account_id, request)
154
+
155
+ # Get open positions
156
+ positions = await client.trading.get_positions(account_id)
157
+
158
+ # Close a position
159
+ close_position = ClosePositionRequest(
160
+ position_id=position_id,
161
+ volume=100000, # Close full volume
162
+ )
163
+ await client.trading.close_position(account_id, close_position)
164
+ ```
165
+
166
+ ### Event Handling
167
+
168
+ ```python
169
+ from ctrader_api_client.events import (
170
+ SpotEvent,
171
+ ExecutionEvent,
172
+ ReadyEvent,
173
+ ReconnectedEvent,
174
+ )
175
+
176
+ # Price updates
177
+ @client.on(SpotEvent, symbol_id=270)
178
+ async def on_spot(event: SpotEvent):
179
+ print(f"{event.bid}/{event.ask}")
180
+
181
+ # Order executions
182
+ @client.on(ExecutionEvent, account_id=account_id)
183
+ async def on_execution(event: ExecutionEvent):
184
+ print(f"Order {event.order_id}: {event.execution_type}")
185
+
186
+ # Account ready (fires on initial auth and after reconnection)
187
+ @client.on(ReadyEvent)
188
+ async def on_ready(event: ReadyEvent):
189
+ # Set up subscriptions here
190
+ await client.market_data.subscribe_spots(event.account_id, symbols)
191
+
192
+ # Connection restored
193
+ @client.on(ReconnectedEvent)
194
+ async def on_reconnected(event: ReconnectedEvent):
195
+ print(f"Reconnected, restored accounts: {event.restored_accounts}")
196
+ ```
197
+
198
+ ### Symbols
199
+
200
+ ```python
201
+ # List all symbols
202
+ symbols = await client.symbols.list_all(account_id)
203
+
204
+ # Search by name
205
+ results = await client.symbols.search(account_id, "EUR")
206
+
207
+ # Get specific symbol
208
+ symbol = await client.symbols.get_by_id(account_id, symbol_id)
209
+ ```
210
+
211
+ ### Account Information
212
+
213
+ ```python
214
+ # Get account details
215
+ account = await client.accounts.get_trader(account_id)
216
+ print(f"Balance: {account.balance}")
217
+ ```
218
+
219
+ ## Automatic Reconnection
220
+
221
+ The client automatically handles connection drops:
222
+
223
+ 1. Reconnects with exponential backoff
224
+ 2. Re-authenticates the app and all accounts
225
+ 3. Emits `ReadyEvent` for each restored account (for resubscribing to market data)
226
+ 4. Emits `ReconnectedEvent` with summary of restored/failed accounts
227
+
228
+ Use `ReadyEvent` to set up subscriptions that persist across reconnections.
229
+
230
+ ## Configuration
231
+
232
+ ```python
233
+ config = ClientConfig(
234
+ client_id="your_client_id",
235
+ client_secret="your_client_secret",
236
+
237
+ # Connection settings
238
+ host="live.ctraderapi.com", # or "demo.ctraderapi.com"
239
+ port=5035,
240
+ use_ssl=True,
241
+
242
+ # Timeouts
243
+ heartbeat_interval=10.0,
244
+ heartbeat_timeout=30.0, # Or 0 to disable server heartbeat checks
245
+ request_timeout=30.0,
246
+
247
+ # Reconnection
248
+ reconnect_attempts=5,
249
+ reconnect_min_wait=1.0,
250
+ reconnect_max_wait=60.0,
251
+ )
252
+ ```
@@ -0,0 +1,43 @@
1
+ ctrader_api_client/__init__.py,sha256=4YAr1TKuOryIhDumTS5iKwRAc-BwxgxFtr6HkOczCBY,1437
2
+ ctrader_api_client/client.py,sha256=oS3J1YiueswXbdKJ9iAdDdtu7zQNqA1RQIX7I_NBX7A,14474
3
+ ctrader_api_client/config.py,sha256=AvJLWBgTKqRcOGy6NLE28wtcAZzbA_PjMymHyhBBB9U,1845
4
+ ctrader_api_client/enums.py,sha256=r57VZkvjKYXH-ff3V7xTAZAzGi7rbLzoF2Fh7TPVY7A,2774
5
+ ctrader_api_client/exceptions.py,sha256=C4k79e9v3Xl-h1avlho6aY8xm3GAyasnvqnqGy8tzHw,7828
6
+ ctrader_api_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ ctrader_api_client/_internal/__init__.py,sha256=3uiL23pBLEx2Xl_ejhHQBnWkfF53XQYgF49cWFGnsgM,511
8
+ ctrader_api_client/_internal/messages.py,sha256=Z4p2LXSTS3s8eeLGlRU2EuMoFqmGLxKP3jH8-m_1FoM,15394
9
+ ctrader_api_client/_internal/serialization.py,sha256=6YvdxOAAZmqtw13KcJuVVA3qeKvbKRm1fsLFOD-aPzM,2473
10
+ ctrader_api_client/_internal/proto/OpenApiCommonMessages.py,sha256=cjga95e4C_OSy8bCm78tJZ6i9Wu9OSsFlFRpnNhjZpM,1388
11
+ ctrader_api_client/_internal/proto/OpenApiCommonModelMessages.py,sha256=NywbMSf7KNJaJSv41ymB1_JgrB0STVh2yeFEekg6-GI,706
12
+ ctrader_api_client/_internal/proto/OpenApiMessages.py,sha256=6aMnUmY6CYrtmMNvGTG8qPsijh2D5hDYo2R3Csja1R4,39293
13
+ ctrader_api_client/_internal/proto/OpenApiModelMessages.py,sha256=KE-k7H9-UDsh7cA8bQF2EZrloUhDkxHRRtEtorWqjnA,27125
14
+ ctrader_api_client/_internal/proto/__init__.py,sha256=-wZhbTn18bgtwOrBjI3EZfckAdX3WlAL5NTad88RKxI,9413
15
+ ctrader_api_client/api/__init__.py,sha256=MrawYa778pN2YXPw92X6D7anIOLTfJmvT9xl0uxfTlM,562
16
+ ctrader_api_client/api/accounts.py,sha256=GTNwAqYHHvxlWc0iIUZSvka9Iqh4WswrVI9IIyuAs0k,1986
17
+ ctrader_api_client/api/market_data.py,sha256=fiyWjvkL1wqTBw5NllyrhBQ6tszoR_fqgfPrO5T-7-A,14325
18
+ ctrader_api_client/api/symbols.py,sha256=2GAB21kxSkcF-qcRxJOL9--pk0o9Ma6DZ2kv5xmzSig,5170
19
+ ctrader_api_client/api/trading.py,sha256=oiwymq2SUwtXxP4kbIu1E-SzLUkQjBmtKzfaOec9LAA,16282
20
+ ctrader_api_client/auth/__init__.py,sha256=ykxE1xPqJl9T3kOpU8a0UT0Tn107GqLGEOS_gqkou_0,287
21
+ ctrader_api_client/auth/credentials.py,sha256=diMXNy8hNci1eyhbkhGnUWNWB0pn18xtqQXc7_okdIU,2153
22
+ ctrader_api_client/auth/manager.py,sha256=r5kjSCjrAS2rQGW3wZAAOInijDJA0YLnGmXrrBX-6hE,18130
23
+ ctrader_api_client/connection/__init__.py,sha256=aHW0ahsLcW__P0KXCzfDL-pdM14IBeMiHKp2npjbo2Q,360
24
+ ctrader_api_client/connection/heartbeat.py,sha256=ASVysDtA0nsd3q57kNdpa8-C0x8o5omb-_evmQrKDck,4118
25
+ ctrader_api_client/connection/protocol.py,sha256=oufw1mDawyC_gO2Es3XYCwLZVAzFsRwG1-3UyYWCk1M,12802
26
+ ctrader_api_client/connection/transport.py,sha256=9zOqaXtPgWtjeNgxqgVHmd06ZMrAgG8jgRMjGy-j6rQ,3808
27
+ ctrader_api_client/events/__init__.py,sha256=kAfzhbFLjcJzCeuQOhc7dCXkj9W77KeoOzeDWj-hmVo,1403
28
+ ctrader_api_client/events/emitter.py,sha256=PwcxT4SLFf5zUFOMiGLhAq9qgOjIleVenH3m_fDT6Y0,8563
29
+ ctrader_api_client/events/router.py,sha256=h0GRF8ZX8PeJswoK1V90bq7iwxMO6-zjnYXgwO1-q8I,14940
30
+ ctrader_api_client/events/types.py,sha256=bEBGPn1TF2h-KJS3-LHuybrdxZJiRYxL-2S17b9aaWM,9368
31
+ ctrader_api_client/models/__init__.py,sha256=I4Xdz_8mCvv_nxSwFJQPOQoyBPlHYnVtsWNEPtupqOE,1178
32
+ ctrader_api_client/models/_base.py,sha256=YQTsIhu7HwQd-fa2U-CaDgKZDBkasLY3BEcVGTMuLcE,410
33
+ ctrader_api_client/models/account.py,sha256=HuWFCH1CAdXMmnUmUIrSDfWhlk5huKF7dc6obor_qHg,6534
34
+ ctrader_api_client/models/deal.py,sha256=7Keh2bnPFm_HvHh-vLwGIG7b6TrTBc9ywrLa2epp2CU,8307
35
+ ctrader_api_client/models/market_data.py,sha256=PkCns7eVweq9aKFoSKCXmcIeTU3SWTyxUeUsoSOPVIY,5349
36
+ ctrader_api_client/models/order.py,sha256=bd9aDZexfVE_XRWFB5yYj2jGFuybzLXRt8tNE5xlz48,10044
37
+ ctrader_api_client/models/position.py,sha256=bppivlIRhQPmTOnj2J_R_61wVTePTTjR92VMZBQ-i7k,7431
38
+ ctrader_api_client/models/requests.py,sha256=OrxtF-cYi8rs3uT0lOzNLBBfrO5i-sqLjOayGInp0UI,10940
39
+ ctrader_api_client/models/symbol.py,sha256=lVNc-gXMo6kwQbpexiCJn7FKbDIN17K1bfxEID9r18A,6309
40
+ ctrader_api_client-0.1.0.dist-info/METADATA,sha256=x2wEm7W6DX0VBZoEwxcVADVqyCH29WfsjFLrKa8BoV4,6635
41
+ ctrader_api_client-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
42
+ ctrader_api_client-0.1.0.dist-info/licenses/LICENSE,sha256=_ZY-NhfjiEbAnrCG6drSXwAPkbibV3NgK68KC95gl6I,1076
43
+ ctrader_api_client-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elio Anthony Chukri
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.