Topics

Forum Topics not found

Replies

amusleh
01 Mar 2022, 09:25 ( Updated at: 01 Mar 2022, 09:26 )

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.


@amusleh

amusleh
01 Mar 2022, 09:21

RE: RE:

RedSeaBro said:

amusleh said:

Hi,

Check here: cAlgo API Reference - MarketDepth Interface (ctrader.com)

Thanks a lot amusleh. 

A follow up question: is the market depth data available and accurate in back test?

Hi,

No, it's not available in backtest.


@amusleh

amusleh
01 Mar 2022, 09:14

Hi,

The mouse hover event for objects only works if the object is interactive, so if you are using this event and if you make your object non interactive then it will not work.

You can use combination of lock and interactive, set object IsLocked to True unless mouse hover over it.


@amusleh

amusleh
28 Feb 2022, 09:12

RE: RE:

majidmesbah123456 said:

                    double volume_Less = position_InLoss_Volume / Math.Abs(Position_InLoss_NetProfit) * (position_InProfit_NetProfit);
                    double NewVolume_Loss = position_InLoss_Volume - volume_Less;
                    double NewVolume_Profit = position_InLoss_Volume - volume_Less;

                    if (position_In_Profit.NetProfit >= 200)
                    {
                        ClosePosition(position_In_Profit);
                        ModifyPosition(position_In_Loss, NewVolume_Loss);
                    }

Hello friends I also have a problem with changing the volume for positions, please help

An example of the code that is written is as follows But this code does not change the size of the position

what is the Problem?

 

Hi,

Please check the example #4 at: cAlgo API Reference - Position Interface (ctrader.com)

We can only help you if you post a full sample code that can reproduce the issue.


@amusleh

amusleh
28 Feb 2022, 09:04

Hi,

Please post a job request on jobs page or contact one of our consultants.


@amusleh

amusleh
28 Feb 2022, 09:02

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.


@amusleh

amusleh
28 Feb 2022, 08:55

RE: RE: Access Custom Indicator outputs

desmaster236 said:

Hi Dear Panagiotis,

I have the same problem, Accessing custom indicator outputs within a cBot.

while i have used some outputs in my indicator.

please help me why i haven't access to my indicator outputs from my cBot.

Regards.

Hi,

You can use custom indicators on your cBot, you have to reference it then you will be able to create an instance of it inside your cBot and access it's public members.

Please follow this guide: https://help.ctrader.com/ctrader-automate/guides/indicators#referencing-custom-indicators


@amusleh

amusleh
28 Feb 2022, 08:53

Hi,

You can develop a custom indicator that will show the number of ticks per x amount of time by using the indicator Timer.

I can't develop it for you as we don't provide programming service here, we provide support.

If you need programming service please post a job request on jobs page or contact one of our consultants.


@amusleh

amusleh
25 Feb 2022, 18:13 ( Updated at: 25 Feb 2022, 18:14 )

Hi,

You have to use ProtoOASpotEvent, you will receive that event after Spot subscription on each tick, not ProtoOAGetTickDataRes.

 


@amusleh

amusleh
25 Feb 2022, 09:33

Hi,

Do you need a tick counter on chart per minute? or per bar?

Can you make your request more clear please.


@amusleh

amusleh
25 Feb 2022, 09:31

Hi,

Most probably your message miss some fields, or there is something wrong with your code.

I can't help you as we don't have a Python sample for FIX right now, I tested on our .NET samples and it was working fine.

We will develop a Python sample for our FIX API very soon.


@amusleh

amusleh
25 Feb 2022, 09:29

Hi,

Can you tell exactly me what's the issue?


@amusleh

amusleh
24 Feb 2022, 10:22

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.


@amusleh

amusleh
24 Feb 2022, 09:07

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.


@amusleh

amusleh
24 Feb 2022, 08:46

Hi,

Once you are subscribed you will receive the data unless your connection drops off.

There is no need to do anything extra.


@amusleh

amusleh
24 Feb 2022, 08:43

Hi,

Can you provide a sample code that can reproduce this issue?


@amusleh

amusleh
23 Feb 2022, 09:18

Hi,

If your message format is invalid or has some missing fields you will receive an error message back from server.

Did you received any error response after sending the request?


