Symbol Rate Conversion¶
Symbol rate conversion is an essential action if you want your application to include any sort of functionality related to P&L calculations.
Use Cases
Performing symbol rate conversions is necessary when calculating commissions, swaps, and dividends. Commissions, swaps, and dividends are typically denoted in USD. However, depending on your broker and your preferences, your account deposit currency may be in any other asset rather than USD. To accurately define commissions, swaps, and dividends, you would need to know the exchange rate between USD and your account deposit currency.
Conversion Chains
Think of the price of each individual symbol as a conversion rate between its base asset and quote asset. The task of attaining conversion rates becomes complicated if there are no symbols that directly link a given asset to another asset. Fortunately, the cTrader backend can automatically create conversion chains that act as the shortest possible conversion paths from one asset to another.
For example, if you want to convert EUR into NZD, and there is no EURNZD symbol on the trading server, cTrader will propose a chain that will serve as intermediate steps in the conversion process. Depending on symbol availability, such a chain could look like EURUSD-USDCAD-CADNZD, EURCFH-CFHUSD-USDNZD, or even EURCAD-CADUSD-USDCFH-CFHNZD.
To convert between two assets, your app needs to perform the following actions.
- Access the IDs of the assets that you want to convert between.
- Attain a conversion chain that includes one or more 'light' symbols.
- Subscribe to and handle spot events.
- Follow the conversion chain and return the final conversion rate.
Below, we explain each of these actions in detail.
Access Asset IDs¶
Asset IDs can be accessed directly as properties of the 'light' symbol entity (represented by the ProtoOALightSymbol
model message). In addition, you can attain the ID of an account deposit currency directly from its related ProtoOaTrader
entity.
Note that the below example only attain asset IDs for one symbol. To perform the same operation for multiple symbols, you would need to add a loop or use another suitable solution (e.g., a map()
method or equivalent).
Working With JSON
When working with JSON, you can still reuse the code below and other code snippets in this tutorial. However, make sure to replace the names of Proto...
classes with the names of your custom classes and make the necessary modifications to account for your preferred TCP/WebSocket client.
symbol
is a variable of the ProtoOALightSymbol
type. If you are using JSON, it can be of any custom type representing the ProtoOALightSymbol
message.
1 2 |
|
In the below example, we attain the ID of the deposit currency of the account
object which is of the ProtoOATrader
type.
1 |
|
symbol
is a variable representing a message of the ProtoOALightSymbol
type.
1 2 |
|
In the below example, we attain the ID of the deposit currency of the account
object which represents the ProtoOATrader
model message.
1 |
|
Attain a Conversion Chain¶
To attain a valid conversion chain, your app needs to send the ProtoOASymbolsForConversionReq
message with its firstAssetId
and lastAssetId
fields set to the IDs of the assets that you want to convert between. When you receive a response of the ProtoOASymbolsForConversionRes
type, store its repeated symbol
field inside a collection.
Here is how you can perform this action via the official SDKs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
1 2 3 4 5 |
|
Also add the following condition to the onMessageReceived
callback.
1 2 3 |
|
Note
We highly recommend attaining all conversion chain symbols for each asset when you first request and receive asset data from the server. Otherwise, you will have to send the ProtoOASymbolsForConversionReq
message every time you need to convert rates which, in some cases, may be several times per second.
Note
As ProtoOALightSymbol
entities do not contain any fields representing bid or ask prices, we highly recommend creating custom Symbol
classes or equivalent so you can easily create new symbols programmatically and update their properties when certain events are triggered. You will have to convert light symbols into objects of this class separately.
Subscribe to and Handle Spot Events¶
To follow the conversion chain from start to finish, you need to subscribe to the ProtoOASpotEvent
for all symbols included in the chain. This is done as follows via the official SDKs.
Before you perform the operations listed below, create a Symbol
class or equivalent so that you can easily create new symbols programmatically and update their properties when certain events are triggered. In the examples below, our Symbol
class includes ProtoOASymbol
and ProtoOALightSymbol
objects as properties.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
We also have to subscribe to spot events and handle them. In the example below, we access the symbols
collection that stores our light symbols. We find the symbol object whose ID matches the symbolId
field of the ProtoOASpotEvent
we have just received. Finally, we update the bid
and ask
properties of the symbol
using the GetPriceFromRelative
helper method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
We can use the following function to subscribe to ProtoOASpotEvent
for a particular symbol. Note that it only subscribes to one symbol, meaning that you would need to call this function for every light symbol in your collection of conversion symbols.
1 2 3 4 5 6 7 |
|
To handle spot events, we can add the following conditions to our onMessageReceived
callback.
1 2 3 |
|
Finally, here is our onSpotEvent
callback.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
In our Symbol
class, the getPipsFromRelative
function is defined as follows.
import math
def getPipsFromRelative(self, relative): return round((relative / 100000.0) / symbol.pipPosition, symbol.digits - symbol.pipPosition) ```
Note that the values of the pipPosition
and digits
properties have to be attained separately.
Follow the Conversion Chain and Return the Final Conversion Rate¶
At this point, all symbols in your conversion chain should receive spot rates and you should be able to access accurate bid and ask prices for each symbol. All that is left is to 'travel' along the conversion chain and return the final rate. This can be done as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|