Coisas interessantes.
Eu estou, como sempre, bisbilhotando a idéia de R. Parece-me que você é a pessoa certa para ao menos discutir a idéia.
A idéia é a seguinte.
Hoje é possível arrastar um arquivo exesh, que foi gerado pelo compilador mcl4/5, para a carta terminal.
É possível fazer um desenvolvimento para poder acorrentar um roteiro R ao gráfico?
Coisas interessantes.
Eu estou, como sempre, bisbilhotando a idéia de R. Parece-me que você é a pessoa certa para ao menos discutir a idéia.
A idéia é a seguinte.
Hoje é possível arrastar um arquivo exesh, que foi gerado pelo compilador mcl4/5, para a carta terminal.
E é possível fazer um desenvolvimento para poder acorrentar um roteiro R ao gráfico?
A propósito, sobre R :-) Você prestou sua atenção ao kit de distribuição R ?
Bem, existe uma biblioteca de diretório/tcltk, que contém R tcl incorporada. Quando um idioma/plataforma não tem facilidades, eles acrescentam tcl, aka "Ferramenta Linguagem Comum", a ela. R carecia de GUI e colocar tcl/tk nele (assim como em Python e Ruby).
Faltavam-me muitas características na MQL, exceto os gráficos, por isso consegui ATcl.
ATcl também pode fazer estatísticas :-) Outro pequeno caso de teste - cálculo de valores estatísticos básicos para um conjunto de dados. O roteiro leva Close, quantos serão dados no parâmetro de entrada
#property copyright "Maxim A.Kuznetsov" #property link "luxtrade.tk" #property version "1.00" #property strict #property script_show_inputs //--- input parameters input int DEPTH=200; #include "ATcl.mqh" const string NAMES[]={ "mean", "minimum", "maximum", "number of data", "sample standard deviation", "sample variance", "population standard deviation","population variance" }; void OnStart() { ATcl_OnInit(); ATcl *tcl=new ATcl; if (tcl==NULL || !tcl.Ready()) { ATcl_OnDeinit(); Alert("Ошибка при создании интерпретатора"); } bool ok=false; do { if (tcl.Eval("package require math::statistics")!=TCL_OK) break; tcl.Set("data",tcl.Obj(Close,0,DEPTH)); if (tcl.Eval("math::statistics::basic-stats $data")!=TCL_OK) break; Tcl_Obj stats=tcl.Result(); tcl.Ref(stats); int total=tcl.Count(stats); for(int i=0;i<total;i++) { PrintFormat("stats %d \"%s\" = %s",i,(i<ArraySize(NAMES)?NAMES[i]:"??"),tcl.String(stats,i)); } tcl.Unref(stats); ok=true; } while(false); if (!ok) { PrintFormat("Что-то пошло не так : %s",tcl.StringResult()); } delete tcl; ATcl_OnDeinit(); }
Em anexo está o roteiro. Há apenas uma linha de cálculo :-)
E mais um exemplo :-)
Vamos pegar um zip e calcular os checksums dos arquivos armazenados nele. Nós calculamos MD5 e SHA256
#property copyright "Maxim A.Kuznetsov" #property link "luxtrade.tk" #property version "1.00" #property strict #property script_show_inputs //--- input parameters input string ZIP="MQL4\\Scripts\\atcl.zip"; #include "ATcl.mqh" void OnStart() { ATcl_OnInit(); ATcl *tcl=new ATcl; if (tcl==NULL || !tcl.Ready()) { ATcl_OnDeinit(); Alert("Ошибка при создании интерпретатора"); } bool ok=false; do { if (tcl.Eval("package require vfs::zip")!=TCL_OK) break; if (tcl.Eval("package require md5")!=TCL_OK) break; if (tcl.Eval("package require sha256")!=TCL_OK) break; tcl.Set("archive",tcl.Obj(ZIP)); if (tcl.Eval("set z [ vfs::zip::Mount $archive $archive ]")!=TCL_OK) break; if (tcl.Eval("set list [ glob -directory $archive -nocomplain *.* ]")!=TCL_OK) break; Tcl_Obj list=tcl.Result(); tcl.Ref(list); int total=tcl.Count(list); // создадим новую процедуру if (tcl.Eval("proc content { name } { set f [ open $name rb ] ; set ret [ read $f ] ; close $f ; set ret }")!=TCL_OK) break; for(int i=0;i<total;i++) { string fileName=tcl.String(list,i); tcl.Set("fileName",tcl.Obj(fileName)); PrintFormat("%s",fileName); if (tcl.Eval("set content [ content $fileName ]")!=TCL_OK) { PrintFormat("Не удалось прочесть файл %s:%s",fileName,tcl.StringResult()); continue; } string sha256=tcl.StringEval("sha2::sha256 -hex -- $content"); PrintFormat(" sha256: %s",sha256); string md5=tcl.StringEval("md5::md5 -hex -- $content"); PrintFormat(" md5: %s",md5); } tcl.Unref(list); tcl.Eval("vfs::zip::Unmount $z $archive"); ok=true; } while(false); if (!ok) { PrintFormat("Что-то пошло не так : %s",tcl.StringResult()); } delete tcl; ATcl_OnDeinit(); }
Apenas para começar, uma captura de tela, é claro :-) Este é um servidor EA tcp-server em 60 linhas de mql + 60 linhas de tcl
E o próprio MQ4 do Expert Advisor:
#property copyright "Maxim A.Kuznetsov" #property link "luxtrade.tk" #property version "1.00" #property strict //--- input parameters input ushort PORT=8000; #include "ATcl.mqh" ATcl *tcl=NULL; // интерпретатор Tcl_Obj StartServer=0,StopServer=0,SendMsg=0,SymName=0,PortNum=0; // объекты Tcl - имена команд и имя символа int OnInit() { ATcl_OnInit(); // включить ATcl tcl=new ATcl; // создать интерпретатор if (tcl==NULL || !tcl.Ready()) { return INIT_FAILED; } // прочтём исходник c командами if (tcl.Eval("source ./MQL4/Experts/atcl_tcpserv.tcl")!=TCL_OK) { PrintFormat("Error in Source:%s",tcl.StringResult()); return INIT_FAILED; } StartServer=tcl.Ref(tcl.Obj("StartServer")); // команда запуска сервера StopServer=tcl.Ref(tcl.Obj("StopServer")); // остановка сервера SendMsg=tcl.Ref(tcl.Obj("SendMsg")); // рассылка сообщения всем клиентам SymName=tcl.Ref(tcl.Obj(Symbol())); // запомним имя текущего символа PortNum=tcl.Ref(tcl.Obj((long)PORT)); // и номер порта /// запускаем сервер if (tcl.Call(StartServer,PortNum)!=TCL_OK) { PrintFormat("Error on StartServer:%s",tcl.StringResult()); return INIT_FAILED; } EventSetTimer(2); Print("Server started"); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { if (tcl!=NULL) { if (tcl.Ready()) { // остановить сервер tcl.Call(StopServer); } // освободить все объекты tcl.Unref(StartServer); tcl.Unref(StopServer); tcl.Unref(SendMsg); tcl.Unref(SymName); tcl.Unref(PortNum); // удалить интерпретатор delete tcl; } ATcl_OnDeinit(reason); } void OnTick() { MqlTick tick; tcl.Update(); if (SymbolInfoTick(Symbol(),tick)!=0) { Tcl_Obj message=tcl.Obj(); tcl.Ref(message); tcl.Append(message,SymName); tcl.Append(message,tcl.Obj((long)tick.time)); tcl.Append(message,tcl.Obj((long)tick.time_msc)); tcl.Append(message,tcl.Obj((double)tick.bid)); tcl.Append(message,tcl.Obj((double)tick.ask)); tcl.Append(message,tcl.Obj((long)tick.volume)); if (tcl.Call(SendMsg,message)!=TCL_OK) { PrintFormat("Error in SendMsg:%s",tcl.StringResult()); } tcl.Unref(message); } } void OnTimer() { tcl.Update(); } void OnChartEvent(const int id, // идентификатор события const long& lparam, // параметр события типа long const double& dparam, // параметр события типа double const string& sparam // параметр события типа string ) { tcl.Update(); }Até agora, tudo (biblioteca e intérprete) funciona em EAs ou roteiros. Para indicadores ainda não está pronto :-( Há algum tipo de estranheza com seqüências OnInit/OnDeinit, carregamento de DLL e temporizadores.
Tudo está se tornando cada vez mais estável, o EventLoop trabalha com confiança em EAs e scripts (e ainda não em indicadores)
Nova e útil demonstração - Cliente HTTP assíncrono e analisador. O código fonte (mq4 e tcl) é de cerca de 60 linhas.
A consulta é executada paralelamente ao Expert Advisor e a análise html é executada corretamente, via DOM parser.
input int EVERY_MINUTS=15; #include "ATcl.mqh" ATcl *tcl=NULL; Tcl_Obj StartClient=0,StopClient=0,report=0,minutes=0; int OnInit() { ATcl_OnInit(); // включить ATcl tcl=new ATcl; // создать интерпретатор if (tcl==NULL || !tcl.Ready()) { return INIT_FAILED; } // прочтём исходник c командами if (tcl.Eval("source ./MQL4/Experts/atcl_httpclient.tcl")!=TCL_OK) { PrintFormat("Error in Source:%s",tcl.StringResult()); return INIT_FAILED; } StartClient=tcl.Ref(tcl.Obj("StartClient")); StopClient=tcl.Ref(tcl.Obj("StopClient")); report=tcl.Ref(tcl.Obj("report")); minutes=tcl.Ref(tcl.Obj((long)EVERY_MINUTS)); if (tcl.Call(StartClient,minutes)!=TCL_OK) { Print("call failed"); return INIT_FAILED; } EventSetTimer(1); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { if (tcl!=NULL) { if (tcl.Ready()) { tcl.Call(StopClient); } tcl.Unref(StartClient); tcl.Unref(StopClient); tcl.Unref(report); tcl.Unref(minutes); delete tcl; } ATcl_OnDeinit(reason); } void OnTimer() { tcl.Update(); if (tcl.IsSet(report)) { string comment=tcl.String(tcl.Get(report)); tcl.Unset(report); Comment(comment); } } void OnTick() { tcl.Update(); }Estou quase satisfeito. Não demorará muito até que eu consiga remover de meu MQL tudo o que não está diretamente relacionado à negociação e acrescentar comunicações normais com o mundo exterior (bancos de dados, e-mails, relatórios e até mesmo GUI).
Se não fosse o problema atual com indicadores e temporizadores :-(.
Em pouco tempo, você poderia remover tudo de suas criações MQL que não está diretamente relacionado com o comércio e adicionar comunicações normais com o mundo exterior (bancos de dados, e-mails, relatórios e até mesmo uma GUI).
E o que o impede de ir para o mundo exterior via tubulação?
O resultado é o mesmo: você pode praticamente esquecer o mql - escrever um servidor uma vez e pronto.
O que o impede de ir para o mundo exterior através de oleodutos?
o resultado é o mesmo: você pode praticamente esquecer o µl - escrever um servidor uma vez e pronto.
e há um nível de integração completamente diferente - os dados podem ser facilmente transferidos entre tcl e mql - eles estão sentados em uma única memória, em um único processo. Em teoria (não verificou o trabalho, mas deve funcionar) e com alguma precisão você pode vincular variáveis.
Acontece que todas as características e bibliotecas que estão em tcl mas carentes em mql estão facilmente disponíveis.
INDICADORES são derrotados (quase) :-) Ou seja, a ATcl agora trabalha em indicadores, incluindo o EventLoop, um evento mal sucedido.
Em captura de tela - o mesmo programa da última vez (cliente http assíncrono), mas agora em indicador:
Naturalmente, o algoritmo de inicialização da DLL não é o mesmo :-)
Podemos dizer que o API-Preview está quase concluído, basta limpar o código fonte e a documentação, e então podemos anunciar a versão Beta
Anexar peru e biblioteca. E eu vou comemorar com cerveja :-)
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
As férias foram frutíferas e tenho o prazer de apresentar a ATcl - a intérprete Tcl integrada para o MT4.
A idéia do projeto era (e ainda é) fazer a interface mais conveniente para o intérprete sem uma portabilidade direta das funções Tcl C Api.
Isto é o que eu tenho (exemplo de trabalho - um script que salva uma cotação em um banco de dados SQLite):
Nesta fase, é uma visualização alfa dormente ou API Preview - avaliação da usabilidade do API. Mas como você pode ver as interfaces para o SGBD funcionar, com alguma precisão também funciona o EventLoop, ou seja, você pode usar comandos assíncronos, I/O e temporizadores.
Anexei o arquivo com a versão atual, você pode experimentá-lo...
A documentação, que estou atualizando o máximo que posso e as últimas versões podem ser encontradas na página do projeto http://luxtrade.tk/atcl.
Neste tópico estou pronto para responder perguntas sobre a própria Tcl/Tk e a mencionada biblioteca ATcl. Idéias, comentários, sugestões, críticas serão apreciadas.
ATUALIZAÇÃO: código fonte do roteiro em anexo neste tópico
ATUALIZAÇÃO: atualizado atcl.zip