@amusleh

amusleh
23 Feb 2022, 09:15

Hi,

To open a position or send any other request you have to first authorize your trading account on your connection session by sending a ProtoOAAccountAuthReq message.

After your account got authorized and you received the ProtoOAAccountAuthRes response message you can start sending trading requests or getting account related data.

To open a new order you have to send a ProtoOANewOrderReq request, this request is used for both pending and market (position) orders.

Now regarding OpenApiPy package, once you received the ProtoOAAccountAuthRes message via MessageReceivedCallback or your Twisted deferred then you can send a ProtoOANewOrderReq.

In your posted code I see you call the sendProtoOANewOrderReq method before you start the client service and connection, that will not work, because there is no connection between you and API yet let alone the app and account authorization.

Please check my added comments at onMessageReceived method:

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
from inputimeout import inputimeout, TimeoutOccurred
import json
import datetime


credentialsFile = open("credentials.json")
credentials = json.load(credentialsFile)

if __name__ == "__main__":
    currentAccountId = None
    hostType = input("Host (Live/Demo): ")
    hostType = hostType.lower()

    while hostType != "live" and  hostType != "demo":
        print(f"{hostType} is not a valid host type.")
        hostType = input("Host (Live/Demo): ")

    appClientId = credentials["ClientId"]
    appClientSecret = credentials["Secret"]
    isTokenAvailable = credentials["AccessToken"]

    accessToken = None
    if isTokenAvailable == False:
        appRedirectUri = input("App Redirect URI: ")
        auth = Auth(appClientId, appClientSecret, appRedirectUri)
        authUri = auth.getAuthUri()
        print(f"Please continue the authentication on your browser:\n {authUri}")
        webbrowser.open_new(authUri)
        print("\nThen enter the auth code that is appended to redirect URI immediatly (the code is after ?code= in URI)")
        authCode = input("Auth Code: ")
        token = auth.getToken(authCode)
        if "accessToken" not in token:
            raise KeyError(token)
        print("Token: \n", token)
        accessToken = token["accessToken"]
    else:
        accessToken = credentials["AccessToken"]
        
    client = Client(EndPoints.PROTOBUF_LIVE_HOST if hostType.lower() == "live" else EndPoints.PROTOBUF_DEMO_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)
 
    def setAccount(accountId):
        global currentAccountId
        if currentAccountId is not None:
            sendProtoOAAccountLogoutReq()
        currentAccountId = int(accountId)
        sendProtoOAAccountAuthReq()
        
        
    def sendProtoOAAccountAuthReq(clientMsgId = None):
        request = ProtoOAAccountAuthReq()
        request.ctidTraderAccountId = currentAccountId
        request.accessToken = accessToken
        deferred = client.send(request, clientMsgId = clientMsgId)
        deferred.addErrback(onError)     
        
        
    
    def connected(client): # Callback for client connection
        print("\nConnected")
        request = ProtoOAApplicationAuthReq()
        request.clientId = appClientId
        request.clientSecret = appClientSecret
        deferred = client.send(request)
        deferred.addErrback(onError)
    
    def disconnected(client, reason): # Callback for client disconnection
        print("\nDisconnected: ", reason)
    
    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")
            # This is where you can send a new order request
            # This is the place that your account authorization
            # response message is received
        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)
        
        
        
    def executeUserCommand():
        try:
            print("\n")
            userInput = inputimeout("Command (ex help): ", timeout=18)
        except TimeoutOccurred:
            print("Command Input Timeout")
            reactor.callLater(3, callable=executeUserCommand)
            return
        userInputSplit = userInput.split(" ")
        if not userInputSplit:
            print("Command split error: ", userInput)
            reactor.callLater(3, callable=executeUserCommand)
            return
        command = userInputSplit[0]
        try:
            parameters = [parameter if parameter[0] != "*" else parameter[1:] for parameter in userInputSplit[1:]]
        except:
            print("Invalid parameters: ", userInput)
            reactor.callLater(3, callable=executeUserCommand)
        if command in commands:
            commands[command](*parameters)
        else:
            print("Invalid Command: ", userInput)
            reactor.callLater(3, callable=executeUserCommand)
        
        
    def sendProtoOAGetAccountListByAccessTokenReq(clientMsgId = None):
        request = ProtoOAGetAccountListByAccessTokenReq()
        request.accessToken = credentials["AccessToken"]
        deferred = client.send(request, clientMsgId = clientMsgId)
        deferred.addErrback(onError)
        
    def sendProtoOAAssetListReq(clientMsgId = None):
        request = ProtoOAAssetListReq()
        request.ctidTraderAccountId = currentAccountId
        deferred = client.send(request, clientMsgId = clientMsgId)
        deferred.addErrback(onError)
        
    def sendProtoOANewOrderReq(symbolId, orderType, tradeSide, volume, price = None, clientMsgId = None):
        request = ProtoOANewOrderReq()
        request.ctidTraderAccountId = currentAccountId
        request.symbolId = int(symbolId)
        request.orderType = ProtoOAOrderType.Value(orderType.upper())
        request.tradeSide = ProtoOATradeSide.Value(tradeSide.upper())
        request.volume = int(volume) * 100
        if request.orderType == ProtoOAOrderType.LIMIT:
            request.limitPrice = float(price)
        elif request.orderType == ProtoOAOrderType.STOP:
            request.stopPrice = float(price)
        deferred = client.send(request, clientMsgId = clientMsgId)
        deferred.addErrback(onError)    
        
        
        
        
    def sendNewMarketOrder(symbolId, tradeSide, volume, clientMsgId = None):
        sendProtoOANewOrderReq(symbolId, "MARKET", tradeSide, volume, clientMsgId = clientMsgId)
        
    
    # Setting optional client callbacks
    client.setConnectedCallback(connected)
    client.setDisconnectedCallback(disconnected)
    client.setMessageReceivedCallback(onMessageReceived)

    # Starting the client service
    client.startService()
    reactor.run()

 


