### Install Python SDK Source: https://help.ctrader.com/open-api/python-SDK/python-sdk-index Install the Python SDK using pip. This command should be run within your project environment. ```bash pip install ctrader-open-api ``` -------------------------------- ### Install .NET SDK using NuGet Package Manager Source: https://help.ctrader.com/open-api/net_SDK/net-sdk-index Use this command in the NuGet Package Manager console to install the cTrader Open API .NET SDK. ```powershell Install-Package cTrader.OpenAPI.Net ``` -------------------------------- ### Example JSON String for ProtoOAApplicationAuthReq Source: https://help.ctrader.com/open-api/sending-receiving-json This is an example of a valid JSON string representing the ProtoOAApplicationAuthReq message. ```json "{\"clientMsgId\": \"cm_id_2\", \"payloadType\": 2100, \"payload\": {\"clientId\": \"34Rsd_T098asHkl\",\"clientSecret\": \"validClientSecret\"}}" ``` -------------------------------- ### Refresh Access Token via Protobuf (Python) Source: https://help.ctrader.com/open-api/account-authentication This Python example demonstrates how to refresh an access token using Protobuf messages. ```APIDOC ## refreshToken (Python) ### Description This method allows you to obtain a new access token and refresh token using a Python client library. ### Method refreshToken (client method) ### Parameters - **refreshToken** (string) - Required - Your current refresh token. ### Returns - **newToken** (object) - An object containing the new access and refresh tokens. ### Code Example ```python newToken = auth.refreshToken("your_refresh_token") ``` ``` -------------------------------- ### Refresh Access Token via Protobuf (C#) Source: https://help.ctrader.com/open-api/account-authentication This C# example demonstrates how to refresh an access token using Protobuf messages, specifically sending a ProtoOARefreshTokenReq and handling the ProtoOARefreshTokenRes. ```APIDOC ## ProtoOARefreshTokenReq / ProtoOARefreshTokenRes (C#) ### Description This method allows you to obtain a new access token and refresh token by sending a Protobuf message. ### Method SendMessage (client method) ### Message Sent `ProtoOARefreshTokenReq` ### Request Body Fields - **refreshToken** (string) - Required - Your current refresh token. ### Response Message `ProtoOARefreshTokenRes` ### Response Fields - **AccessToken** (string) - The new access token. - **RefreshToken** (string) - The new refresh token. - **ExpiresIn** (long) - The expiration time of the access token in milliseconds. - **TokenType** (string) - The type of the token (e.g., 'Bearer'). ### Code Example ```csharp _disposables.Add(_client.OfType().Subscribe(OnRefreshTokenResponse)); private static void OnRefreshTokenResponse(ProtoOARefreshTokenRes response) { _token = new Token { AccessToken = response.AccessToken, RefreshToken = response.RefreshToken, ExpiresIn = DateTimeOffset.FromUnixTimeMilliseconds(response.ExpiresIn), TokenType = response.TokenType, }; } var refreshTokenReq = new ProtoOARefreshTokenReq { refreshToken = "{your_refresh_token}", // Add your refresh token here }; await _client.SendMessage(refreshTokenReq); ``` ``` -------------------------------- ### Refresh Access Token using refreshToken (Python) Source: https://help.ctrader.com/open-api/account-authentication?q= This Python example shows how to call the refreshToken method with your existing refresh token to obtain a new access token. ```python newToken = auth.refreshToken("refresh_Token") ``` -------------------------------- ### Get Access Token using cURL Source: https://help.ctrader.com/open-api/account-authentication?q= Use this cURL command to perform a GET request to the apps/token endpoint to obtain an access token. Ensure all required query parameters are correctly provided. ```bash curl -X GET 'https://openapi.ctrader.com/apps/token?grant_type=authorization_code&code=0ssdgds98as9_QSF56FVC_22dfdf&redirect_uri=https://spotware.com&client_id=5430012&client_secret=012sds23dlkjQsd' -H 'Accept: application/json' -H 'Content-Type: application/json' ``` -------------------------------- ### ProtoOADealOffsetListReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting sets of Deals that were offset by a specific Deal and that are offsetting the Deal. ```APIDOC ## ProtoOADealOffsetListReq ### Description Request for getting sets of Deals that were offset by a specific Deal and that are offsetting the Deal. ### Parameters #### Request Body - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **dealId** (int64) - Required - The unique ID of the Deal. ``` -------------------------------- ### Refresh Access Token via Protobuf Source: https://help.ctrader.com/open-api/account-authentication?q= This section provides examples of how to refresh an access token using Protobuf messages in C# and Python. ```APIDOC ## ProtoOARefreshTokenReq / ProtoOARefreshTokenRes ### Description Use the `ProtoOARefreshTokenReq` message to request new tokens and receive them in the `ProtoOARefreshTokenRes` message. ### C# Example ```csharp _disposables.Add(_client.OfType().Subscribe(OnRefreshTokenResponse)); private static void OnRefreshTokenResponse(ProtoOARefreshTokenRes response) { _token = new Token { AccessToken = response.AccessToken, RefreshToken = response.RefreshToken, ExpiresIn = DateTimeOffset.FromUnixTimeMilliseconds(response.ExpiresIn), TokenType = response.TokenType, }; } var refreshTokenReq = new ProtoOARefreshTokenReq { refreshToken = "{your_refresh_token}", // Add your refresh token here }; await _client.SendMessage(refreshTokenReq); ``` ### Python Example ```python newToken = auth.refreshToken("refresh_Token") ``` ``` -------------------------------- ### ProtoOADealOffsetListReq Source: https://help.ctrader.com/open-api/messages Request for getting sets of Deals that were offset by a specific Deal and that are offsetting the Deal. ```APIDOC ## ProtoOADealOffsetListReq ### Description Request for getting sets of Deals that were offset by a specific Deal and that are offsetting the Deal. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **dealId** (int64) - Required - The unique ID of the Deal. ``` -------------------------------- ### Protocol Buffers Message Definition (.proto file) Source: https://help.ctrader.com/open-api/protocol-buffers-json?q= This example defines a Person message using Protocol Buffers version 2 syntax. It includes basic fields, an enum, a nested message, and a repeated field. ```protobuf message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; } ``` -------------------------------- ### Get Conversion Symbols (C#) Source: https://help.ctrader.com/open-api/symbol-rate-conversion?q= This C# code snippet demonstrates how to retrieve a list of symbols that can be used for conversion between two specified assets. It utilizes the `GetConversionSymbols` method, which sends a `ProtoOASymbolsForConversionReq` message and processes the `ProtoOASymbolsForConversionRes` response. ```APIDOC ## GetConversionSymbols ### Description Retrieves a list of `ProtoOALightSymbol` objects that represent possible conversion paths between two assets. ### Method This is a client-side SDK method, not a direct HTTP endpoint. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp var symbolsResult = await GetConversionSymbols(accountId, isLive, baseAssetId, quoteAssetId); ``` ### Response #### Success Response - **ProtoOALightSymbol[]**: An array of `ProtoOALightSymbol` objects. #### Response Example ```json // Example response structure (conceptual) [ { "symbolId": 123, "baseAssetId": 456, "quoteAssetId": 789, ... }, { "symbolId": 456, "baseAssetId": 789, "quoteAssetId": 123, ... } ] ``` ``` -------------------------------- ### ProtoOAOrderDetailsReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting Order and its related Deals. ```APIDOC ## ProtoOAOrderDetailsReq ### Description Request for getting Order and its related Deals. ### Parameters #### Request Body - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **orderId** (int64) - Required - The unique ID of the Order. ``` -------------------------------- ### Construct Authorization URI Source: https://help.ctrader.com/open-api/account-authentication?q= Build this URI to initiate the user authorization flow. Ensure all required parameters are correctly populated. ```url https://id.ctrader.com/my/settings/openapi/grantingaccess/?client_id={clientId}&redirect_uri={your_redirectURI}&scope={scope}&product=web ``` -------------------------------- ### ProtoOAOrderDetailsReq Source: https://help.ctrader.com/open-api/messages Request for getting Order and its related Deals. ```APIDOC ## ProtoOAOrderDetailsReq ### Description Request for getting Order and its related Deals. ### Method GET (Assumed, as it's a request to retrieve data) ### Endpoint /messages/orders/{orderId} (Assumed, based on context) ### Parameters #### Query Parameters - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. #### Path Parameters - **orderId** (int64) - Required - The unique ID of the Order. ``` -------------------------------- ### ProtoOATraderReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting data of a Trader's Account. ```APIDOC ## ProtoOATraderReq ### Description Request for getting data of Trader's Account. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. ``` -------------------------------- ### ProtoOADealListReq Source: https://help.ctrader.com/open-api/messages Request for getting historical deal data for a trader. ```APIDOC ## ProtoOADealListReq ### Description Request for getting Trader's deals historical data (execution details). ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **fromTimestamp** (int64) - Optional - The Unix time from which the search starts >=0 (1st Jan 1970). - **toTimestamp** (int64) - Optional - The Unix time where to stop searching <= 2147483646000 (19th Jan 2038). - **maxRows** (int32) - Optional - The maximum number of the deals to return. ``` -------------------------------- ### Python Account Authentication Flow Source: https://help.ctrader.com/open-api/account-authentication?q= This Python code demonstrates how to authenticate your application and accounts using ProtoBuf messages. It includes callbacks for connection, disconnection, message reception, and errors. Replace placeholders with your actual credentials and tokens. ```python currentAccountId = None client = Client(EndPoints.PROTOBUF_LIVE_HOST if hostType.lower() == "live" else EndPoints.PROTOBUF_DEMO_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol) def connected(client): # Callback for client connection print("\nConnected") request = ProtoOAApplicationAuthReq() request.clientId = appClientId request.clientSecret = appClientSecret deferred = client.send(request) def disconnected(client, reason): # Callback for client disconnection print("\nDisconnected: ", reason) def onMessageReceived(client, message): # Callback for receiving all messages global currentAccountId if message.payloadType in [ProtoOASubscribeSpotsRes().payloadType, ProtoOAAccountLogoutRes().payloadType, ProtoHeartbeatEvent().payloadType]: return elif message.payloadType == ProtoOAApplicationAuthRes().payloadType: print("API Application authorized\n") if currentAccountId is not None: sendProtoOAAccountAuthReq() return accountListReq = ProtoOAGetAccountListByAccessTokenReq() accountListReq.accessToken = accessToken deferred = client.send(accountListReq) elif message.payloadType == ProtoOAGetAccountListByAccessTokenRes().payloadType: protoOAGetAccountListByAccessTokenRes = Protobuf.extract(message) currentAccountId = int(protoOAGetAccountListByAccessTokenRes.ctidTraderAccount[0].ctidTraderAccountId) accountAuthReq = ProtoOAAccountAuthReq() accountAuthReq.ctidTraderAccountId = currentAccountId accountAuthReq.accessToken = accessToken deferred = client.send(accountAuthReq) elif message.payloadType == ProtoOAAccountAuthRes().payloadType: protoOAAccountAuthRes = Protobuf.extract(message) print(f"Account {protoOAAccountAuthRes.ctidTraderAccountId} has been authorized\n") print("This acccount will be used for all future requests\n") else: print("Message received: \n", Protobuf.extract(message)) reactor.callLater(3, callable=executeUserCommand) def onError(failure): # Call back for errors print("Message Error: ", failure) reactor.callLater(3, callable=executeUserCommand) ``` -------------------------------- ### ProtoOAOrderListReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting Trader's orders filtered by timestamp. ```APIDOC ## ProtoOAOrderListReq ### Description Request for getting Trader's orders filtered by timestamp. ### Parameters #### Query Parameters - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **fromTimestamp** (int64) - Optional - The Unix time from which the search starts >=0 (1st Jan 1970). - **toTimestamp** (int64) - Optional - The Unix time where to stop searching <= 2147483646000 (19th Jan 2038). ``` -------------------------------- ### Connect WebSocket and Parse Protobuf in C# Source: https://help.ctrader.com/open-api/sending-receiving-protobuf Establishes a WebSocket connection, configures client settings, and subscribes to message events. It parses incoming binary messages into `ProtoMessage` objects using `ProtoMessage.Parser.ParseFrom()`. ```csharp private async Task ConnectWebSocket() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(7, 2); defaultInterpolatedStringHandler.AppendLiteral("wss://"); defaultInterpolatedStringHandler.AppendFormatted(Host); defaultInterpolatedStringHandler.AppendLiteral(":"); defaultInterpolatedStringHandler.AppendFormatted(Port); Uri url = new Uri(defaultInterpolatedStringHandler.ToStringAndClear()); _websocketClient = new WebsocketClient(url, () => new ClientWebSocket()) { IsTextMessageConversionEnabled = false, ReconnectTimeout = null, IsReconnectionEnabled = false, ErrorReconnectTimeout = null }; _webSocketMessageReceivedDisposable = _websocketClient.MessageReceived.Select((ResponseMessage msg) => ProtoMessage.Parser.ParseFrom(msg.Binary)).Subscribe(new Action(OnNext)); _webSocketDisconnectionHappenedDisposable = _websocketClient.DisconnectionHappened.Subscribe(new Action(OnWebSocketDisconnectionHappened)); await _websocketClient.StartOrFail(); } ``` -------------------------------- ### Subscribe to Spot Events in C# Source: https://help.ctrader.com/open-api/symbol-rate-conversion This C# method subscribes to spot events for a given account and a list of symbol IDs. It returns a task that completes when the subscription response is received. ```csharp public Task SubscribeToSpots(long accountId, bool isLive, params long[] symbolIds) { var client = GetClient(isLive); var taskCompletionSource = new TaskCompletionSource(); IDisposable disposable = null; disposable = client.OfType().Where(response => response.CtidTraderAccountId == accountId).Subscribe(response => { taskCompletionSource.SetResult(response); disposable?.Dispose(); }); var requestMessage = new ProtoOASubscribeSpotsReq { CtidTraderAccountId = accountId, }; requestMessage.SymbolId.AddRange(symbolIds); EnqueueMessage(requestMessage, ProtoOAPayloadType.ProtoOaSubscribeSpotsReq, client); return taskCompletionSource.Task; } ``` -------------------------------- ### ProtoOAGetTrendbarsReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting historical trend bars for a specific symbol. ```APIDOC ## ProtoOAGetTrendbarsReq ### Description Request for getting historical trend bars for the symbol. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **fromTimestamp** (int64) - Optional - The Unix time in milliseconds from which the search starts. Must be bigger or equal to zero (1st Jan 1970). - **toTimestamp** (int64) - Optional - The Unix time in milliseconds of finishing the search. Smaller or equal to 2147483646000 (19th Jan 2038). - **period** (ProtoOATrendbarPeriod) - Required - Specifies period of trend bar series (e.g. M1, M10, etc.). - **symbolId** (int64) - Required - Unique identifier of the Symbol in cTrader platform. - **count** (uint32) - Optional - Limit number of trend bars in response back from toTimestamp. ``` -------------------------------- ### Handling Spot Events (C#) Source: https://help.ctrader.com/open-api/symbol-rate-conversion?q= Handles incoming ProtoOASpotEvent messages to update symbol bid and ask prices. ```APIDOC ## Handling Spot Events (C#) ### Description Subscribes to `ProtoOASpotEvent` and processes incoming events to update the bid and ask prices of the corresponding symbols. ### Method ```csharp client.OfType().Subscribe(OnSpotEvent); ``` ### Callback Method ```csharp private void OnSpotEvent(ProtoOASpotEvent spotEvent) ``` ### Logic - Finds the symbol by `spotEvent.SymbolId`. - Updates the symbol's `Bid` and `Ask` properties if new values are available and different from the current ones. - Uses `GetPriceFromRelative` to convert relative price data. ``` -------------------------------- ### ProtoOAGetTickDataReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting historical tick data for a specific symbol. ```APIDOC ## ProtoOAGetTickDataReq ### Description Request for getting historical tick data for the symbol. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **symbolId** (int64) - Required - Unique identifier of the Symbol in cTrader platform. - **type** (ProtoOAQuoteType) - Required - Bid/Ask (½). - **fromTimestamp** (int64) - Optional - The Unix time in milliseconds of starting the search. Must be bigger or equal to zero (1st Jan 1970). - **toTimestamp** (int64) - Optional - The Unix time in milliseconds of finishing the search. <= 2147483646000 (19th Jan 2038). ``` -------------------------------- ### ProtoOAOrderListReq Source: https://help.ctrader.com/open-api/messages Request for getting a trader's orders filtered by timestamp. ```APIDOC ## ProtoOAOrderListReq ### Description Request for getting Trader's orders filtered by timestamp. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **fromTimestamp** (int64) - Optional - The Unix time from which the search starts >=0 (1st Jan 1970). - **toTimestamp** (int64) - Optional - The Unix time where to stop searching <= 2147483646000 (19th Jan 2038). ``` -------------------------------- ### Application and Account Authentication Source: https://help.ctrader.com/open-api/account-authentication?q= This snippet demonstrates how to authenticate your application and then authenticate a specific trading account using ProtoBuf messages. ```APIDOC ## Application and Account Authentication ### Description This section details the process of sending `ProtoOAApplicationAuthReq`, `ProtoOAGetAccountListByAccessTokenReq`, and `ProtoOAAccountAuthReq` messages to authenticate your application and trading accounts. ### C# Example ```csharp var _client = new OpenClient(host, ApiInfo.Port, TimeSpan.FromSeconds(10), useWebSocket: false); var applicationAuthReq = new ProtoOAApplicationAuthReq { ClientId = "{your_client_id}", // Add your client ID here ClientSecret = "{your_app_secret}", // Add your app secret here }; await _client.SendMessage(applicationAuthReq); await Task.Delay(5000); var getAccountListByAccessToken = new ProtoOAGetAccountListByAccessTokenReq { AccessToken = "{access_token}" // Add your access token here } var accountAuthReq = new ProtoOAAccountAuthReq { ctidTraderAccountId = {account_id}, // Add the ctidTraderAccountId of the account you want to authorize here AccessToken = "{access_token}" // Add your access token here }; await _client.SendMessage(accountAuthReq); ``` ### Python Example ```python currentAccountId = None client = Client(EndPoints.PROTOBUF_LIVE_HOST if hostType.lower() == "live" else EndPoints.PROTOBUF_DEMO_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol) def connected(client): # Callback for client connection print("\nConnected") request = ProtoOAApplicationAuthReq() request.clientId = appClientId request.clientSecret = appClientSecret deferred = client.send(request) def disconnected(client, reason): # Callback for client disconnection print("\nDisconnected: ", reason) def onMessageReceived(client, message): # Callback for receiving all messages global currentAccountId if message.payloadType in [ProtoOASubscribeSpotsRes().payloadType, ProtoOAAccountLogoutRes().payloadType, ProtoHeartbeatEvent().payloadType]: return elif message.payloadType == ProtoOAApplicationAuthRes().payloadType: print("API Application authorized\n") if currentAccountId is not None: sendProtoOAAccountAuthReq() return accountListReq = ProtoOAGetAccountListByAccessTokenReq() accountListReq.accessToken = accessToken deferred = client.send(accountListReq) elif message.payloadType == ProtoOAGetAccountListByAccessTokenRes().payloadType: protoOAGetAccountListByAccessTokenRes = Protobuf.extract(message) currentAccountId = int(protoOAGetAccountListByAccessTokenRes.ctidTraderAccount[0].ctidTraderAccountId) accountAuthReq = ProtoOAAccountAuthReq() accountAuthReq.ctidTraderAccountId = currentAccountId accountAuthReq.accessToken = accessToken deferred = client.send(accountAuthReq) elif message.payloadType == ProtoOAAccountAuthRes().payloadType: protoOAAccountAuthRes = Protobuf.extract(message) print(f"Account {protoOAAccountAuthRes.ctidTraderAccountId} has been authorized\n") print("This acccount will be used for all future requests\n") else: print("Message received: \n", Protobuf.extract(message)) reactor.callLater(3, callable=executeUserCommand) def onError(failure): # Call back for errors print("Message Error: ", failure) reactor.callLater(3, callable=executeUserCommand) ``` ``` -------------------------------- ### ProtoOAGetPositionUnrealizedPnLReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting trader's positions' unrealized PnLs. ```APIDOC ## ProtoOAGetPositionUnrealizedPnLReq ### Description Request for getting trader's positions' unrealized PnLs. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - The unique identifier of the trader's account in cTrader platform. ``` -------------------------------- ### SubscribeToSpots (C#) Source: https://help.ctrader.com/open-api/symbol-rate-conversion?q= Subscribes to ProtoOASpotEvent for specified symbol IDs to track conversion chain events. ```APIDOC ## SubscribeToSpots (C#) ### Description Subscribes to `ProtoOASpotEvent` for a given account and a list of symbol IDs to monitor conversion chain progress. ### Method Signature ```csharp public Task SubscribeToSpots(long accountId, bool isLive, params long[] symbolIds) ``` ### Parameters - `accountId` (long): The ID of the cTrader account. - `isLive` (bool): Specifies if the subscription is for a live or demo account. - `symbolIds` (params long[]): A variable number of symbol IDs to subscribe to. ### Returns A `Task` that resolves to `ProtoOASubscribeSpotsRes` upon successful subscription. ``` -------------------------------- ### ProtoOAGetDynamicLeverageByIDReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting a dynamic leverage entity referenced in ProtoOASymbol. ```APIDOC ## ProtoOAGetDynamicLeverageByIDReq ### Description Request for getting a dynamic leverage entity referenced in ProtoOASymbol. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **leverageId** (int64) - Required - ``` -------------------------------- ### ProtoOASymbolsForConversionReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting a conversion chain between two assets when no direct quote is available. ```APIDOC ## ProtoOASymbolsForConversionReq ### Description Request for getting a conversion chain between two assets that consists of several symbols. Use when no direct quote is available. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **firstAssetId** (int64) - Required - The ID of the firs asset in the conversation chain. e.g.: for EUR/USD the firstAssetId is EUR ID and lastAssetId is USD ID. - **lastAssetId** (int64) - Required - The ID of the last asset in the conversation chain. e.g.: for EUR/USD the firstAssetId is EUR ID and lastAssetId is USD ID. ``` -------------------------------- ### ProtoOASubscribeSpotsReq Source: https://help.ctrader.com/open-api/messages Request to subscribe for spot events for a specified symbol. After subscription, the first event will be a technical ProtoOASpotEvent with the latest price. ```APIDOC ## ProtoOASubscribeSpotsReq Request for subscribing on spot events of the specified symbol. After successful subscription you'll receive technical ProtoOASpotEvent with latest price, after which you'll start receiving updates on prices via consequent ProtoOASpotEvents. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **symbolId** (RepeatedField) - Repeated - Unique identifier of the Symbol in cTrader platform. - **subscribeToSpotTimestamp** (bool) - Optional - If TRUE you will also receive the timestamp in ProtoOASpotEvent. ``` -------------------------------- ### TCP Connection Implementation (C#) Source: https://help.ctrader.com/open-api/connection This is the internal implementation for establishing a TCP connection, including SSL authentication. It runs the read loop in a separate task. ```csharp private async Task ConnectTcp() { _tcpClient = new TcpClient { LingerState = new LingerOption(enable: true, 10) }; await _tcpClient.ConnectAsync(Host, Port).ConfigureAwait(continueOnCapturedContext: false); _sslStream = new SslStream(_tcpClient.GetStream(), leaveInnerStreamOpen: false); await _sslStream.AuthenticateAsClientAsync(Host).ConfigureAwait(continueOnCapturedContext: false); Task.Run(delegate { ReadTcp(_cancellationTokenSource.Token); }); } ``` -------------------------------- ### WebSocket Connection Implementation (C#) Source: https://help.ctrader.com/open-api/connection This is the internal implementation for establishing a WebSocket connection, including setting up message handling and reconnection logic. Note that the Python SDK does not support WebSockets. ```csharp private async Task ConnectWebScoket() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(7, 2); defaultInterpolatedStringHandler.AppendLiteral("wss://"); defaultInterpolatedStringHandler.AppendFormatted(Host); defaultInterpolatedStringHandler.AppendLiteral(":"); defaultInterpolatedStringHandler.AppendFormatted(Port); Uri url = new Uri(defaultInterpolatedStringHandler.ToStringAndClear()); _websocketClient = new WebsocketClient(url, () => new ClientWebSocket()) { IsTextMessageConversionEnabled = false, ReconnectTimeout = null, IsReconnectionEnabled = false, ErrorReconnectTimeout = null }; _webSocketMessageReceivedDisposable = _websocketClient.MessageReceived.Select((ResponseMessage msg) => ProtoMessage.Parser.ParseFrom(msg.Binary)).Subscribe(new Action(OnNext)); _webSocketDisconnectionHappenedDisposable = _websocketClient.DisconnectionHappened.Subscribe(new Action(OnWebSocketDisconnectionHappened)); await _websocketClient.StartOrFail(); } ``` -------------------------------- ### ProtoOAReconcileReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting Trader's current open positions and pending orders data. ```APIDOC ## ProtoOAReconcileReq ### Description Request for getting Trader's current open positions and pending orders data. ### Parameters #### Query Parameters - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **returnProtectionOrders** (bool) - Optional - If TRUE, then current protection orders are returned separately, otherwise you can use position.stopLoss and position.takeProfit fields. ``` -------------------------------- ### Connect to cTrader Open API via WebSocket (C#) Source: https://help.ctrader.com/open-api/connection?q= This snippet demonstrates establishing a WebSocket connection to the cTrader Open API. The host and port remain the same as for TCP connections. The `OpenClient.Connect()` method internally calls `OpenClient.ConnectWebSocket()`. ```csharp _client = new OpenClient("live1.p.ctrader.com", 5035, TimeSpan.FromSeconds(10), useWebSocket: true); await _client.Connect() ``` ```csharp private async Task ConnectWebScoket() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(7, 2); defaultInterpolatedStringHandler.AppendLiteral("wss://"); defaultInterpolatedStringHandler.AppendFormatted(Host); defaultInterpolatedStringHandler.AppendLiteral(":"); defaultInterpolatedStringHandler.AppendFormatted(Port); Uri url = new Uri(defaultInterpolatedStringHandler.ToStringAndClear()); _websocketClient = new WebsocketClient(url, () => new ClientWebSocket()) { IsTextMessageConversionEnabled = false, ReconnectTimeout = null, IsReconnectionEnabled = false, ErrorReconnectTimeout = null }; _webSocketMessageReceivedDisposable = _websocketClient.MessageReceived.Select((ResponseMessage msg) => ProtoMessage.Parser.ParseFrom(msg.Binary)).Subscribe(new Action(OnNext)); _webSocketDisconnectionHappenedDisposable = _websocketClient.DisconnectionHappened.Subscribe(new Action(OnWebSocketDisconnectionHappened)); await _websocketClient.StartOrFail(); } ``` -------------------------------- ### ProtoOAReconcileReq Source: https://help.ctrader.com/open-api/messages Request for getting a trader's current open positions and pending orders data. ```APIDOC ## ProtoOAReconcileReq ### Description Request for getting Trader's current open positions and pending orders data. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **returnProtectionOrders** (bool) - Optional - If TRUE, then current protection orders are returned separately, otherwise you can use position.stopLoss and position.takeProfit fields. ``` -------------------------------- ### ProtoOAGetCtidProfileByTokenReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting details of a Trader's profile, limited due to GDPR requirements. ```APIDOC ## ProtoOAGetCtidProfileByTokenReq ### Description Request for getting details of Trader's profile. Limited due to GDRP requirements. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - - **accessToken** (string) - Required - The Access Token issued for providing access to the Trader's Account. ``` -------------------------------- ### ProtoOAGetAccountListByAccessTokenReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting the list of granted trader's accounts associated with an access token. ```APIDOC ## ProtoOAGetAccountListByAccessTokenReq ### Description Request for getting the list of granted trader's account for the access token. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - - **accessToken** (string) - Required - The Access Token issued for providing access to the Trader's Account. ``` -------------------------------- ### ProtoOASubscribeSpotsReq Source: https://help.ctrader.com/open-api/messages?q= Request to subscribe to spot events for specified symbols. After subscription, initial spot prices are sent, followed by updates. ```APIDOC ## ProtoOASubscribeSpotsReq ### Description Request for subscribing on spot events of the specified symbol. After successful subscription you'll receive technical ProtoOASpotEvent with latest price, after which you'll start receiving updates on prices via consequent ProtoOASpotEvents. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **symbolId** (RepeatedField) - Repeated - Unique identifier of the Symbol in cTrader platform. - **subscribeToSpotTimestamp** (bool) - Optional - If TRUE you will also receive the timestamp in ProtoOASpotEvent. ``` -------------------------------- ### ProtoOAExpectedMarginReq Source: https://help.ctrader.com/open-api/messages?q= Request for getting the margin estimate according to leverage profiles. This can be used before sending a new order request. ```APIDOC ## ProtoOAExpectedMarginReq ### Description Request for getting the margin estimate according to leverage profiles. Can be used before sending a new order request. This doesn't consider ACCORDING_TO_GSL margin calculation type, as this calculation is trivial: usedMargin = (VWAP price of the position - GSL price) * volume * Quote2Deposit. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **symbolId** (int64) - Required - Unique identifier of the Symbol in cTrader platform. - **volume** (RepeatedField) - Repeated - Volume represented in 0.01 of a unit (e.g. 1000 in protocol means 10.00 units). ``` -------------------------------- ### ProtoOAGetDynamicLeverageByIDReq Source: https://help.ctrader.com/open-api/messages Request for retrieving a dynamic leverage entity by its ID. This is used in conjunction with ProtoOASymbol to get leverage details. ```APIDOC ## ProtoOAGetDynamicLeverageByIDReq ### Description Request for getting a dynamic leverage entity referenced in ProtoOASymbol. ### Parameters #### Query Parameters - **leverageId** (int64) - Required - Identifier for the leverage. - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. ``` -------------------------------- ### Establish TCP Connection (Python) Source: https://help.ctrader.com/open-api/connection Initializes a TCP connection to the cTrader Open API. The Python Open API client automatically attempts to establish a connection upon initialization. ```APIDOC ## Establish TCP Connection (Python) ### Description Initializes a TCP connection to the cTrader Open API. The Python Open API client automatically attempts to establish a connection upon initialization. ### Method ```python client = Client("live1.p.ctrader.com", 5035, TcpProtocol) ``` ``` -------------------------------- ### Handling Spot Events (Python) Source: https://help.ctrader.com/open-api/symbol-rate-conversion?q= Adds logic to the message receiving callback to handle ProtoOASpotEvent messages. ```APIDOC ## Handling Spot Events (Python) ### Description Modifies the `onMessageReceived` callback to identify and process `ProtoOASpotEvent` messages by extracting the event data and passing it to the `onSpotEvent` handler. ### Logic ```python elif message.paloadType == ProtoOASpotEvent().payloadType: ProtoOASpotEvent = Protobuf.extract(message) onSpotEvent(ProtoOASpotEvent) ``` ``` -------------------------------- ### ProtoOAExpectedMarginReq Source: https://help.ctrader.com/open-api/messages Request for getting the margin estimate according to leverage profiles, usable before sending a new order request. ```APIDOC ## ProtoOAExpectedMarginReq ### Description Request for getting the margin estimate according to leverage profiles. Can be used before sending a new order request. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **ctidTraderAccountId** (int64) - Required - Unique identifier of the trader's account. Used to match responses to trader's accounts. - **symbolId** (int64) - Required - Unique identifier of the Symbol in cTrader platform. - **volume** (RepeatedField) - Repeated - Volume represented in 0.01 of a unit (e.g. 1000 in protocol means 10.00 units). ``` -------------------------------- ### Establish WebSocket Connection (C#) Source: https://help.ctrader.com/open-api/connection Establishes a WebSocket connection to the cTrader Open API using the official SDK. The host and port are the same as for the TCP connection. ```APIDOC ## Establish WebSocket Connection (C#) ### Description Establishes a WebSocket connection to the cTrader Open API using the official SDK. The host and port are the same as for the TCP connection. ### Method ```csharp _client = new OpenClient("live1.p.ctrader.com", 5035, TimeSpan.FromSeconds(10), useWebSocket: true); await _client.Connect() ``` ### Internal Method Details ```csharp private async Task ConnectWebScoket() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(7, 2); defaultInterpolatedStringHandler.AppendLiteral("wss://"); defaultInterpolatedStringHandler.AppendFormatted(Host); defaultInterpolatedStringHandler.AppendLiteral(":"); defaultInterpolatedStringHandler.AppendFormatted(Port); Uri url = new Uri(defaultInterpolatedStringHandler.ToStringAndClear()); _websocketClient = new WebsocketClient(url, () => new ClientWebSocket()) { IsTextMessageConversionEnabled = false, ReconnectTimeout = null, IsReconnectionEnabled = false, ErrorReconnectTimeout = null }; _webSocketMessageReceivedDisposable = _websocketClient.MessageReceived.Select((ResponseMessage msg) => ProtoMessage.Parser.ParseFrom(msg.Binary)).Subscribe(new Action(OnNext)); _webSocketDisconnectionHappenedDisposable = _websocketClient.DisconnectionHappened.Subscribe(new Action(OnWebSocketDisconnectionHappened)); await _websocketClient.StartOrFail(); } ``` ``` -------------------------------- ### Get Live Bars Data Source: https://help.ctrader.com/open-api/symbol-data?q= Retrieve historical bars data or subscribe to live bars updates for a symbol. ```APIDOC ## Get Live Bars Data ### Description Retrieves historical bars data for a specified symbol and count, or subscribes to real-time live bars updates. ### Request Historical Bars Initialize and fill a `ProtoOAGetTrendbarsReq` message with: - `ctidTraderAccountId`: The trader account ID. - `symbolId`: The ID of the symbol. - `ProtoOATrendbarPeriod`: The period of the trendbars. - `count`: The number of trendbars to return. - `toTimestamp`: The end of the time range (Unix timestamp in milliseconds). - `fromTimestamp`: The start of the time range (Unix timestamp in milliseconds). ### Response Historical Bars Receives a `ProtoOAGetTrendbarsRes` message. Access the `trendbar` field for a list of trend bars. ### Data Transformation for Historical Bars To get the actual symbol price: 1. Get the low price of a trendbar and divide it by 100000. 2. Round the result to symbol digits. 3. To get high, open, and close prices, add the trendbar delta of each to the trendbar low price. 4. Divide each resulting number by 100000 and round to symbol digits. ### Subscribe to Live Bars 1. Initialize `ProtoOASubscribeLiveTrendbarReq` with `ctidTraderAccountId`, `ProtoOATrendbarPeriod`, and `symbolId`. 2. Initialize `ProtoOASubscribeSpotsReq`. 3. Send `ProtoOASubscribeSpotsReq` followed by `ProtoOASubscribeLiveTrendbarReq`. 4. Receive `ProtoOASubscribeSpotsRes` and `ProtoOASubscribeLiveTrenbarsRes`. 5. You will then receive `ProtoOASpotEvent` messages containing live trendbar data. ### Handling Live Bars Data When a `ProtoOASpotEvent` message is received, use its `trendbar` field for the last closed bar data. ### Data Transformation for Live Bars Same as for historical bars: divide by 100000 and round to symbol digits, using deltas for open, high, and close prices relative to the low price. ### Unsubscribe from Live Bars Send `ProtoOAUnsubscribeLiveTrendbarsReq` with `symbolId`, `period`, and `ctidTraderAccountId`. You will receive `ProtoOAUnsubscribeLiveTrenbarRes` upon success. Subscription to spot events will remain. ``` -------------------------------- ### ProtoOAVersionRes Source: https://help.ctrader.com/open-api/messages?q= Response containing the current version of the server application. ```APIDOC ## ProtoOAVersionRes ### Description Response to the ProtoOAVersionReq request. ### Fields - **payloadType** (ProtoOAPayloadType) - Optional - **version** (string) - Required - The current version of the server application. ```