4

I have obtained the OHLC values from the iqoption and trying to find out a way to use it with MT5.
Here is how I got the values:

import time
from iqoptionapi.stable_api import IQ_Option
I_want_money=IQ_Option("email","password")
goal="EURUSD"
print("get candles")
print(I_want_money.get_candles(goal,60,111,time.time()))

The above code library is here: iqoptionapi

The line: I_want_money.get_candles(goal,60,111,time.time()) output json as : Output of the command

Now I am getting json in the output so it work like an API, I guess so.

Meanwhile, I try to create a Custom Symbol in MT5 as iqoption. Now I just wanted to add the data of the OHLC from the API to it, so that it will continue fetching data from the Iqoption and display the chart on the chart window for the custom symbol iqoption.

But I am not able to load it in the custom symbol. Kindly, help me.

Edited

This is the code for live streaming data from the iqoption:

from iqoptionapi.stable_api import IQ_Option
import logging
import time
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s %(message)s')
I_want_money=IQ_Option("email","password")
I_want_money.start_candles_stream("EURUSD")
thread=I_want_money.collect_realtime_candles_thread_start("EURUSD",100)
I_want_money.start_candles_stream("USDTRY")
thread2=I_want_money.collect_realtime_candles_thread_start("USDTRY",100)
time.sleep(3)
#Do some thing
ans=I_want_money.thread_collect_realtime.items()
for k, v in ans:
    print (k, v)
I_want_money.collect_realtime_candles_thread_stop(thread)
I_want_money.stop_candles_stream("EURUSD")
I_want_money.collect_realtime_candles_thread_stop(thread2)
I_want_money.stop_candles_stream("USDTRY")
glibdud
  • 7,550
  • 4
  • 27
  • 37
Jaffer Wilson
  • 7,029
  • 10
  • 62
  • 139
  • Please let me know the answer. – Jaffer Wilson Jun 29 '18 at 11:17
  • Seems doable enough if you want to backtest your strategy in MT5 using the data you fetched. Do you want to test it in the graphical interface? I'll try to help you out if this is your scenario. – trust512 Jun 29 '18 at 11:25
  • I want it to display on the screen as well as in the backtest. The realtime data fetched from the API and then displayed on the screen using custom symbol or any other methodology. – Jaffer Wilson Jun 29 '18 at 11:38
  • I just want that the should get accessible through the custom symbol in MT5. If this gets possible then backtest and rest things are already done as far as I know. – Jaffer Wilson Jun 29 '18 at 11:44
  • 1
    Yes @JafferWilson but that implies different (much harder) approach. Generally, this is a big thing to do on MT platforms and you are better off going to professional platforms - like JForex - as MT is (IMO) a playground for beginners (stating after years of experience with it). As much as I'd like to help you and receive the bounty - it's not worth the effort. I work on this field for years now - having my own algo trading platform integrated with JForex API. – trust512 Jun 29 '18 at 14:55
  • @trust512 it might be a time consuming or worthless, but most of my work I did in MT5. It is not at all possible for me to shift to new platform and start it from ground zero. Kindly, let me know how I can make the above integration possible, please. – Jaffer Wilson Jul 02 '18 at 04:41

2 Answers2

4

Ok, you need to
1. receive the feed from the broker(I hope you succeeded)
2. write it into a file
** (both - python) **
3. read and parse it
4. add it to the history centre/marketWatch
** (both - mt5) **

  1. So, you receive data as a string after I_want_money.get_candles(goal,60,111,time.time()) this string might be json or json-array.

  2. The important question is of course the path you are going to put the data. An expert in MQL45 can access only two folders (if not applying dll): C:\Users\MY_NAME_IS_DANIEL_KNIAZ\AppData\Roaming\MetaQuotes\Terminal\MY_TERMINAL_ID_IN_HEX_FORMAT\MQL4\Files and C:\Users\MY_NAME_IS_DANIEL_KNIAZ\AppData\Roaming\MetaQuotes\Terminal\Common\Files in the latter case you need to open a file with const int handle=FileOpen(,|*| FILECOMMON);

In order to parse json, you can use jason.mqh https://www.mql5.com/en/code/13663 library (there are few others) but as far as i remember it has a bug: it cannot parse array of objects correctly. In order to overcome that, I would suggest to write each tick at a separate line. And the last, you will recieve data from your python application at random time, and write it into Common or direct folder. The MT5 robot will read it and delete. Just to avoid confusion, it could be better to guarantee that a file has a unique name. Either random (random.randint(1,1000)) or milliseconds from datetime can help.

So far, you have python code:

 receivedString = I_want_money.get_candles(goal,60,111,time.time())  
 filePath = 'C:\Users\MY_NAME_IS_DANIEL_KNIAZ\AppData\Roaming\MetaQuotes\Terminal\MY_TERMINAL_ID_IN_HEX_FORMAT\MQL4\Files\iqoptionfeed'  
 fileName = os.path.join(filePath,"_"+goal+"_"+str(datetime.now())+".txt")   
 file = open(fileName, "w")  
 for string_ in receivedString:  
     file.write(string_)  
 file.close()  

