Roba interessante.
Sto, come sempre, rosicchiando l'idea di R. Mi sembra che lei sia la persona giusta con cui almeno discutere l'idea.
L'idea è la seguente.
Oggi è possibile trascinare un file exesh, che è stato generato dal compilatore mcl4/5, nel grafico del terminale.
È possibile fare uno sviluppo per poter concatenare uno script R al grafico?
Roba interessante.
Sto, come sempre, rosicchiando l'idea di R. Mi sembra che lei sia la persona giusta con cui almeno discutere l'idea.
L'idea è la seguente.
Oggi è possibile trascinare un file exesh, che è stato generato dal compilatore mcl4/5, nel grafico del terminale.
Ed è possibile fare uno sviluppo per poter concatenare uno script R al grafico?
A proposito, a proposito di R :-) Hai prestato attenzione al kit di distribuzione R?
Bene, c'è una directory library/tcltk, che contiene il tcl integrato in R. Quando una lingua/piattaforma manca di strutture, vi aggiungono tcl, alias "Tool Common Language". R mancava di GUI e ci ha messo tcl/tk (proprio come in Python e Ruby).
Mi mancavano molte caratteristiche in MQL, tranne i grafici, così ho preso ATcl.
ATcl può anche fare statistiche :-) Un altro piccolo caso di test: calcolare valori statistici di base per un set di dati. Lo script prende Close, quanti saranno dati nel parametro di input
#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(); }
In allegato c'è lo script. C'è solo una linea di calcolo :-)
E un altro esempio :-)
Prendiamo uno zip e calcoliamo le checksum dei file memorizzati in esso. Calcoliamo 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(); }
Solo come anticipazione, ovviamente, uno screenshot :-) Questo è un server tcp EA in 60 linee di mql + 60 linee di tcl
E MQ4 dello stesso 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(); }Finora tutto (libreria e interprete) funziona negli EA o negli script. Per gli indicatori non è ancora pronto :-( C'è una sorta di stranezza con le sequenze OnInit/OnDeinit, il caricamento delle DLL e i timer.
Tutto sta diventando sempre più stabile, EventLoop funziona con sicurezza negli EA e negli script (e ancora non negli indicatori)
Nuovo, utile demo - HTTP-client e parser asincrono. Il codice sorgente (mq4 e tcl) è di circa 60 linee.
La query viene eseguita parallelamente a Expert Advisor e l'analisi dell'html viene eseguita correttamente, tramite il parser DOM.
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(); }Sono quasi soddisfatto. Non ci vorrà molto prima che io sia in grado di rimuovere dai miei falsi MQL tutto ciò che non è direttamente collegato al trading e aggiungere le normali comunicazioni con il mondo esterno (database, e-mail, rapporti e anche GUI).
Se non fosse per l'attuale problema con gli indicatori e i timer :-(.
In un tempo un po' più lungo, si potrebbe rimuovere dalle creazioni MQL tutto ciò che non è direttamente legato al trading e aggiungere le normali comunicazioni con il mondo esterno (database, e-mail, rapporti e anche una GUI).
E cosa vi impedisce di andare nel mondo esterno attraverso le tubature?
Il risultato è lo stesso: puoi praticamente dimenticarti di mql - scrivi un server una volta e basta.
Che cosa vi impedisce di andare verso il mondo esterno attraverso le condutture?
il risultato è lo stesso: si può praticamente dimenticare µl - scrivere un server una volta e basta.
e c'è un livello di integrazione completamente diverso - i dati possono essere facilmente trasferiti tra tcl e mql - sono seduti proprio in una memoria, in un unico processo. In teoria (non ho controllato il lavoro, ma dovrebbe funzionare) e con una certa precisione si possono collegare le variabili.
Si scopre che tutte le caratteristiche e le librerie che sono in tcl ma mancano in mql sono facilmente disponibili.
Gli indicatori sono sconfitti (quasi) :-) Cioè, ATcl ora funziona negli indicatori, compreso lo sfortunato EventLoop.
Nella schermata - lo stesso programma dell'ultima volta (client http asincrono), ma ora in indicatore:
Naturalmente, l'algoritmo di inizializzazione della DLL non è lo stesso :-)
Possiamo dire che l'API-Preview è quasi completata, basta pulire il codice sorgente e la documentazione, e poi possiamo annunciare la versione beta
Allegare il tacchino e la biblioteca. E ho intenzione di festeggiare con la birra :-)
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso
Le vacanze sono state fruttuose, e sono lieto di presentare ATcl - l'interprete Tcl integrato per MT4.
L'idea del progetto era (ed è ancora) quella di fare l'interfaccia più conveniente per l'interprete senza un porting diretto delle funzioni Tcl C Api.
Questo è quello che ho ottenuto (esempio di lavoro - uno script che salva una citazione in un database SQLite):
In questa fase è un'alfa dormiente o API Preview - valutazione dell'usabilità dell'API. Ma come potete vedere le interfacce al DBMS funzionano, con una certa precisione anche EventLoop funziona, cioè potete usare comandi asincroni, I/O e timer.
Ho allegato l'archivio con la versione attuale, potete provare...
La documentazione, che sto aggiornando il più possibile e le ultime versioni possono essere trovate sulla pagina del progetto http://luxtrade.tk/atcl.
Questo thread è pronto a rispondere alle domande su Tcl/Tk stesso e sulla citata libreria ATcl. Idee, commenti, suggerimenti, critiche saranno apprezzati.
AGGIORNAMENTO: allegato il codice sorgente dello script in questo topic
AGGIORNAMENTO: aggiornato atcl.zip