Replies

prenven570
11 Apr 2022, 14:50

RE:

amusleh said:

Hi,

The Open API returns the last closed bar data if you pass right parameters to trend bar request.

To get only the last closed bar set the to timestamp to now and request count field to 1, then it will return only the last bar data.

If you are using our Open API Python package (OpenApiPy) there was an issue on it's samples related to Python date time to Unix time conversion, we fixed it, please update your samples.

Thanks!, now I get the candle I need


@prenven570

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