n1nj4z33 / iqoptionapi

IQ Option API 4.x (Python 2.7) The project is obsolete and is not supported because of problems with access to IQ Options in Russia
119 stars 539 forks source link

wee lost candles now :( #88

Open remarco opened 6 years ago

remarco commented 6 years ago

something changed. no more candles data :( i dont know what. any patch for this????

for me write error

Traceback (most recent call last): File "C:\iqoptionbot\bot_data.py", line 22, in for candles in data: TypeError: 'NoneType' object is not iterable

2018-04-10 23:20:24,581 {"name":"timeSync",

luidelia commented 6 years ago

from 6:30 pm it does not work...

suddar commented 6 years ago

fix it pls

remarco commented 6 years ago

I not a programmer and i think i cant solve this.... wee can only wait for someone who can....

luidelia commented 6 years ago

someone has news???

remarco commented 6 years ago

nop... i tray to find what was changed in candles request but find nothing :( i dont know how to find...

SeanStayn commented 6 years ago

I'm new with this code, but I have a first solution to solve this problem:

Sorry, the following Instruction is for another iqoption repo

Please see the messages below!

luidelia commented 6 years ago

We agree that the request and response has changed, but not with your changes to the api.py file, maybe you use other api? This is api.py

SeanStayn commented 6 years ago

You are right, SORRY, I use this repo: https://github.com/bitte-ein-bit/IQOption-Api

But the new request is the following: {"name":"sendMessage","request_id":"15","msg":{"name":"get-candles","version":"2.0","body":{"active_id":1,"size":60,"to":1523488183,"count":1}}}

remarco commented 6 years ago

SeanStayn ty for info... i no time to make changes now but tomorow i check this solution... ty for info:)

SeanStayn commented 6 years ago

I have taken a look at this repo, you must change the request in this file: https://github.com/n1nj4z33/iqoptionapi/blob/master/iqoptionapi/ws/chanels/candles.py

And if you want to use the request_id as well, you have to change the send_websocket_request in the api.py. You can try to change the following code..

def send_websocket_request(self, name, msg):
        """Send websocket request to IQ Option server.
        :param str name: The websocket request name.
        :param dict msg: The websocket request msg.
        """
        logger = logging.getLogger(__name__)

        data = json.dumps(dict(name=name,
                               msg=msg))
        logger.debug(data)
        self.websocket.send(data)

... to this code (I have not tested it, but it should work:

def send_websocket_request(self, name, msg, request_id=None):
        """Send websocket request to IQ Option server.
        :param str name: The websocket request name.
        :param dict msg: The websocket request msg.
        """
        logger = logging.getLogger(__name__)
        if request_id is None:
             data = json.dumps(dict(name=name,
                               msg=msg))
        else:
              data = json.dumps(dict(name=name,request_id=request_id
                               msg=msg))
        logger.debug(data)
        self.websocket.send(data)

AND the response message comes here in on_message: https://github.com/n1nj4z33/iqoptionapi/blob/master/iqoptionapi/ws/client.py

(!message in this case doesn't contain a data attribute anymore. It has changed to "candles"!)

elif message["name"] == "candles":
            self.api.candles.candles_data = message["msg"]["data"]
codeChaba commented 6 years ago

SeanStayn, thanks for the quick reaction. I have now modified my code accordingly (I'm using harwees API (https://github.com/harwee/IQOption-Api/issues), and I am recieving a message, but some things about the reply are different if I see it correctly:

{ u'msg': { u'candles': [{u'from': 1523537640, u'min': 1.23246, u'max': 1.232645, u'volume': 0, u'to': 1523537700, u'close': 1.2325, u'open': 1.2326, u'id': 168315}]}, u'status': 2000, u'name': u'candles', u'request_id': u'15'}

it seems like the active_id property (the market index) does not get send anymore. Do I have to map the request id to marketplaces or is there a more convenient way?

ghost commented 6 years ago

Try on client.py: self.api.send_websocket_request('subscribeMessage', {"name":"candle-generated","params":{"routingFilters":{"active_id":1,"size":60}}})

In all time returns this: {"name":"candle-generated","msg":{"active_id":1,"size":60,"at":1523538897029933427,"from":1523538840,"to":1523538900,"id":168335,"open":1.231655,"close":1.231865,"min":1.231655,"max":1.23189,"ask":1.232005,"bid":1.231725,"volume":0}}

codeChaba commented 6 years ago

warleyolf, does the message you mention subscribe to regular updates (like does the api automatically send the values each time a new candle finishes)?

SeanStayn commented 6 years ago

Okay, these are two different methods..

  1. The following request gets a specific number of candles with a specific time:{"name":"sendMessage","request_id":"15","msg":{"name":"get-candles","version":"2.0","body":{"active_id":1,"size":60,"to":1523488183,"count":1}}}

  2. The following request subscribes the canldes, so you get the newest candle: {"name":"subscribeMessage", "msg": {"name":"candle-generated","params":{"routingFilters":{"active_id":1,"size":60}}}

The question is what you want.. Do you need the last 100 candles for analyzing or something else OR do you need the newest candle, to see the current market value?!

codeChaba commented 6 years ago

thank you for your quick answer. I actually kinda need both and I wan't aware of 2. being a thing, thats pretty cool!

what I was asking before is, with 1. the response does not specify the active_id of the requested candle data anymore, like it did before the update. Am I right? I currently use the request id parameter as a substitute for that (by setting the request_id to the marketplace_id when I send the request message). Seems to work so far

SeanStayn commented 6 years ago

what I was asking before is, with 1. the response does not specify the active_id of the requested candle data anymore, like it did before the update. Am I right?

If I understand it right, yes! But perhaps, IQO will change this in the next days!?

luidelia commented 6 years ago

Ty @SeanStayn but for me not working with this repo, @remarco have you tried?

remarco commented 6 years ago

bad lyck :( my knowledge is insufficient

kazi308 commented 6 years ago

Hi @SeanStayn is it possible for you to repost the instructions for the https://github.com/bitte-ein-bit/IQOption-Api repo? That would be much appreciated.

codeChaba commented 6 years ago

ok I got it to work correctly, I am using a different repository, but maybe this helps you guys as well:

The websocket api communicates with the IQoption server using JSON-Messages. In the recent update, the message format for the message you need to send to request candle data changed. @kazi308 Im not using the bitte-ein-bit version, but this should work either way:

to send the request for new candles, use this function:

def update_candle_data(self,market_name,interval,count,end_time):
        self.send_socket_message("sendMessage",{"name":"get-candles",
                                                "version":"2.0",
                                                "body":{"active_id":self.instruments_to_id[market_name],  -                                                    
                                                "size":interval,"to":end_time,"count":count}},
                                                  str(self.instruments_to_id[market_name]))

where market_name is given as string, interval marks the candle size (in seconds), count is the number of candles you want and end-time is the last timepoint. the request_id is a parameter that you can assign. Since the new message format for some reason doesn't return the market_id with the candles anymore, I am using the request_id to specify the market name (which works as a workaround). To send the message correctly, I added request_id to the send function as an optional parameter (the functionality stays the same if no third parameter is given:

def send_socket_message(self,name,msg,request_id=None):
        if request_id is None:
             data = dict(name=name, msg=msg)
        else:
              data = dict(name=name,request_id=request_id,msg=msg)
              #print (json.dumps(data))
        self.socket.send(json.dumps(data))

example call would be
api.update_candle_data("EURUSD",60,10,time.time()) for the last 10 60 seconds candles.

For the message to be recieved correctly, add a member variable to store them, directly under class IQOption: candle_data={}

then go into the on_socket_message() function and add:

 elif message["name"] == "candles":
            self.parse_candles_message(message["msg"],int(message["request_id"]))

now just add the parse_candles_message(...) function:

def parse_candles_message(self,message,market_id):  
        self.__latest_candles_data = message["candles"]
        duration=message["candles"][0]["to"]-message["candles"][0]["from"]
        market_name = self.id_to_instruments[market_id]
        if market_name in self.candle_data:
            self.candle_data[market_name][duration] = message["candles"]
        else:
            self.candle_data[market_name] = {duration:message["candles"]}

this is what worked for me

SeanStayn commented 6 years ago

@kazi308:

The problem: The request AND the response for candles has changed. The very stupid think is, that the response doesn't contain the market id anymore. My solution is to put the market id as request id into the request and get the request id back in the response and with this the market id..

One solution:

  1. Replace your update_candle_data in the api.py file with the following code:

    def update_candle_data(self,market_name,interval,start_time,end_time):
        """
            interval (seconds)
            start_time (integer timestamp) 
            end_time (integer tiestamp)
        """
        count = int((end_time-start_time)/interval)+1
        #{{"name":"get-candles","version":"2.0","body":{"active_id":1,"size":60,"to":1523488183,"count":1}}}
        marketId = self.instruments_to_id[market_name]
        self.send_socket_message("sendMessage", {"name": "get-candles", "version": "2.0", "body": {"active_id":marketId,"size":interval,"to":end_time,"count":count}}, "{}".format(marketId))
  2. Replace the following code in the on_socket_message method in the api.py file:

    elif messagename == "candles":
            self.parse_candles_message(message)
  3. Replace your parse_candles_message in the api.py file with the following code:

    def parse_candles_message(self,message):
        self.__latest_candles_data = message["msg"]["candles"]
        market_name = self.id_to_instruments[int(message["request_id"])]
        duration = message["msg"]["candles"][-1]['to'] - message["msg"]["candles"][-1]['from']
        if market_name in self.candle_data:
            self.candle_data[market_name][duration] = message["msg"]["candles"][:-1]
        else:
            self.candle_data[market_name] = {duration:message["msg"]["candles"][:-1]}
  4. Replace your send_socket_message in the api.py file with the following code:

    def send_socket_message(self, name, msg, msg_id=None, log=True):
        if msg_id is None:
            msg_id = "{}".format(randint(0, 1000))
        data = {"name": name, "request_id": msg_id, "msg": msg}
        if log:
            self.logger.debug("send_socket_message: {0}".format(data))
            self.socket.send(json.dumps(data))
  5. Add the following line at the top of the api.py file: from random import randint

  6. This is an example code, to see how you can access the candle data:

    # last 10 candles with an interval of 10 seconds
    api.update_candle_data('EURUSD',10,int(time.time())-100,int(time.time()))
    time.sleep(1)
    lastCandles = api.candle_data['EURUSD'][10]
    for candle in lastCandles:
     print(candle['from'])
     print(candle['to'])
     print(candle['open'])
     print(candle['close'])
     print(candle['max'])
     print(candle['min'])
  7. You may have to do the formatting of the code yourself (indenting)

kazi308 commented 6 years ago

Hi @codeChaba and @SeanStayn, thank you for the information. I manged to get it working using codeChaba code. I would like to know how to enable websocket debug?

codeChaba commented 6 years ago

@kazi308 what I did is just put a print message in the functions that send and receive messages, in order to see exactly what the format is that gets send out and received. Actually it's pretty cool because there are a lot of messages that my client just ignores: leaderboards, commission info, etc.

kazi308 notifications@github.com schrieb am So., 15. Apr. 2018, 16:12:

Hi @codeChaba https://github.com/codeChaba and @SeanStayn https://github.com/SeanStayn, thank you for the information. I manged to get it working using codeChaba code. I would like to know how to enable websocket debug?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/n1nj4z33/iqoptionapi/issues/88#issuecomment-381409718, or mute the thread https://github.com/notifications/unsubscribe-auth/AkTjfmgCbkdhnCPAWXofZK36YtsgQ9vAks5to1VbgaJpZM4TO8Al .

SeanStayn commented 6 years ago

@kazi308:

I'm using Chrome:

  1. Go to IqOptions trade room
  2. Open DevTools by pressing Command+Option+I (Mac) or Control+Shift+I (Windows, Linux). This shortcut opens the Console panel.
  3. Select the "Network" tab
  4. Select the "WS" tab in the "Network" tab
  5. Refresh the page (F5)
  6. After loading you can see the open web sockets. Double-click on the web socket and you can see what you want! :)

Have fun!

kazi308 commented 6 years ago

Thanks for the info guys!

luidelia commented 6 years ago

Sostituendo questo data = {"name": "get-candles", "version": "2.0", "body": {"active_id":active_id,"size":duration,"to":(self.api.timesync.server_timestamp - (duration * amount)) ,"count":amount}}

in candles.py funziona, ma la risposta è ancora grezza, riesco a recuperare i dati elaborandoli nel mio script.

remarco commented 6 years ago

I not understand where make the changes :( @kazi308 how you did it? can you write files where i must made changes ?

Lu-Yi-Hsun commented 6 years ago

thank @SeanStayn I fix iqoptionapi https://github.com/Lu-Yi-Hsun/iqoptionapi

run on python3 success sample code

from iqoptionapi.api import IQOptionAPI
import datetime
import time
import logging
logging.basicConfig(format='%(asctime)s %(message)s')

api = IQOptionAPI("iqoption.com", "email","password")

api.connect()
time.sleep(1.5)
print ('Your current blance is: {:.2f}'.format(api.profile.balance))

api.buy(1, 1, "turbo", "call")
api.getcandles(1, 1, 3)
            #getcandles(ACTIVES,interval,count)
            #ACTIVES:look constants.py file
            #interval: time interval
            #count:how many candles you want to get from now to past
#somehow we need that wait. Don't ask me why. Otherwise we have no data
time.sleep(2)
data = api.candles.candles_data

print(data)
remarco commented 6 years ago

@SeanStayn and now change your password :)

Lu-Yi-Hsun commented 6 years ago

@remarco please forget it QQ

remarco commented 6 years ago

Super ty... i broke my brain thinking where put changes :D ... @SeanStayn it work !!!

remarco commented 6 years ago

@SeanStayn are you add parser for candles data? from data get candles? or this must be done in my script?

SeanStayn commented 6 years ago

@SeanStayn and now change your password :)

I think you don't mean my password. ;)

I'm glad, that I could help you guys!

@remarco: What do you mean? How should your dictionary with candles look like?

remarco commented 6 years ago

this like:

data = api.candles.candles_data for candles in data: st = datetime.datetime.fromtimestamp(candles[0]+60).strftime('%Y-%m-%d %H:%M:%S') print st, candles

OUTPUT IS: Your current blance is: 203584.95 2018-03-12 21:30:00 [1520882940, 1233520, 1233520, 1233530, 1233510] 2018-03-12 21:31:00 [1520883000, 1233520, 1233580, 1233580, 1233515] 2018-03-12 21:32:00 [1520883060, 1233580, 1233755, 1233755, 1233580] 2018-03-12 21:33:00 [1520883120, 1233755, 1233755, 1233790, 1233750] 2018-03-12 21:34:00 [1520883180, 1233755, 1233740, 1233770, 1233710] 2018-03-12 21:35:00 [1520883240, 1233740, 1233640, 1233750, 1233640] 2018-03-12 21:36:00 [1520883300, 1233640, 1233645, 1233645, 1233530] 2018-03-12 21:37:00 [1520883360, 1233645, 1233635, 1233645, 1233600]

remarco commented 6 years ago

in ws\objects\candles.py i changed class Candles(Base): """Class for IQ Option Candles websocket object."""

def __init__(self):
    super(Candles, self).__init__()
    self.__name = "candles"
    self.__candles_data = None

to class Candles(Base): """Class for IQ Option Candles websocket object."""

def __init__(self):
    super(Candles, self).__init__()
    self.__name = "sendMessage"
    self.__candles_data = None

and have output. not clear but have candles. output data: [{u'from': 1523959080, u'min': 1.237145, u'max': 1.237275, u'volume': 0, u'to': 1523959140, u'close': 1.237225, u'open': 1.237275, u'id': 172459}, {u'from': 1523959140, u'min': 1.2372, u'max': 1.23729, u'volume': 0, u'to': 1523959200, u'close': 1.23728, u'open': 1.23723, u'id': 172460}] output candles: {u'from': 1523959080, u'min': 1.237145, u'max': 1.237275, u'volume': 0, u'to': 1523959140, u'close': 1.237225, u'open': 1.237275, u'id': 172459} {u'from': 1523959140, u'min': 1.2372, u'max': 1.23729, u'volume': 0, u'to': 1523959200, u'close': 1.23728, u'open': 1.23723, u'id': 172460}

i think in this file class Candle(object) must be rewrite. but i not understand from where this properties get data.. :(

luidelia commented 6 years ago

@remarco i have parse this response in my script in this way:

`
api.getcandles(1, 1, 1) data = api.candles.candles_data

        try:
            data_val = []

            splt = str(data).split(',')
            for line in splt:
                line = line.split(':')
                data_val.append(line[1])

            current_candle_time = int(data_val[4])
            current_candle_open = float(data_val[6])
            current_candle_close = float(data_val[5])
            current_candle_high = float(data_val[2])
            current_candle_low = float(data_val[1]) 

`

remarco commented 6 years ago

ty @luidelia this is one solution. i tray this but i like if someon change built in .... but this be ok right now:)

ok i tray this...
this not work good for me. its work oly for data_val.append(line[1]) another lines not work. i need last 5 candles to compare end math .. i need values open and close from last 5 candles .

luidelia commented 6 years ago

ok, try this: api.getcandles(1, 60, 5) now you can analyze the data of the 5 candles in the array data, you can do it via a for loop: `for cand in data:
data_val = []

        splt = str(cand).split(',')
        for line in splt:
            line = line.split(':')
            data_val.append(line[1])

        candle[i][0] = int(data_val[4])
        candle[i][1] = float(data_val[6])
        candle[i][2] = float(data_val[5])
        candle[i][3] = float(data_val[2])
        candle[i][4] = float(data_val[1])

        i +=1 `

I have not tried it but it should work

remarco commented 6 years ago

no luck :( IndexError: list assignment index out of range .... something there is no right. line return [" u'id'", ' 172745}'] from this wee cant get candle[i][0]

aaah my fail. i use diferent spaces but i not get 4 candles data [[1523994240, 1.237165, 1.237145, 1.23719, 1.237145], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]

luidelia commented 6 years ago

It works

` api.getcandles(1, 60, 5)

time.sleep(0.25) data = api.candles.candles_data

i = 0

candle = [[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]] for cand in data: data_val = [] splt = str(cand).split(',') for line in splt: line = line.split(':') data_val.append(line[1])

candle[i][0] = int(data_val[4])
candle[i][1] = float(data_val[6])
candle[i][2] = float(data_val[5])
candle[i][3] = float(data_val[2])
candle[i][4] = float(data_val[1])

i +=1

print candle

`

remarco commented 6 years ago

look like i do something wrong :( no work for me . for some reason i not value:

candle[i][0] = int(data_val[4]) IndexError: list index out of range

oooo ! ty i get it to work... ty. its hard to understand spaces if you not a programmer.

kazi308 commented 6 years ago

Hi @remarco I am using https://github.com/harwee/IQOption-Api repo and I followed codeChaba instructions.

remarco commented 6 years ago

@kazi308 i understand that... but this api work too from there https://github.com/Lu-Yi-Hsun/iqoptionapi

codeChaba commented 6 years ago

@SeanStayn Do you know what the API call / message for checking binary option returns is? Like say I want to run a bot on all pairs that have >85% returns on the 1m, is there a request message for a list of all instruments with current returns?

remarco commented 6 years ago

no . i dont know. if you bay you can check the %... somewere i write this in coments.

Lu-Yi-Hsun commented 6 years ago

@codeChaba you mean return which profit >85%?

sample "EURUSD" :99% "USDJP" :88% return all profit >85

codeChaba commented 6 years ago

Exactly, but ofc the filtering is not the problem, I'm looking for how to retrieve the individual numbers for all currencies

Anson notifications@github.com schrieb am Mi., 18. Apr. 2018, 13:21:

@codeChaba https://github.com/codeChaba you mean return which profit

85%?

sample "EURUSD" :99% "USDJP" :88% return all profit >85

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/n1nj4z33/iqoptionapi/issues/88#issuecomment-382353437, or mute the thread https://github.com/notifications/unsubscribe-auth/AkTjfr7lpm0SwY-FUdnMmaGEokJ3MI_gks5tpyGcgaJpZM4TO8Al .

remarco commented 6 years ago

maby this???? {"name":"sendMessage","request_id":"2","msg":{"name":"get-currencies-list","version":"2.0","body":{}}}

someon please get answer for this

and any changes i think is there {"name":"subscribeMessage","msg":{"name":"currency-updated","version":"1.0"}}

Lu-Yi-Hsun commented 6 years ago

@codeChaba sample code (sucess on python3 ) need use my Repositories https://github.com/Lu-Yi-Hsun/iqoptionapi

from iqoptionapi.api import IQOptionAPI
import iqoptionapi.constants as OP_code
import time
import iqoptionapi.constants as OP_code
import logging
#logging.basicConfig(format='%(asctime)s %(message)s')
class Binary_Option:
    def __init__(self,email,password):
        self.email=email
        self.password=password
        self.suspend = 0.5
        self.connect()
        self.init_info=None
    def connect(self):
        self.api = IQOptionAPI("iqoption.com", self.email, self.password)
        self.api.connect()
        time.sleep(self.suspend)

    def get_all_init(self):
        self.api.api_option_init_all_result = None
        self.api.get_api_option_init_all()
        while self.api.api_option_init_all_result == None:
            pass
        self.init_info=self.api.api_option_init_all_result
    def get_profit(self,ACTIVES):
        return (100.0-self.init_info["result"]["turbo"]["actives"][str(OP_code.ACTIVES[ACTIVES])]["option"]["profit"]["commission"])/100.0

bo=Binary_Option( "email","password")
bo.get_all_init()
for ac in OP_code.ACTIVES:
    try:
        prof=bo.get_profit(ac)
        print(ac,prof)
    except:
        pass

output sample

EURUSD 0.83
EURGBP 0.87
GBPJPY 0.86
EURJPY 0.84
GBPUSD 0.85
USDJPY 0.75
AUDCAD 0.79
NZDUSD 0.78
USDRUB 0.84
AMAZON 0.67
APPLE 0.65
GOOGLE 0.65
USDCHF 0.83
EURUSD-OTC 0.88
EURGBP-OTC 0.87
USDCHF-OTC 0.87
NZDUSD-OTC 0.87
AUDCAD-OTC 0.88
ALIBABA 0.65
AUDUSD 0.8
USDCAD 0.75
AUDJPY 0.82
GBPCAD 0.87
GBPCHF 0.87
GBPAUD 0.87
EURCAD 0.82
CHFJPY 0.82
CADCHF 0.83
EURAUD 0.83
USDNOK 0.87
EURNZD 0.84
USDSEK 0.86
USDTRY 0.87
remarco commented 6 years ago

ooo cool :)