Skip to main content

Python example of how to subscribe for data

Sensitive data stored in .env file.

https://t.me/ctrader_open_api_support/8932

from ctrader_open_api import Client, Protobuf, TcpProtocol, EndPoints
import ctrader_open_api.messages.OpenApiMessages_pb2 as OA
import os
from twisted.internet import reactor
from dotenv import load_dotenv

load_dotenv()

credentials = {
'clientId': os.getenv('CLIENT_ID'),
'clientSecret': os.getenv('CLIENT_SECRET'),
'accessToken': os.getenv('ACCESS_TOKEN'),
'accountId': int(os.getenv('ACCOUNT_ID'))
}

client = Client(EndPoints.PROTOBUF_LIVE_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)
PROTO_OA_ERROR_RES_PAYLOAD_TYPE = OA.ProtoOAErrorRes().payloadType

tickers = ['EURUSD', 'XAUUSD', 'USDCNH', 'XAGUSD']
symbol_ids = {}


def onAccAuth(message):
if message.payloadType == PROTO_OA_ERROR_RES_PAYLOAD_TYPE:
print('Account authentication failed:', Protobuf.extract(message))
reactor.stop()
return
print('Account authenticated')
print('Requesting symbol list...')
req = OA.ProtoOASymbolsListReq()
req.ctidTraderAccountId = credentials['accountId']
deferred = client.send(req)
deferred.addCallbacks(onSymbolsList, onError)


def onSymbolsList(message):
response = Protobuf.extract(message)
print('Symbols received')
for symbol in response.symbol:
if symbol.symbolName in tickers:
symbol_ids[symbol.symbolName] = symbol.symbolId
print(f'{symbol.symbolName} -> SymbolID {symbol.symbolId}')
subscribeToPrices()


def subscribeToPrices():
print('Subscribing to price streams...')
req = OA.ProtoOASubscribeSpotsReq()
req.ctidTraderAccountId = credentials['accountId']
# Setup ID list
req.symbolId.extend(symbol_ids.values())
client.send(req)


def onMsg(client, message):
if message.payloadType == OA.ProtoOASpotEvent().payloadType:
response = Protobuf.extract(message)
symbolName = next((n for n, sid in symbol_ids.items() if sid == response.symbolId), str(response.symbolId))
print(f'Price update: {symbolName} Bid {response.bid} Ask {response.ask}')


def onAppAuth(message):
if message.payloadType == PROTO_OA_ERROR_RES_PAYLOAD_TYPE:
print('App authentication failed:', Protobuf.extract(message))
reactor.stop()
return
print('App authenticated')
req = OA.ProtoOAAccountAuthReq()
req.ctidTraderAccountId = credentials['accountId']
req.accessToken = credentials['accessToken']
deferred = client.send(req)
deferred.addCallbacks(onAccAuth, onError)


def onError(failure):
print('Error:', repr(failure.value))
reactor.stop()


def connected(client):
print('Connected')
req = OA.ProtoOAApplicationAuthReq()
req.clientId = credentials['clientId']
req.clientSecret = credentials['clientSecret']
deferred = client.send(req, responseTimeoutInSeconds=20)
deferred.addCallbacks(onAppAuth, onError)


def disconnected(client, reason):
print('Disconnected:', reason)
reactor.stop()


client.setConnectedCallback(connected)
client.setDisconnectedCallback(disconnected)
client.setMessageReceivedCallback(onMsg)
client.startService()
reactor.run()