흥미로운 일입니다.
언제나처럼 나는 R 아이디어를 만지작거리고 있는데, 나는 당신이 적어도 그 아이디어에 대해 논의할 적임자라고 생각합니다.
아이디어는 다음과 같습니다.
오늘날 터미널 차트에서 µl4/5로 컴파일러를 생성한 실행 파일을 드래그할 수 있습니다.
R 스크립트를 일정에 연결할 수 있도록 개발할 수 있습니까?
흥미로운 일입니다.
언제나처럼, 나는 R 아이디어를 만지작거리고 있다 . 당신은 적어도 그 아이디어에 대해 논의할 수 있는 사람인 것 같습니다.
아이디어는 다음과 같습니다.
오늘날 터미널 차트에서 µl4/5로 컴파일러를 생성한 실행 파일을 드래그할 수 있습니다.
R 스크립트를 일정에 연결할 수 있도록 개발할 수 있습니까?
그건 그렇고, R에 대해 :-) R 분포의 구성에주의를 기울였습니까?
따라서 내장 R tcl을 포함하는 library/tcltk 디렉토리가 있습니다. 언어/플랫폼에 자금이 부족하면 "Tool Common Language"라고 하는 tcl이 추가됩니다. R에서는 GUI가 충분하지 않았고 tcl/tk가 그 안에 설치되었습니다(실제로 Python 및 Ruby에서와 같이).
차트를 제외하고 MQL의 많은 기능이 부족하여 ATcl을 얻었습니다.
ATcl은 통계도 할 수 있습니다 :-) 또 하나의 작은 테스트 예제는 기본 통계 계산입니다. 데이터 세트에 대한 값. 닫기는 스크립트에서 수행되며 입력 매개변수에 설정되는 개수
#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(); }
스크립트를 첨부합니다. 한 줄만 계산하면 됩니다 :-)
그리고 또 하나의 예 :-)
zip을 가져와서 그 안에 있는 파일의 체크섬을 계산해 보겠습니다. MD5 및 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(); }
우선, 물론 스크린샷 :-) 이것은 60mql 라인 + 60tcl 라인의 tcp-server Advisor입니다.
그리고 이 EA의 MQ4:
#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(); }지금까지 모든 것(라이브러리와 인터프리터)은 Expert Advisors 또는 스크립트에서 작동합니다. 아직 표시기에 대한 준비가 되지 않았습니다.:-( OnInit/OnDeinit 대기열, DLL 로드 및 언로딩, 타이머가 있는 일종의 게임이 있습니다.
모든 것이 점점 더 안정되고 있습니다. EventLoop은 Expert Advisors 및 스크립트에서 자신 있게 작동합니다(그러나 표시기에서는 여전히 작동하지 않음)
새롭고 유용한 데모 - 비동기식 HTTP 클라이언트 및 파서. 소스 코드(mq4 및 tcl)의 길이가 약 60줄인 것은 이미 전통적입니다.
요청은 전문가와 병렬로 수행되며 html 페이지의 파싱은 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(); }거의 만족합니다. 조금만 더 하면 MQL 기술에서 거래와 직접적으로 관련되지 않은 모든 것을 제거하고 외부 세계(데이터베이스, 편지, 보고서, GUI)와의 정상적인 통신을 추가할 수 있습니다.
표시기 및 타이머와 관련된 현재 문제가 아니라면 :-(
조금만 더 하면 MQL 기술에서 거래와 직접 관련되지 않은 모든 것을 제거하고 외부 세계(데이터베이스, 편지, 보고서 및 GUI)와의 정상적인 통신을 추가할 수 있습니다.
그리고 파이프를 통해 외부 세계로 나가는 것을 막는 것은 무엇입니까?
결과는 동일합니다. µl은 거의 잊어버릴 수 있습니다. 서버는 한 번만 작성하면 됩니다.
그리고 파이프를 통해 외부 세계로 나가는 것을 막는 것은 무엇입니까?
결과는 동일합니다. µl은 거의 잊어버릴 수 있습니다. 서버는 한 번만 작성하면 됩니다.
여기에 완전히 다른 수준의 통합이 있습니다. tcl과 mql 간에 데이터를 쉽게 전송할 수 있습니다. 이들은 단일 프로세스에서 동일한 메모리에 바로 위치합니다. 이론상(나는 작업을 확인하지 않았지만 작동해야 함) 약간의 정확도로 변수를 연결할 수 있습니다.
tcl에는 있지만 mql에는 없는 모든 기능과 라이브러리에 쉽게 액세스할 수 있습니다.
INDICATORS (거의) :-) 즉, ATcl은 이제 불운한 EventLoop를 포함하여 표시기에서 작동합니다.
화면에서 - 지난 번과 동일한 프로그램(비동기 http 클라이언트), 하지만 이제 표시기에:
물론 DLL 초기화 알고리즘은 똑같았다 :-)
API-Preview가 거의 끝났다고 할 수 있습니다. 문서와 함께 소스 코드를 정리하면 베타 버전을 발표할 수 있을 것입니다.
칠면조와 도서관을 붙이고 있습니다. 그리고 맥주와 함께 축하해요 :-)
휴일은 유익했고 저는 MT4에 내장된 Tcl 인터프리터인 ATcl을 대중에게 선보였습니다.
프로젝트의 아이디어는 Tcl C Api 기능을 직접 이식하지 않고 인터프리터에 가장 편리한 인터페이스를 만드는 것이었습니다.
결과는 다음과 같습니다(실제 예제는 SQLite 데이터베이스에 견적을 저장하는 스크립트입니다).
이 단계에서 이것은 여전히 조밀한 알파이거나 API가 얼마나 편리한지에 대한 평가인 "API 미리보기"라고 말할 수 있습니다. 그러나 보시다시피 DBMS에 대한 인터페이스는 어느 정도 정확하게 작동하며 EventLoop도 작동합니다. 즉, 비동기 명령, 입력/출력 및 타이머를 사용할 수 있습니다.
현재 버전으로 아카이브를 첨부하여 시도할 수 있습니다..
최대한 보완한 문서와 최신 버전은 프로젝트 페이지 http://luxtrade.tk/atcl 에서 가져갈 수 있습니다.
이 스레드에서 저는 Tcl/Tk 자체와 언급된 ATcl 라이브러리에 대한 질문에 답할 준비가 되었습니다. 아이디어, 제안, 비판을 듣게 되어 기쁩니다.
업데이트: 주제에 제공된 스크립트 소스 첨부
업데이트: 업데이트된 atcl.zip