使用MQL5将OHLC值从Python API集成到MT5



我已经从iqoption中获得了OHLC值,并试图找到一种将其与MT5一起使用的方法。
以下是我获得值的方法:

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()))

上面的代码库在这里:iquoptionapi

行:I_want_money.get_candles(goal,60,111,time.time())输出json为:命令的输出

现在我在输出中得到json,所以它像API一样工作,我想是这样

同时,我尝试在MT5中创建一个自定义符号iqoption。现在我只想将来自API的OHLC的数据添加到其中,这样它将继续从Iqoption获取数据,并在自定义符号iqoption的图表窗口上显示图表。

但我无法将其加载到自定义符号中。请帮帮我。

已编辑

这是来自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")

好的,您需要
1。接收来自经纪人的提要(我希望你成功)
2。将其写入文件
**(both-python)**
3。阅读并解析
4。将其添加到历史记录中心/市场观察
**(均为-mt5)**

  1. 因此,在I_want_money.get_candles(goal,60,111,time.time())这个字符串可能是json或json数组。

  2. 重要的问题当然是你要把数据放在什么路径上。MQL45专家只能访问两个文件夹(如果不应用dll):C: \Users\MY_NAME_IS_DANIEL_NIAZ\AppData\Roaming\MetaQuotes\Terminal\MY_Terminal_ID_IN_HEX_FORMAT\MQL4\Files和C: \Users\MY_NAME_IS_DANIEL_NIAZ\AppData\Roaming\MetaQuotes\Terminal\Common\Files在后一种情况下,您需要打开一个const int handle=FileOpen(|*|FILECOMMON)的文件;

为了解析json,可以使用jason.mqhhttps://www.mql5.com/en/code/13663库(其他库很少),但据我记忆所及,它有一个错误:无法正确解析对象数组。为了克服这一点,我建议在单独的一行写下每个勾号。最后,您将随机接收来自python应用程序的数据,并将其写入Common或direct文件夹。MT5机器人将读取并删除它。为了避免混淆,最好保证文件具有唯一的名称。随机(random.randint(11000))或从日期时间算起的毫秒都会有所帮助。

到目前为止,您已经有了python代码:

receivedString = I_want_money.get_candles(goal,60,111,time.time())  
filePath = 'C:UsersMY_NAME_IS_DANIEL_KNIAZAppDataRoamingMetaQuotesTerminalMY_TERMINAL_ID_IN_HEX_FORMATMQL4Filesiqoptionfeed'  
fileName = os.path.join(filePath,"_"+goal+"_"+str(datetime.now())+".txt")   
file = open(fileName, "w")  
for string_ in receivedString:  
file.write(string_)  
file.close()  

如果您创建了一个线程,每次收到来自该线程的答复时,您都会编写这样一个文件。

接下来,您需要MT5中的数据。最简单的方法是循环浏览现有文件,确保您可以读取它们并在读取后进行读取(如果不能,则放弃)和删除,然后继续处理收到的数据。当然,最简单快捷的方法是使用0MQ,但让我们在没有dll的情况下完成它。为了读取文件,你需要设置一个可以尽可能快地工作的计时器,然后让它过去。由于你不能让windows应用程序的睡眠时间少于15.6ms,你的计时器应该睡眠这个时间。

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);
}
}  

这段代码循环文件夹并处理它设法找到的每个文件。现在读取文件(两个功能)并处理其中的消息:

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;
}

最后但并非最不重要的一点是:处理获得的文件。正如上面所建议的,它为每个新的tick都有一个json格式的tick,用\r\n分隔
我们的目标是将其添加到符号中。为了解析json,jason.mqh是一个可用的解决方案,但您当然可以手动解析它。

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];
}

不要忘记添加调试信息,请求GetLastError()是因为某些原因导致的错误。

这能在背部测试仪中工作吗?当然不是。首先,MQL测试仪不支持OnTimer()。接下来,您需要一些历史记录才能使其运行。如果你没有任何历史-没有人可以帮你解锁,经纪人可以给你;最好的想法是现在就开始收集和存储它,当项目准备好(也许再过几个月)时,你就会准备好它,并能够使用可用的数据集测试和优化策略。您可以将收集的集合应用到测试仪中(与MQL4相比,MQL5实际上是算法交易开发的下一步),可以手动应用,也可以使用tickDataSuite及其Csv2Fxt.ex4文件,该文件制作测试仪可以读取和处理的HST二进制文件;无论如何,这是另一个问题,没有人能告诉你,如果你的经纪人把他们的数据存储在某个地方,以提供给你。

仔细阅读你写的(和编辑的)内容后,我可以看到你想要的:

  • 一个与iqeption同步的符号[通过您的代理/远程]
  • 该符号可用于回溯测试
  • 该符号可用于屏幕直播/策略/指示器运行

这意味着MT平台不允许在策略/指标之外以自动化方式进行操作-您可以通过提供数据包、将其解析为CSV并导入自定义符号创建者来手动实现。这里有很好的记录。

不幸的是,你选择的平台在设计上代表着独立的策略和指标,更适合初学者,而不是认真对待它的专业人士。

请参阅我提供的链接并亲自查看。官方文档指出,您可以通过mql-ref创建自定义符号,但即使他们在前言中指出,它允许第三方提供商使用-它在其他任何地方都没有引用,也没有显示任何集成的可能性。


自定义指示器

自定义符号属性

最新更新