Topics
Replies
prenven570
30 Mar 2022, 09:36
RE:
amusleh said:
Hi,
You can use a global variable to check if the position is already opened or not, ex:
isPositionsRequestSent = False def onMessageReceived(client, message): # Callback for receiving all messages if message.payloadType in [ProtoHeartbeatEvent().payloadType, ProtoOAAccountAuthRes().payloadType, ProtoOAApplicationAuthRes().payloadType, ProtoOASymbolsListRes().payloadType, ProtoOAGetTrendbarsRes().payloadType]: return print("\nMessage received: \n", Protobuf.extract(message)) if message.payloadType == ProtoOAExecutionEvent().payloadType: print("Execution event received") executionEvent = Protobuf.extract(message) print(executionEvent.position.positionId) positionId = executionEvent.position.positionId if isPositionsRequestSent is False: global isPositionsRequestSent isPositionsRequestSent = True symbolId = 1106 clientMsgId = None volume = 2 request = ProtoOANewOrderReq() request.ctidTraderAccountId = currentAccountId request.symbolId = int(symbolId) request.orderType = ProtoOAOrderType.MARKET request.tradeSide = ProtoOATradeSide.SELL request.volume = int(volume) * 100 deferred = client.send(request, clientMsgId = clientMsgId) deferred.addErrback(onError)
There are other solutions too, but this one is simplest one, it all depends on what you want to do and your design and architecture.
It's not something related to Open API or our package, these are basic programming stuff that you should know.
Perfect, thanks, this method worked:
global isPositionsRequestSent
if isPositionsRequestSent is False:
isPositionsRequestSent = True
@prenven570
prenven570
10 Mar 2022, 13:00
RE:
prenven570 said:
I have this code (from jupyter sample):
from ctrader_open_api import Client, Protobuf, TcpProtocol, Auth, EndPoints from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import * from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import * from ctrader_open_api.messages.OpenApiMessages_pb2 import * from ctrader_open_api.messages.OpenApiModelMessages_pb2 import * from twisted.internet import reactor import json import datetime
credentialsFile = open("credentials-dev.json") credentials = json.load(credentialsFile)
host = EndPoints.PROTOBUF_LIVE_HOST if credentials["HostType"].lower() == "live" else EndPoints.PROTOBUF_DEMO_HOST client = Client(host, EndPoints.PROTOBUF_PORT, TcpProtocol)
symbolName = "GERMANY 40"dailyBars = []def transformTrendbar(trendbar): openTime = datetime.datetime.fromtimestamp(trendbar.utcTimestampInMinutes * 60) openPrice = (trendbar.low + trendbar.deltaOpen) / 100000.0 highPrice = (trendbar.low + trendbar.deltaHigh) / 100000.0 lowPrice = trendbar.low / 100000.0 closePrice = (trendbar.low + trendbar.deltaClose) / 100000.0 return [openTime, openPrice, highPrice, lowPrice, closePrice, trendbar.volume]
def trendbarsResponseCallback(result): print("\nTrendbars received") trendbars = Protobuf.extract(result) barsData = list(map(transformTrendbar, trendbars.trendbar)) global dailyBars dailyBars.clear() dailyBars.extend(barsData) print("\ndailyBars length:", len(dailyBars)) print("\Stopping reactor...") reactor.stop() def symbolsResponseCallback(result): print("\nSymbols received") symbols = Protobuf.extract(result) global symbolName symbolsFilterResult = list(filter(lambda symbol: symbol.symbolName == symbolName, symbols.symbol)) if len(symbolsFilterResult) == 0: raise Exception(f"There is symbol that matches to your defined symbol name: {symbolName}") elif len(symbolsFilterResult) > 1: raise Exception(f"More than one symbol matched with your defined symbol name: {symbolName}, match result: {symbolsFilterResult}") symbol = symbolsFilterResult[0] request = ProtoOAGetTrendbarsReq() request.symbolId = symbol.symbolId request.ctidTraderAccountId = credentials["AccountId"] request.period = ProtoOATrendbarPeriod.H1 # We set the from/to time stamps to 50 weeks, you can load more data by sending multiple requests # Please check the ProtoOAGetTrendbarsReq documentation for more detail request.fromTimestamp = int((datetime.datetime.utcnow() - datetime.timedelta(weeks=1)).timestamp()) * 1000 request.toTimestamp = int(datetime.datetime.utcnow().timestamp()) * 1000 deferred = client.send(request) deferred.addCallbacks(trendbarsResponseCallback, onError) def accountAuthResponseCallback(result): print("\nAccount authenticated") request = ProtoOASymbolsListReq() request.ctidTraderAccountId = credentials["AccountId"] request.includeArchivedSymbols = False deferred = client.send(request) deferred.addCallbacks(symbolsResponseCallback, onError)
def applicationAuthResponseCallback(result): print("\nApplication authenticated") request = ProtoOAAccountAuthReq() request.ctidTraderAccountId = credentials["AccountId"] request.accessToken = credentials["AccessToken"] deferred = client.send(request) deferred.addCallbacks(accountAuthResponseCallback, onError) def onError(client, failure): # Call back for errors print("\nMessage Error: ", failure) def disconnected(client, reason): # Callback for client disconnection print("\nDisconnected: ", reason) def onMessageReceived(client, message): # Callback for receiving all messages if message.payloadType in [ProtoHeartbeatEvent().payloadType, ProtoOAAccountAuthRes().payloadType, ProtoOAApplicationAuthRes().payloadType, ProtoOASymbolsListRes().payloadType, ProtoOAGetTrendbarsRes().payloadType]: return print("\nMessage received: \n", Protobuf.extract(message)) def connected(client): # Callback for client connection print("\nConnected") request = ProtoOAApplicationAuthReq() request.clientId = credentials["ClientId"] request.clientSecret = credentials["Secret"] deferred = client.send(request) deferred.addCallbacks(applicationAuthResponseCallback, onError) # Setting optional client callbacks client.setConnectedCallback(connected) client.setDisconnectedCallback(disconnected) client.setMessageReceivedCallback(onMessageReceived)
# Starting the client service client.startService() # Run Twisted reactor, we imported it earlier reactor.run()
df = pd.DataFrame(np.array(dailyBars), columns=['Time', 'Open', 'High', 'Low', 'Close', 'Volume']) df["Open"] = pd.to_numeric(df["Open"]) df["High"] = pd.to_numeric(df["High"]) df["Low"] = pd.to_numeric(df["Low"]) df["Close"] = pd.to_numeric(df["Close"]) df["Volume"] = pd.to_numeric(df["Volume"])
df
I get values starting with "03:00:00" or "08:00:00", but I need data starting from 00:00:00. How can I get these data?
(solved)
It depends by the broker you use
@prenven570
prenven570
04 Mar 2022, 09:18
RE: RE: RE:
william@hallsdesign.co.uk said:
prenven570 said:
Edit:
i solved the problem of the unauthorized trading account, but the second question remains: How to open a position?
Hi, how did you solve the unauthorised trading account bit? I have this same issue and I am unsure how to solve. ( just changed my accountID to xxxxxxxx ).
Message received:
ctidTraderAccountId: xxxxxxxx
errorCode: "ACCOUNT_NOT_AUTHORIZED"
description: "Account is not authorized"Any help is greatly appreciated.
I solved by using this code:
from ctrader_open_api import Client, Protobuf, TcpProtocol, Auth, EndPoints from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import * from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import * from ctrader_open_api.messages.OpenApiMessages_pb2 import * from ctrader_open_api.messages.OpenApiModelMessages_pb2 import * from twisted.internet import reactor import json import datetime
#you create a .json file with credentials ther's a sample on the github repository (jupyter sample)
credentialsFile = open("credentials-dev.json") credentials = json.load(credentialsFile)
host = EndPoints.PROTOBUF_LIVE_HOST if credentials["HostType"].lower() == "live" else EndPoints.PROTOBUF_DEMO_HOST client = Client(host, EndPoints.PROTOBUF_PORT, TcpProtocol)
def accountAuthResponseCallback(result): print("\nAccount authenticated") request = ProtoOASymbolsListReq() request.ctidTraderAccountId = credentials["AccountId"] request.includeArchivedSymbols = False deferred = client.send(request) def applicationAuthResponseCallback(result): print("\nApplication authenticated") request = ProtoOAAccountAuthReq() request.ctidTraderAccountId = credentials["AccountId"] request.accessToken = credentials["AccessToken"] deferred = client.send(request) deferred.addCallbacks(accountAuthResponseCallback, onError) def onError(client, failure): # Call back for errors print("\nMessage Error: ", failure) def disconnected(client, reason): # Callback for client disconnection print("\nDisconnected: ", reason) def onMessageReceived(client, message): # Callback for receiving all messages if message.payloadType in [ProtoHeartbeatEvent().payloadType, ProtoOAAccountAuthRes().payloadType, ProtoOAApplicationAuthRes().payloadType, ProtoOASymbolsListRes().payloadType, ProtoOAGetTrendbarsRes().payloadType]: return print("\nMessage received: \n", Protobuf.extract(message)) def connected(client): # Callback for client connection print("\nConnected") request = ProtoOAApplicationAuthReq() request.clientId = credentials["ClientId"] request.clientSecret = credentials["Secret"] deferred = client.send(request) deferred.addCallbacks(applicationAuthResponseCallback, onError) # Setting optional client callbacks client.setConnectedCallback(connected) client.setDisconnectedCallback(disconnected) client.setMessageReceivedCallback(onMessageReceived)
# Starting the client service
client.startService()
# Run Twisted reactor, we imported it earlier
reactor.run()
@prenven570
prenven570
01 Mar 2022, 15:31
RE:
amusleh said:
Hi,
You can do it like this:
# this will contain all symbol IDs with their bid/ask prices symbolsData = dict() def symbolsResponseCallback(result): print("\nSymbols received") symbols = Protobuf.extract(result) global symbolsData for symbol in symbols.symbol: symbolsData.append(symbol.symbolId, (0, 0)) spotRequest = ProtoOASubscribeSpotsReq() spotRequest.symbolId = symbol.symbolId spotRequest.ctidTraderAccountId = credentials["AccountId"] deferred = client.send(request) deferred.addErrback(onError) def accountAuthResponseCallback(result): print("\nAccount authenticated") request = ProtoOASymbolsListReq() request.ctidTraderAccountId = credentials["AccountId"] request.includeArchivedSymbols = False deferred = client.send(request) deferred.addCallbacks(symbolsResponseCallback, onError) def applicationAuthResponseCallback(result): print("\nApplication authenticated") request = ProtoOAAccountAuthReq() request.ctidTraderAccountId = credentials["AccountId"] request.accessToken = credentials["AccessToken"] deferred = client.send(request) deferred.addCallbacks(accountAuthResponseCallback, onError) def onError(client, failure): # Call back for errors print("\nMessage Error: ", failure) def disconnected(client, reason): # Callback for client disconnection print("\nDisconnected: ", reason) def onMessageReceived(client, message): # Callback for receiving all messages if message.payloadType in [ProtoHeartbeatEvent().payloadType, ProtoOAAccountAuthRes().payloadType, ProtoOAApplicationAuthRes().payloadType, ProtoOASymbolsListRes().payloadType, ProtoOAGetTrendbarsRes().payloadType]: return elif message.payloadType == ProtoOASpotEvent().payloadType: global symbolsData spotEvent = Protobuf.extract(message) symbolsData[spotEvent.symbolId] = (spotEvent.bid / 100000, spotEvent.ask / 100000) # now you have the symbol prices, do anything you want to here or by using # the symbolsData dictionary #print("\nMessage received: \n", Protobuf.extract(message)) def connected(client): # Callback for client connection print("\nConnected") request = ProtoOAApplicationAuthReq() request.clientId = credentials["ClientId"] request.clientSecret = credentials["Secret"] deferred = client.send(request) deferred.addCallbacks(applicationAuthResponseCallback, onError) # Setting optional client callbacks client.setConnectedCallback(connected) client.setDisconnectedCallback(disconnected) client.setMessageReceivedCallback(onMessageReceived)
My code might have some issues as I haven't tested it but it will give you an idea.
Thank you a lot for the example.
yes, there's an error on line 25:
AttributeError: 'dict' object has no attribute 'append'
@prenven570
prenven570
01 Mar 2022, 13:59
RE:
amusleh said:
Hi,
There are lots of ways that you can do that, it depends on what design pattern you follow.
A simple solution will be to create a symbol class, get all symbols from API and transform them to your symbol class instances.
The symbol class should have a bid and ask property, store all those Symbols inside a list or dictionary with their name as key.
The symbols collection should be available on your global scope or the on message received method scope.
Then subscribe to spot event for all those symbols, whenever you receive the bid/ask prices of a symbol update the symbol instance bid/ask properties.
This way you will have access always to latest bid/ask prices of all symbols.
As I said on my previous post, it's not something related to Open API or OpenApiPy, it's related to your Python coding skill.
Hello, yes it's probably related to my coding skills.
It would be nice if there were more concrete examples in the openApiPy repository, in this way people who haven't much experience would be able to code some basic systems.
I think I'm not asking something that hard, only how to set correctly a price condition, it would be very helpful. Please, think about it. Thanks.
@prenven570
prenven570
28 Feb 2022, 09:23
RE:
amusleh said:
Hi,
The way you coded it is not correct.
I see most of your issues are related to your Python skills not to Open API.
If you want to send a new order request based on a condition that uses current price then you have to use the Spot event for getting the price, once you got the price check the condition if it's ok then send a new order request.
ProtoOASpotEvent has the bid/ask properties, and it's not in actual price, you have to transform is to price by dividing it to 100000.
The OpenApiPy uses Twisted and you have to use callbacks, the execution flow is not sequential.
Hello, thanks for the answer. But how can I get the updated price in another function?
I get it inside the onMessageReceived function, but when I use global to use price variable in another function, I don't get the updated price.
But I get only one price: 3928229, 3928229, 3928229...
@prenven570
prenven570
25 Feb 2022, 19:15
RE:
amusleh said:
Hi,
You have to use ProtoOASpotEvent, you will receive that event after Spot subscription on each tick, not ProtoOAGetTickDataRes.
Thanks
@prenven570
prenven570
24 Feb 2022, 10:28
RE:
amusleh said:
Hi,
If you can receive the response then getting the position ID or any other field of it is very easy.
Here is an example:
def onMessageReceived(client, message): # Callback for receiving all messages # execute a trade on your account, to get an execution event if message.payloadType == ProtoOAExecutionEvent().payloadType: print("Execution event received") executionEvent = Protobuf.extract(message) print(executionEvent.position.positionId) # send a reconcile request to receive a reconcile response if message.payloadType == ProtoOAReconcileRes().payloadType: print("Reconcile response received") reconcileRes = Protobuf.extract(message) for position in reconcileRes.position: print(position.positionId) for order in reconcileRes.order: print(order.orderId)
When you receive a message you can check it's payload type, if it's of your interested type then you can serialize the message to that type and access it's data.
In case you used the Twisted deferred for getting a request response you don't have to do the serialization, it will be done automatically and your callback will be called with the request message response, you can't use the Twisted deferreds for events like spot event, execution event, etc... for them you have to use the message received call back.
Thanks a lot!!! It worked
@prenven570
prenven570
24 Feb 2022, 09:25
RE:
amusleh said:
Hi,
To get a position ID you can either use ExecutionEvent or Reconcile request.
The reconcile request gives you list of all open account orders with their detail, and ExecutionEvent occurs whenever you perform a trading operation on your account.
In our console sample use setAccount command to authorize a trading account, ex: setAccount account_Id
For example, if I use the console sample, and set account to one of my accounts, and then if I create a new market order I will receive the execution event:
ctidTraderAccountId: 16608956 executionType: ORDER_FILLED position { positionId: 263362553 tradeData { symbolId: 2 volume: 100000 tradeSide: SELL openTimestamp: 1645685625147 guaranteedStopLoss: false } positionStatus: POSITION_STATUS_OPEN swap: 0 price: 1.34984 utcLastUpdateTimestamp: 1645685625147 commission: -4 marginRate: 1.34984 mirroringCommission: 0 guaranteedStopLoss: false usedMargin: 270 moneyDigits: 2 } order { orderId: 399293765 tradeData { symbolId: 2 volume: 100000 tradeSide: SELL openTimestamp: 1645685624943 guaranteedStopLoss: false } orderType: MARKET orderStatus: ORDER_STATUS_FILLED executionPrice: 1.34984 executedVolume: 100000 utcLastUpdateTimestamp: 1645685625147 closingOrder: false clientOrderId: "ctd-df2b5de6032c47609a443bf746b136d0" timeInForce: IMMEDIATE_OR_CANCEL positionId: 263362553 } deal { dealId: 365614484 orderId: 399293765 positionId: 263362553 volume: 100000 filledVolume: 100000 symbolId: 2 createTimestamp: 1645685624943 executionTimestamp: 1645685625147 utcLastUpdateTimestamp: 1645685625147 executionPrice: 1.34984 tradeSide: SELL dealStatus: FILLED marginRate: 1.34984 commission: -4 baseToUsdConversionRate: 1.34984 moneyDigits: 2 } isServerEvent: false
You see in above execution event, the position ID, order ID and all the other details are there.
You have to authorize your connection to an account, then you will receive the execution event, for getting execution events use the general MessageReceivedCallback:
def onMessageReceived(client, message): # Callback for receiving all messages if message.payloadType in [ProtoOASubscribeSpotsRes().payloadType, ProtoOAAccountLogoutRes().payloadType, ProtoHeartbeatEvent().payloadType]: return elif message.payloadType == ProtoOAApplicationAuthRes().payloadType: print("API Application authorized\n") print("Please use setAccount command to set the authorized account before sending any other command, try help for more detail\n") print("To get account IDs use ProtoOAGetAccountListByAccessTokenReq command") if currentAccountId is not None: sendProtoOAAccountAuthReq() return 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") print("You can change the account by using setAccount command") else: print("Message received: \n", Protobuf.extract(message)) reactor.callLater(3, callable=executeUserCommand) client.setMessageReceivedCallback(onMessageReceived)
The above code is part of our console sample.
To get orders data with reconcile request you just have to send a reconcile request after account authorization and you will receive back the response:
def sendProtoOAReconcileReq(clientMsgId = None): request = ProtoOAReconcileReq() request.ctidTraderAccountId = currentAccountId deferred = client.send(request, clientMsgId = clientMsgId) deferred.addErrback(onError)
You can use both the deferred or general message received call back for getting back the response.
Here is an example of reconcile response:
Message received: ctidTraderAccountId: 16608956 position { positionId: 263362553 tradeData { symbolId: 2 volume: 100000 tradeSide: SELL openTimestamp: 1645685625147 guaranteedStopLoss: false } positionStatus: POSITION_STATUS_OPEN swap: 0 price: 1.34984 utcLastUpdateTimestamp: 1645685625147 commission: -4 marginRate: 1.34984 mirroringCommission: 0 guaranteedStopLoss: false usedMargin: 270 moneyDigits: 2 }
Now, regarding your issue, there is no position Id on reconcile request, the request is a message you will send for getting positions/orders data.
Please read the Open API documentation, review the console sample code, and play with it, then you will understand how it works.
Thanks for your answer. I know that I can see the positionId and other information in the output, but I think I need a way to store the positionId number inside a variable, so I can close the opened position. When I open a position, I'm not able to close it, because "positionId" is not defined, this happens even with a reconcile request. So what can I do to close the opened position?
@prenven570
prenven570
22 Feb 2022, 12:37
( Updated at: 22 Feb 2022, 12:44 )
RE:
Edit:
i solved the problem of the unauthorized trading account, but the second question remains: How to open a position?
@prenven570
prenven570
11 Apr 2022, 14:50
RE:
amusleh said:
Thanks!, now I get the candle I need
@prenven570