ejtraderLabs / ejtraderCT

The best Python Ctrader FIX API Perfect for HFT
MIT License
61 stars 21 forks source link

Problem running with Flask Application #12

Closed ghost closed 1 year ago

ghost commented 1 year ago

Hi ejtraderCT Team,

This package is great and running well for us. However, we wanted to make it work with Flask Application. So, we can host it on the Linux server and then send a request to it to open and close the positions.

When I start my Flask Application and open 1 order. It opens the position correctly but when I try to send it again it don't process the connection and shows this error.

ERROR:root:Disconnected ERROR:root:Disconnected

Then after few mints. It's automatically show another message and start for one more alert again.

ERROR:root:Error in QUOTE send. Closing connection. client_id: 1 ERROR:root:Error in QUOTE send. Closing connection. client_id: 1

After this above error message seems like the connection is closed and now I can make the connection again. According to my understanding. I can make the connection only once. Whenever I send a few Flask request it stops working as it's already connected to the server and our code is to make the new connection every time.

I don't know how I can change my code according to the Client Server Connection. So, don't connect again and again or check every time if it's connected or not already.

`class Exchanges: def ctrader(key, secret, password, broker, pair, ordertype, order, volume, price, sl, tp):

  SERVER = secret # 'h50.p.ctrader.com'
  BROKER = broker # 'demo.icmarkets'
  LOGIN  = key    #account_number
  PASSWORD = password #password
  CURRENCY = pair[-3:] #'USD'

  def auth():
      logging.getLogger().setLevel(logging.INFO)
      api = Ctrader(SERVER, BROKER, LOGIN, PASSWORD, CURRENCY)
      return api

  try:
        client = auth()
        time.sleep(1)

        client.subscribe(pair)
        time.sleep(1)

        quote = client.quote(pair)
        print(quote['ask'])

        if order == 'buy':
          order = client.buy(pair, volume, stoploss=None, takeprofit=None)`

Please help me to resolve this. My Flask application is almost ready but I'm stuck here. Your help would be very appreciated. Also if you have a discord server let me know.

One last thing that I would like to mention about the TP and SL. We are unable to set the TP and SL as per the documentation. It would be great if you find a way to implement it. As it is very important to set the Pre to define TP and SL instead of waiting for the system to close it.

Thanks

ghost commented 1 year ago

After reading so many articles and especially on the IBKR GitHub package issues.

I believe we need to have the api.disconnect() option for the package. Please let me know if it's already there or if there is a way we can do it using the async and await functions. So, we don't need to connect again and again on each Flask Request.

Looking forward to your expert review and feedback

Thanks

traderpedroso commented 1 year ago

After reading so many articles and especially on the IBKR GitHub package issues.

I believe we need to have the api.disconnect() option for the package. Please let me know if it's already there or if there is a way we can do it using the async and await functions. So, we don't need to connect again and again on each Flask Request.

Looking forward to your expert review and feedback

Thanks

You don't need to connect every time; simply place the API globally at the beginning of the script.

import ejtraderCT
from flask import Flask, request

import logging
import time

from ejtraderCT import Ctrader

logging.getLogger().setLevel(logging.INFO)

SERVER = "IP"  # Host name
BROKER = "demo.icmarkets"
LOGIN = "11111"
PASSWORD = "1111"
CURRENCY = "EUR"

volume = 10 # position size

api = Ctrader(server=SERVER, broker=BROKER, login=LOGIN, password=PASSWORD, currency=CURRENCY)

app = Flask(__name__)

@app.route('/alert', methods=['POST'])
def handle_alert():
    data = request.get_json()
    # faça algo com os dados do alerta recebido
    return 'alert received!'

def handle_alert():
    data = request.get_json()
    symbol = data["SYMBOL"]
    type = data['TYPE']

    if  type == 'buy':
        api.buy(symbol=symbol, volume= volume, stoploss=None, takeprofit=None)
    elif data['type'] == 'sell':
        api.sell(symbol=symbol, volume= volume, stoploss=None, takeprofit=None) 

    return 'Action Done!'
ghost commented 1 year ago

Thank you so much for your response. It's genius answer. However, I have to run alerts request and each request come with the different account details. For example

Alert 1: Account #1 Alert 2: Account #2 Alert 3: Account #1 Alert 4: Account #1

So, we have multiple accounts with multiple alerts to handle a trade. Can you please give me an example which I can use to configure multiple accounts. If we have 2 coming alerts for two different accounts login and password. How I would be able to handle it?

Thank you so much for your help. You are awesome.

traderpedroso commented 1 year ago

Author