In case you created a thread, each time you receive an answer from the thread you write such a file.

Next, you need that data in MT5. The easiest way is to loop over the existing files, make sure you can read them and read (or give up if you cannot) and delete after reading, then proceed with the data received. The easiest and faster way is to use 0MQ of course, but let us do it without dll's. In order to read the files, you need to setup a timer that can work as fast as possible, and let it go. Since you cannot make a windows app sleeping less then 15.6ms, your timer should sleep this number of time.

string path;
int OnInit()
  {
   EventSetMillisecondTimer(16);    
   path="iqoptionfeed\\*";
  }
void OnDeinit(const int reason) {   EventKillTimer();   }

string _fileName;
long _search_handle;
void OnTimer()
  {
   _search_handle=FileFindFirst(path,_fileName);
   if(_search_handle!=INVALID_HANDLE)
      {
       do
         {
          ResetLastError();
          FileIsExist(_fileName);
          if(GetLastError()!=ERR_FILE_IS_DIRECTORY)
             processFile(path+_fileName);
         }
       while(FileFindNext(_search_handle,_fileName));
       FileFindClose(_search_handle);
      }
  }  

this piece of code loops the folder and processes each file it managed to find. Now reading the file (two functions) and processing the message inside it:

void processFile(const string fileName)
  {
   string message;
   if(ReadFile(fileName,message))
      processMessage(message,fileName);
  }
bool ReadFile(const string fileName,string &result,const bool common=false)
  {
   const int handle = FileOpen(fileName,common?(FILE_COMMON|FILE_READ):FILE_READ);
   if(handle==INVALID_HANDLE)
     {
      printf("%i - failed to find file %s (probably doesnt exist!). error=%d",__LINE__,fileName,GetLastError());
      return(false);
     }
   Read(handle,result);
   FileClose(handle);
   if(!FileDelete(fileName,common?FILE_COMMON:0))
      printf("%i - failed to delete file %s/%d. error=%d",__LINE__,fileName,common,GetLastError());
   return(true);
  }
void Read(const int handle,string &message)
  {
   string text="";
   while(!FileIsEnding(handle) && !IsStopped())
     {
      text=StringConcatenate(text,FileReadString(handle),"\n");
     }
   //printf("%i %s - %s.",__LINE__,__FUNCTION__,text);
   message=text;
  }

And the last but not the least: process the obtained file. As it was suggested above, it has a json formatted tick for each new tick, separated by \r\n.
Our goal is to add it to the symbol. In order to parse json, jason.mqh is an available solution but you can parse it manually of course.

void processMessage(const string message,const string fileName)
  {
   string symbolName=getSymbolFromFileName(fileName);
   if(!SymbolSelect(symbolName,true))
     {
      if(!CustomSymbolCreate(symbolName))
         return;
     }
   string lines[];
   int size=StringSplit(message,(ushort)'\n',lines);
   for(int i=0;i<size;i++)
     {
      if(StringLen(lines[i])==0)
        continue;
      CJAVal jLine(jtUNDEF,NULL);
      jLine.Deserialize(lines[i]);
      MqlTick mql;
      //here I assume that you receive a json file like " { "time":2147483647,"bid":1.16896,"ask":1.16906,"some_other_data":"someOtherDataThatYouMayAlsoUse" } "
      mql.time=(datetime)jLine["time"].ToInt();
      mql.bid=(double)jLine["bid"].ToDbl();
      mql.ask=(double)jLine["ask"].ToDbl();
      ResetLastError();
      if(CustomTicksAdd(symbolName,mql)<0)
          printf("%i %s - failed to upload tick: %s %s %.5f %.5f. error=%d",__LINE__,__FILE__,symbolName,TimeToString(mql.time),mql.bid,mql.ask,GetLastError()); 
     }
  }
string getSymbolFromFileName(const string fileName)
  {
   string elements[];
   int size=StringSplit(fileName,(ushort)'_',elements);
   if(size<2)
      return NULL;
   return elements[1];
  }

Do not forget to add debugging info and request for GetLastError() is for some reason you get errors.

Can this work in a back tester? Of course not. Fist, OnTimer() is not supported in MQL tester. Next, you need some history record in order to make it running. If you do not have any history - Nobody can help you unlees a broker can give it to you; the best idea could be to start collecting and storing it right now, and when the project is ready (maybe another couple months), you will have it ready and be able to test and optimize the strategy with the available dataset. You can apply the collected set into tester (MQL5 is really the next step in algo trading development compared to MQL4), either manually or with something like tickDataSuite and its Csv2Fxt.ex4 file that makes HST binary files that the tester can read and process; anyway that is another question and nobody can tell you if your broker stores their data somewhere to provide it to you.