@amusleh

amusleh
23 Feb 2022, 09:03 ( Updated at: 23 Feb 2022, 09:04 )

Hi,

The lazy loading of indicators means that the indicator code is not called/executed unless you access it's data.

By data I mean indicator Outputs / IndicatorDataSeries, if your indicator has no Output then you have to explicitly call the indicator Calculate method.

It's an implementation detail, and it's very rare to face any issue with indicator lazy loading unless you use an indicator without an Output.


@amusleh

amusleh
23 Feb 2022, 09:00

Hi,

Try this:

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleRSImodifiedwoLabel : Robot
    {
        [Parameter("Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        [Parameter("Source", Group = "RSI")]
        public DataSeries Source { get; set; }

        [Parameter("Periods", Group = "RSI", DefaultValue = 14)]
        public int Periods { get; set; }

        [Parameter("Lower RSI Level", Group = "RSI", DefaultValue = 30, MinValue = 0, MaxValue = 50)]
        public int LRL { get; set; }

        [Parameter("Upper RSI Level", Group = "RSI", DefaultValue = 70, MinValue = 50, MaxValue = 100)]
        public int URL { get; set; }

        [Parameter("Take Profit in pips", Group = "TP SL", DefaultValue = 100)]
        public int TP { get; set; }

        [Parameter("Stop Loss in pips", Group = "TP SL", DefaultValue = 100)]
        public int SL { get; set; }

        [Parameter("Label", Group = "Others", DefaultValue = "SampleRSI")]
        public string Label { get; set; }

        private RelativeStrengthIndex rsi;

        protected override void OnStart()
        {
            rsi = Indicators.RelativeStrengthIndex(Source, Periods);
        }

        protected override void OnTick()
        {
            if (rsi.Result.LastValue < LRL)
            {
                Close(TradeType.Sell);
                Open(TradeType.Buy);
            }
            else if (rsi.Result.LastValue > URL)
            {
                Close(TradeType.Buy);
                Open(TradeType.Sell);
            }
        }

        private void Close(TradeType tradeType)
        {
            foreach (var position in Positions.FindAll(Label, SymbolName, tradeType))
                ClosePosition(position);
        }

        private void Open(TradeType tradeType)
        {
            var position = Positions.Find(Label, SymbolName, tradeType);
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);

            if (position == null)
                ExecuteMarketOrder(tradeType, SymbolName, volumeInUnits, Label, SL, TP);
        }
    }
}

 


@amusleh