面白いものですね。
私はいつものように、Rのアイデアをノセています。少なくとも相談相手としては適任だと思われます。
考え方は次のとおりです。
現在では、mcl4/5コンパイラで生成されたexeshファイルをターミナルチャートにドラッグすることが可能です。
チャートにRスクリプトを連鎖させることができるような開発は可能でしょうか?
面白いものですね。
私はいつものように、Rのアイデアをノセて います。少なくとも相談相手としては適任だと思われます。
考え方は次のとおりです。
現在では、mcl4/5コンパイラで生成されたexeshファイルをターミナルチャートにドラッグすることが可能です。
また、チャートにRスクリプトを連鎖させられるような展開は可能でしょうか?
ところで、Rについてですが :-)Rディストリビューション・キットに注目しましたか?
さて、Rのビルトインtclを含むディレクトリlibrary/tcltkがあります。ある言語・プラットフォームに設備が足りない場合、tcl、別名「ツール共通言語」を追加するのです。RのGUIを欠き、そこにtcl/tkを入れる(PythonやRubyと同じ)。
MQLではグラフ以外の多くの機能が足りなかったので、ATclを手に入れました。
ATclは統計もできる :-)もう一つの小さなテストケース - データセットの基本的な統計値を計算する。スクリプトはCloseを取るが、その数は入力パラメータに与えられる
#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(); }
スクリプトを添付します。計算の線は1本だけです :-)
そして、もうひとつの例 :-)
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(); }
手始めに、もちろんスクリーンショットを :-)60行のmql + 60行のtclで構成されるEA tcp-serverです。
そしてExpert Advisor自体の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(); }今のところ、EAやスクリプトですべて(ライブラリやインタプリタ)が動作しています。OnInit/OnDeinitシーケンス、DLLロード、タイマーに何らかの不都合があるようです。
EAやスクリプトでEventLoopが確実に動作するようになり、すべてが安定してきた(インジケーターではまだだが)
新しい、便利なデモ - 非同期HTTP-クライアントとパーサー。ソースコード(mq4とtcl)は約60行です。
クエリーはExpert Advisorと並行して実行され、DOMパーサーによってhtmlの解析が正しく行われます。
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)を追加することも可能でしょう。
また、パイピングで外界に出られないのはなぜですか?
その結果、mqlのことは実質的に忘れることができ、サーバーを一度書けばそれで終わりです。
パイプラインで外部に出ることを阻むものは何ですか?
その結果、µlのことは実質的に忘れることができ、サーバーを一度書けばそれで終わりです。
tclとmqlの間では、データを簡単に転送することができ、1つのメモリ、1つのプロセスで動作します。理論的には(動作確認はしていませんが、動作するはずです)、ある程度の精度で、変数をリンクさせることができます。
tclにはあってmqlにない機能やライブラリが簡単に手に入ることがわかったのです。
INDICATORSは敗北した(ほぼ) :-)つまり、ATclは、不遇のEventLoopを含むインジケータで動作するようになったのだ。
スクリーンショット - 前回と同じプログラム(非同期httpクライアント)が、インジケータで表示されるようになりました。
もちろん、DLLの初期化アルゴリズムは同じではありません :-)
APIプレビューはほぼ完了し、あとはソースコードとドキュメントのクリーンアップを行い、ベータ版を発表することができます。
ターキーとライブラリーを装着する。そして、ビールで祝杯をあげるつもりです :-)
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
この連休は実り多く、MT4用の組み込みTclインタプリタであるATclを発表できることを嬉しく思います。
このプロジェクトのアイデアは、Tcl C API関数を直接移植することなく、インタープリタへの最も便利なインタフェースを作ることでした(現在もそうです)。
これは私が得たものです(作業例 - SQLiteデータベースに引用符を保存するスクリプト)。
この段階では、休眠状態のアルファ版、あるいはAPIプレビュー(APIの使い勝手を評価するもの)である。しかし、あなたが見ることができるように、DBMSへのインタフェースは、いくつかの精度で、イベントループも動作します、つまり、あなたは非同期コマンド、I / O、およびタイマーを使用することができます。
現在のバージョンのアーカイブを添付しますので、試してみてください...。
ドキュメントは、できる限り更新していますし、最新版はプロジェクトページhttp://luxtrade.tk/atcl で見ることができます。
このスレッドでは、Tcl/Tkそのものや、言及されているATclライブラリに関する質問に答える用意があります。アイデア、コメント、提案、批評をお待ちしています。
UPDATE: このトピックにスクリプトのソースコードを添付しました。
UPDATE: atcl.zipをアップデートしました。