Daniel Kniaz
  • 4,603
  • 2
  • 14
  • 20
  • Thank you, Daniel, for your hep. At least it something that I haven't came across till now and I guess it will work too. But currently, I won't be able to test it as I missed the deadline and I don't know when will I be going for this. I was expecting such answers from people here till 2 days back from now.... – Jaffer Wilson Jul 06 '18 at 04:51
  • Welcome! It took some time to collect some pieces of code from different places in order to provide an optimized version of the code, that is why the reply was not prompt – Daniel Kniaz Jul 06 '18 at 08:05
  • Dear Daniel, Can you bundle up the above code and attach the link with your answer? That will help me. If I can get the runnable code. Please let me know. Thank you in advanced. – Jaffer Wilson Oct 03 '18 at 14:29
  • Sorry didnt understand how I can help you. The examples are here, I think you can copy them, of course MT for MT, python - in python so there are two different files – Daniel Kniaz Oct 03 '18 at 21:01
  • Do I need to call the Python multiple times for getting the values? And what is it in MT -- Expert, Indicator or script? Please let me know about it sir. – Jaffer Wilson Oct 04 '18 at 05:04
  • Hello Sir, I am encountering few bugs while I am implementing the code. Please help me. Here is the gist of it: https://gist.github.com/JafferWilson/a738575af448d4bf54687d9de5fcd04a . Also, from Python I am receiving 111 candles data and not the ticks in ask or bid format. So will it be possible for your code to work on the candles data too? Sir, can you help me modify the above code what you have suggested? – Jaffer Wilson Oct 04 '18 at 06:32
  • This is the format that I get from the API: `[{'close': 1.148255, 'max': 1.148255, 'from': 1538635500, 'at': 1538635510004255308, 'min': 1.148235, 'id': 347946, 'volume': 39, 'open': 1.148255, 'to': 1538635560}]` Please let me know what we can do. I haven't tried it when I asked the question and I found that your answer was acceptable. Please help me with this. I can convert the complete json to csv file as well using the python itself, if that can be easy to handle then. Sir do let me know your reply. – Jaffer Wilson Oct 04 '18 at 06:47
  • Python: I think you should add `while TRUE:` in order to request the ticks all the time, and then check that new data arrived. MT: this is an expert. Scripts are good for one-time operations, I do not think it makes sense to sleep and freeze the thread if you have experts; indicator is not good as it cannot send trade requests. About receiving candles not ticks - that is a question to the API that they provide, maybe they have different API for receiving quotes. Reqarding compilation issue: try it as script first of all, please check the updated code. it was designed for quotes not candles – Daniel Kniaz Oct 04 '18 at 08:42
  • Yes I see that. I wanted to know whether we can show candles in place of quotes as IQO api is not support the quotes but the OHLC values as I have mentioned in the comment. Please can you help me? – Jaffer Wilson Oct 04 '18 at 09:02
  • You can use `CustomRatesUpdate()` (link: https://www.mql5.com/en/docs/customsymbols/customratesupdate) to add `MqlRates` instead of `MqlTick`. Also you need to feed MqlRates using close,max,min,open,volume,from values as shown with MqlTick – Daniel Kniaz Oct 04 '18 at 11:18
1

After second-reading what you wrote (and edited) I can see you want:

  • a symbol synchronized with iqoption [ through your proxy / remotely ]
  • The symbol could be used for backtesting
  • The symbol could be used for on-screen live/strategy/indicator run

That implies operations outside strategy/indicator which MT platforms do not allow in an automated manner - you can achieve it manually by providing a data package, parsing it to CSV and importing to custom symbol creator. Well documented here.

Unfortunately, you choose a platform that by-design stands for self-contained strategies and indicators, more for beginners than professionals taking it seriously.

Refer to the link I provided and see for yourself. The official doc states you can create a custom symbol via mql ref, yet even though they state, in the foreword, it allows 3rd party providers - it's not referenced anywhere else and does not show any integration possibilities.


custom indicators

custom symbol properties

Jaffer Wilson
  • 7,029
  • 10
  • 62
  • 139
trust512
  • 2,188
  • 1
  • 18
  • 18
  • Yes I know my friend. I have referred these links. I found the documentation is weak and not understandable. Hence, I have asked question here. But since no one here on stackoverflow is interested in answering my queries, I set bounty amount so that people will get interested in helping me. But I guess no has an accurate solution. You are also giving link what I already have searched and gone through. Don't you think my friend that I might have done all my research before asking question here? – Jaffer Wilson Jul 04 '18 at 07:53
  • 1
    I provided a official-docs based answer. You didn't state you read anything in the field before attempting - so there is no reason not to post such a answer. You wanted an answer from officlal/credible sources so that's what I'm posting. Stating it's not officially possible is not a quality answer for you? – trust512 Jul 05 '18 at 13:02