Regarding the request, I couldn't understand these requests for multiple accounts. Are these pieces of information that you will execute on a single account, or will you execute these requests on different accounts? For example, if you will execute them on different accounts, it would be ideal to use threads in the same script to run multiple accounts. In the messages you will receive, there must be an ID so you can route them. Please explain if you want to manage multiple accounts or copy signals from outside to your single account, so I can give you an idea of how to do it. Some time ago, I created an application to manage multiple accounts in a single backend, but for this, you need to create something that checks the connection in case it is not connected, and so on. In my case, at the time, I used RabbitMQ to manage the queues and create a kind of thread-safe environment.

ghost commented 1 year ago

Thanks for your kind response traderpedroso,

You are correct. I'm trying to place the order on the multiple accounts. What I'm trying to do is I receive the account information from the alert message and then place the order on that particular account.

So in my above example Alert 1 include the Account 1 information (LOGIN and PASSWORD). Alert 2 include the Account 2 information and then Alert 3 and 4 include the information of Account 1 again. So, each POST request contain the account information as well.

Alert 1: Account 1 Alert 2: Account 2 Alert 3: Account 1 Alert 4: Account 1

If I make the account information Global then the account information will be fix and I won't be able to change it on each alert as each alert include different account information. That's why I asked if we can have a feature which we can use to disconnect the client like api.disconnect()

So, when we receive the alert we connect with that particular account and then disconnect it and wait for the other alert.

I'm really sorry if we can do it with Thread can you please share with me the example. I'm not very good with async and Thread. You example code would be really appreciated.

Thank you so much

traderpedroso commented 1 year ago

Thanks for your kind response traderpedroso,

You are correct. I'm trying to place the order on the multiple accounts. What I'm trying to do is I receive the account information from the alert message and then place the order on that particular account.

So in my above example Alert 1 include the Account 1 information (LOGIN and PASSWORD). Alert 2 include the Account 2 information and then Alert 3 and 4 include the information of Account 1 again. So, each POST request contain the account information as well.

Alert 1: Account 1 Alert 2: Account 2 Alert 3: Account 1 Alert 4: Account 1

If I make the account information Global then the account information will be fix and I won't be able to change it on each alert as each alert include different account information. That's why I asked if we can have a feature which we can use to disconnect the client like api.disconnect()

So, when we receive the alert we connect with that particular account and then disconnect it and wait for the other alert.

I'm really sorry if we can do it with Thread can you please share with me the example. I'm not very good with async and Thread. You example code would be really appreciated.

Thank you so much

I just added the logout function to disconnect, now just update to version 1.0.8.

pip install ejtraderCT -U

to disconnect from the ctrader before connect to other account

api.logout()

ghost commented 1 year ago

Wow, great man. It is working like a Cham now. It also fix some other problem that I were facing like I were not available to place order or get the quote['ask'] for other symbols like XAUUSD and US500.

However, I'm facing little issue with the lot size for XAUUSD and US500. I try to place the order for XAUUSD for 0.01 but instead of passing the 0.01 I have to pass 0.00001 value for XAUUSD 0.01 Lot Size.

For the US500 I have to pass this volume 0.00001 which place the order for US500 but for 1.00 Standard Lot size which is fine because in cTrader US500 support minimum lot size of 1.00 but I want to pass 1.0 for that not 0.00001. Can you please check both of the symbols and other symbols.

Thank you so much - Looking forward to your response

Edit: 11 APR 2023

Please note: Other Forex pairs are working fine with the lot size like EURUSD, GBPUSD, AUDUSD. For them I pass the volume 0.01 and it open the lot size 0.01 for me.

traderpedroso commented 1 year ago

Wow, great man. It is working like a Cham now. It also fix some other problem that I were facing like I were not available to place order or get the quote['ask'] for other symbols like XAUUSD and US500.

However, I'm facing little issue with the lot size for XAUUSD and US500. I try to place the order for XAUUSD for 0.01 but instead of passing the 0.01 I have to pass 0.00001 value for XAUUSD 0.01 Lot Size.

For the US500 I have to pass this volume 0.00001 which place the order for US500 but for 1.00 Standard Lot size which is fine because in cTrader US500 support minimum lot size of 1.00 but I want to pass 1.0 for that not 0.00001. Can you please check both of the symbols and other symbols.

Thank you so much - Looking forward to your response

Edit: 11 APR 2023

Please note: Other Forex pairs are working fine with the lot size like EURUSD, GBPUSD, AUDUSD. For them I pass the volume 0.01 and it open the lot size 0.01 for me.

This is not a problem, it's the calculation of tick size for assets like gold or index, which have a different tick size compared to assets like EURUSD. In reality, you will have to manually calculate the tick size for each asset. It is not possible to use the same tick size for all assets. Therefore, you should create a symbol list with the tick size for each asset individually. The best way to do this is to directly write it in your code. For example, TICKGOLD = 0.01 * TICKSIZE. Example tick size for EURUSD is 0.00001 if your broker offer 5 digits, some have only 4 digits

ghost commented 1 year ago

Perfect, Thank you so much for all of your help. I created and add the TICKSIZE for pairs I use most.

Last thing, is there any upcoming plan to add the Take Profit and Stoploss to the market order or existing position? Because none of them are working for me. I'm creating the Limit and Stop order in netting account to set TP and SL. But it is not for the Hedge Account.

But having the pre-define TP and SL will reduce lot of work and work great for both Netting and Hedge Account. According to the documentation the TP and SL should work but it is not. So, I have to make it None.

response = client.buy(pair, volume, stoploss=None, takeprofit=None)

Please let me know if I'm missing something or it'll be in the upcoming updates?

Moreover, I recommend you to create the Discord Server that will reduce lot of FAQ for you and we can help other developers and I believe cTrader is better than MT4/MT5 as it's provide API.

Thanks

Edit: 11 APR 2023

traderpedroso commented 1 year ago

Perfect, Thank you so much for all of your help. I created and add the TICKSIZE for pairs I use most.

Last thing, is there any upcoming plan to add the Take Profit and Stoploss to the market order or existing position? Because none of them are working for me. I'm creating the Limit and Stop order in netting account to set TP and SL. But it is not for the Hedge Account.

But having the pre-define TP and SL will reduce lot of work and work great for both Netting and Hedge Account. According to the documentation the TP and SL should work but it is not. So, I have to make it None.

response = client.buy(pair, volume, stoploss=None, takeprofit=None)

Please let me know if I'm missing something or it'll be in the upcoming updates?

Moreover, I recommend you to create the Discord Server that will reduce lot of FAQ for you and we can help other developers and I believe cTrader is better than MT4/MT5 as it's provide API.

Thanks

Edit: 11 APR 2023

Perfect, Thank you so much for all of your help. I created and add the TICKSIZE for pairs I use most.

Last thing, is there any upcoming plan to add the Take Profit and Stoploss to the market order or existing position? Because none of them are working for me. I'm creating the Limit and Stop order in netting account to set TP and SL. But it is not for the Hedge Account.

But having the pre-define TP and SL will reduce lot of work and work great for both Netting and Hedge Account. According to the documentation the TP and SL should work but it is not. So, I have to make it None.

response = client.buy(pair, volume, stoploss=None, takeprofit=None)

Please let me know if I'm missing something or it'll be in the upcoming updates?

Moreover, I recommend you to create the Discord Server that will reduce lot of FAQ for you and we can help other developers and I believe cTrader is better than MT4/MT5 as it's provide API.

Thanks

Edit: 11 APR 2023

I will work on TP and SL! regarding netting accounts. You can place an opposite order that will close the trade. I am not sure if your broker allows this, but either way, I will solve this in case it is not a limitation problem of the FIX API Thank you for your feedback

ghost commented 1 year ago

Yes, I'm currently using BuyLimit and StopLimit for Take Profit and Stop Loss for netting account. Looking forward to the pre-define Take Profit and Stop Loss.

Thank you!

ghost commented 1 year ago

Hi @traderpedroso,

Hope you doing good. I'm running the app from more than a month now and everything seems good. However, the only thing I'm missing is the TP and SL setup in a position.

Just checking again about the Position TP and SL option if we can add it somehow. Because creating the alternative order is not a good practice. So, is there way we can make it happen?

Or there is anyway we can create cBot that implement fixed TP and SL on each position? (Again not a good practice when we have multiple accounts)

Looking forward to your message Thanks

traderpedroso commented 1 year ago

Hi @traderpedroso,

Hope you doing good. I'm running the app from more than a month now and everything seems good. However, the only thing I'm missing is the TP and SL setup in a position.

Just checking again about the Position TP and SL option if we can add it somehow. Because creating the alternative order is not a good practice. So, is there way we can make it happen?

Or there is anyway we can create cBot that implement fixed TP and SL on each position? (Again not a good practice when we have multiple accounts)

Looking forward to your message Thanks Everything's great, my friend. In the latest version, we've added the take profit and stop loss features. I'd recommend checking out the documentation. But be aware that the authentication process and other functions have changed. You'll need to adapt your bot to the new API overhaul. The stop loss and take profit features currently only work for market orders, not pending orders. As of now, we haven't found a solution for this. Pay attention to the disclaimer at the end about TP and SL. Personally, I added a rule: if there are no orders, close all.