
HTMLでのチャート、ダイヤグラム
はじめに
おそらく、MetaTrader 5は、自己充足型の製品であり、追加の拡張機能は必要ではありません。MetaTrader 5は、ブローカーとの接続を提供し、市場分析のためのインジケーターの使用を可能にし、また、もちろん、トレード処理を行う機会も提供します。MetaTrader5は、主にトレーーディングを快適に行えるようにしていることに焦点が当てられており、調査や数学的な手法の分析、マルチメディアのコンテンツ作成などに設計された絶対的に普遍的なツールではありません。
さらに、度の超えた普遍性を備えたソフトウェア製品は最終的に効果や信頼性、安全性を失うものなのです。一方で、時折、ユーザーはいくつかの追加機能を必要とし、トレーダーは専門知識やバックグラウンドを持った人々です。従って、追加機能は、もし信頼性や安全性を大小とせず、シンプルな方法で組み込まれれば、トレーディングプラットフォームの魅力を向上します。
この記事では、そのような補足機能の一つ、ターミナルから取得したデータに基づくチャートやダイヤグラムを作成し表示するための機能について考察します。
個々のプログラムは、それぞれのできる限りのことをすべきです。この規則に従えば、MetaTrader5は、ブローカーとのトレードや、情報の収集や処理などに責任を持つようにし、この情報の表示のための異なるプログラムを使用します。
ウェブブラウザ
今日、ウェブブラウザをインストールしていないコンピューターはほとんどありません。長い間、ブラウザは進化し成長し続けてきました。現代のブラウザはとても信頼でき、また動作が安定し、無料でもあります。ウェブブラウザがインターネットへアクセスする基礎的なツールであるということを考慮すると、ユーザーの多くはそれに馴染みがあり、使用の際にほとんど困難を体験しません。
現代のブラウザの機能はとても広く、ビデオを見たり、音楽を聴いたり、ゲームをしたり、ウェブブラウザを通して数多くのことを行うことができます。従って、ウェブブラウザは、様々なフォーマットで異なる種類の情報を表示するための良いツールです。
現在複数の人気ウェブブラウザがあり、InternetExplorer、Mozilla Firefox, Google ChromeやOperaなどがあります。これらのブラウザはソフトウェアの実行やUIなどの観点からお互いに異なっています。しかしながら、HTML言語の標準を含む情報の交換のためのネットワークへの適応など、理論的に基礎的な標準をサポートしています。
開発者の努力に関わらず、ブラウザは特定のプロトコルや技術の実行において個別の特徴が残っています。もし、個別の特徴のせいで固有のブラウザがあっていないと分かれば、この問題はそのコンピューターに他のブラウザをインストールし、修正すれば良いです。Firefoxなどのブラウザの十分なサポートも、それらのシステムに少なくともInternet Explorerのシステムが組み込まれています。
リモートサーバーとの通信を提供するよう、ウェブブラウザはクライアント側として開発されましたが、コンピューターに保存されたローカルな情報を表示するためにも使用できます。この例としては、あなたのコンピュータに保存されたウェブページを見ることなどです。ブラウザはローカルページを見るためにインターネットにアクセスする必要がありません。
従って、オフラインモードのウェブブラウザは、MetaTrader 5クライアントターミナルのグラッフィク機能を拡大するためのプログラムの役割のためのとても魅力的な候補です。高価な買い物や、やっかいで時間のかかるインストールや、新しいソフトウェアの使用方法を学ぶ必要はありません。
それゆえ、この記事では、さらにMetaTrader5で取得さたデータを基にした、チャートやダイヤグラムの構築のためのウェブブラウザの使用における可能性を探っていきます。
HTMLとJavaScript
拡張機能としてウェブブラウザを選ぶことにより、ローカルかリモートウェブサーバーなしで作成したHTMLページの表示が実行されるべき、など今後従っていく基礎のルールを定義しましょう。これについては、コンピューターに何もサーバー用ソフトをインストールしません。ページの表示は、ネットワークへのアクセスも必要としていません。作成するHMTLページは、ウェブブラウザによってのみ表示され、自分のコンピューター内に保存されている必要があります。このルールは、外部ネットワークにアクセスすることにより安全性の欠落に関連づくリスクを最小化します。
情報の表示のためにHTML4の機能のみを使用し、図表やフォーマット化されたテキスト、イメージを載せたウェブページを作成できますが、私たちの目的はMetaTrader5のデータによる完全なチャートやダイヤグラムを作成することなので、これではまだまだ不十分です。
異なるサイトへ移動した際に見るようなものは、HTMLの拡張機能を使用して作成されたものです。一般的に、これらの拡張機能は、サーバーサイドで実行され、その理由から今回の目的には適しません。ブラウザサイドで動作する技術のみを使用し、サーバー側ソフトウェアを必要としません。例えば、FlashやJavaScript、Javaなどが我々の関心の的となります。
もしMacromedai FlashやJavaなどのブラウザサイドの実行のために、追加のプラグインを必要とする際は、JavaScriptで記述されたユーザープログラムがブラウザより直接実行されます。すべてのウェブブラウザが共通してJavaScript翻訳機を内蔵しています。追加のソフトウェアやプラグインなどをインストールすることを避けるために、JavaScriptを使用しましょう。
MQL5の付属した、MetaTrader 5と、HTML、JavaScriptを使用できるウェブラウザのみを使用します。その他のソフトウェアは必要ではありません。HTMLページは、テキストファイルでしかありません。従って、HTMLを作成するために、テキストエディターを使用できます。例えば、MetaEditor 5にてHTMLコードを作成し編集できます。この記事を作成する際には、HMTLコードの編集は、Opera @ USB v10.63ブラウザにて行われていました。ページのコンテンツを編集し、修正したページの保存、表示方法を見ることもできます。
HTMLやJavaScriptに馴染みのない人は、それらをマスターするのは難しいだろうと不安に思うかもしれません。作業を促進させ、HTMLやJavaScriptのより深い勉強を避けるために、この技術に基づくすでにできあがったソリューションを使用していきます。この記事で取り扱い範囲内では、ゴールとしては、チャートとダイヤグラムの構築に限られているので、すでに記述されたJavaScriptライブラリを使用します。
Emprise JavaScriots Chartsは高度なグラッフィクライブラリです。おそらく、読者の方々は、貼り付けられたリンクにてそれについてより知ることに興味があるかもしれませんが、このライブ来は無料ではありません。なので、Dygraphs JavaScript Visualization LibraryやHighcharts charting libraryなどの無料のライブラリを見ていきます。Dygraphsは、コンパクトさやシンプルさのおかげで魅力的であり、Highchartsライブラリは、数多くの機能を含み、より普遍的なツールです。Highchatsライブラリはおおよそ75KBで、追加のjQueryライブラリを必要とするにもかかわらず、それをライブラリとして選択します。
HIghchartsライブラリはhttp://www.highcharts.com/の「Demo Gallery」というセクション内にて詳しく知ることができます。それぞれの例において、「View Options」をクリックすると、JavaScriptのソースこ0度を見ることができます。そのライブラリの詳細なドキュメントは、「Documentation/Options Reference」のセクションに位置しており、異なるオプションの使用例を見ることもできます。一見すると、たくさんのJavaScriptコードや、慣れないMQLプログラム構文により複雑に見えます。これはそうではありません。チャートの表示を行うHTMLファイルの最初の例を考えてみてください。
具体例として、Test_01.htmlという名前のテキストファイルをNotepadエディターにて作成し、以下のライブラリの使用例のコードをコピーしてみましょう。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Example</title> <!-- - --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script> <script src="/js/highcharts.js" type="text/javascript"></script> <!-- - --> <script type="text/javascript"> var chart1; $(document).ready(function(){ chart1 = new Highcharts.Chart({ chart: {renderTo: 'container1'}, series: [{data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]}] }); }); </script> <!-- - --> </head> <body> <div id="container1" style="width: 700px; height: 400px "></div> </body> </html>
そのサンプルコードは、コメントにより4つのセクションにわかれています。
コードの最初の部分は、普通のHTMLページのタグを含んでいます。これは、特に現在は関係ありません。
その次にあるものとして、二つのタグ<script>があります。最初の部分は、ajax.googleapis.comのウェブサイトからjquery.min.jsというライブラリコードをダウンロードさせるコマンドをブラウザに与えます。二番目は、サーバー側で、/js/カタログが、ブラウザがダウンロードすべきhighchars.jsライブラリを含んでいることを想定しています。ページを表示するプロセス内にて、外部のソースへのアクセスが作成されるべきではないということを決定した通り、このコードは変更される必要があります。
変更したのち、このコードのはこのようになります。
<script src="jquery.min.js" type="text/javascript"></script> <script src="highcharts.js" type="text/javascript"></script>
この場合、HTMLファイルを持つカタログから両方のライブラリをダウンロードするようなコマンドを与えます。ブラウザによりライブラリをダウンロードするために、まず、ajax.googleapis.comとhttp://www.highcharts.comからそれぞれダウンロードされ、HTMLファイルの位置する同じカタログ内にコピーされる必要があります。これらのライブラリ両方とも、この記事の最後にて見ることができます。
コードの次のセクションとして、Highcharts.Chartのクラスオブジェクトが生成されています。「renterTo'container1'」というパラメーターは、そのチャートが、「container1」というHTMLの要素内にて表示され、その「data」パラメーターがチャート上に表示されるデータを定義することを示しています。この例では、Highcharts.Chartクラスのオブジェクトの生成中に、そのデータはそのパラメーターと同じように定義されていあす。簡単に変更することで、表示されるデータの定義を、複数のチャートを表示する必要のある場合などに、コードを個別の箇所に配置し、データのグルーピングを行うことができます。
例の最後の部分では、<div>のタグが「container1」というHTML要素を宣言し、このアイテムの規模が示されています。以前述べた通り、これは、チャートを構築するために使用されるHTML要素であり、そのチャートのサイズは、<div>のタグにて明記される「container1」要素のサイズにより決定されます。
行われた変更を考慮に入れた、具体例のコードは以下のようになります;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Example</title> <!-- - --> <script src="jquery.min.js" type="text/javascript"></script> <script src="highcharts.js" type="text/javascript"></script> <!-- - --> <script type="text/javascript"> var dat1 = [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]; </script> <!-- - --> <script type="text/javascript"> var chart1; $(document).ready(function(){ chart1 = new Highcharts.Chart({ chart: {renderTo: 'container1'}, series: [{data: dat1}] }); }); </script> <!-- - --> </head> <body> <div id="container1" style="width: 700px; height: 400px "></div> </body> </html>
このテストやライブラリは、この記事の終わりにある添付からコピーできます。Test_01.htmファイルや、ライブラリファイルは、同じ\Testフォルダにに保存されており、動作結果は、Test_01.htmlをダブルクリックすることで見ることができます。
このテストページの表示のために、JavaScriptの実行はWebブラウザにて可能にされている必要があります。ブラウザは安全のため、このオプションを停止させるために、停止されている可能性があります。その結果、以下のようになります。
図1. Test_01.htm
これは、最初のテストチャートです。この技術の複雑さにも関わらず、時間はあまりかかっていません。
このように作成されたチャートの特徴を記しておく必要があります。charts, created in this way. コピーされたカタログにて、Test_01.htmlファイルを開き、もしウェブブラウザで表示ページのズームが可能であれば、かなり拡大してもチャートのクオリティが悪くなっていないということに気づくとおもいます。
これは、このチャートがPNGやJPEGファイルなど、静的なイメージではなく、描画された場所のズーミングやズームアウトに応じて、再描画されているからです。従って、リンク付けしているような写真を保存する方法で、そのようなイメージがディスクに保存されることはありません。チャートは、JavaScriptにより構築されているため、それぞれ内臓の言語のインタープリターを持ち、同じような方法で実行しないということを忘れてはいけません。
そのチャートは、JavaScriptを使用し、異なるブラウザを使用した際には異なった見え方をします。しばしば、その他のブラウザと比べた際の違いは、Ineternet Explorerに見受けられます。
しかし、JavaScriptライブラリの作成者が人気なブラウザとコードの親和性をチェックしてくれることを願います。
MetaTrader 5とMQL5
上記の例では、チャートに表示されるように意図されたデータは、HTMLページさ癖字に手動で設定されています。MetaTrader 5からのデータを作成したチャートに写すために、最も簡単な方法を用います。MetaTrader 5にデータをブラウザにロードされる個別のファイルに記録しましょう。データをファイルやこのファイルを作成するMQL5のスクリプトからダウンロードし、チャートを作成するHTMLページを記述します。
HTMLファイルとして、以前作成されたTest_01.htmlを、いくつか変更を行ったのちに使用します。修正されたファイルをexample1.htmlと呼びます。変更点は、以下に記載されています。
<script type="text/javascript"> var dat1 = [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]; </script>will be replaced by
<script type="text/javascript"> var dat1=[0]; </script> <script src="exdat.txt" type="text/javascript"></script>
HTMLページをダウンロードした際にブラウザが、exdat.txtファイルをロードする必要があり、チャート上に表示される予定の値は、dat1配列に割り当てられます。このファイルは、JavaScriptコードの一部を含んでいる必要があります。このファイルは、MetaTrader5にて、一致するスクリプトを使用し簡単に作成されます。
そのスクリプトの例は以下に示されています。
//+------------------------------------------------------------------+ //| Example1.mq5 | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { int i,n,fhandle; double gr[25]; string str; n=ArraySize(gr); for(i=0;i<n;i++) { gr[i]=NormalizeDouble(MathSin(i*3*2*M_PI/n),4); } str=DoubleToString(gr[0],4); for(i=1;i<n;i++) { str+=","+DoubleToString(gr[i],4); } ResetLastError(); fhandle=FileOpen("exdat.txt",FILE_WRITE|FILE_TXT|FILE_ANSI); if(fhandle<0){Print("File open failed, error ",GetLastError());return;} FileWriteString(fhandle,"dat1=["+str+"];\n"); FileClose(fhandle); } //+------------------------------------------------------------------+
表示されるデータを保存するために、このスクリプトはgr[]配列を使用し、25のアイテムを保持します。この配列は、sinus関数の値を持ち、4つの少数値にされる切り上げがされます。この配列はもちろんその他の便利なデータも格納します。
さらに、このデータは、一つのStringにフォーマット化され、組み合わされます。生成されるテキストファイルの量を減らす場合、gr[]配列要素の値はStringに変換されます。このためには、DoubleToString()関数を使用します。
テキストStringのstrが作成されたのちに、exdata.txtファイルに保存されます。そのスクリプトが実行された際、texdata.txtファイルは、クライアントターミナルの\MQL5\Filesサブフォルダーに作成されます。もしそのファイルがすでに存在する場合、上書きされます。
jquery.min.js、highcharts.js、Example1.mq5、Example1.htmとexdat.txtファイルは、添付セクションのこの記事の終わりにて示されています。これらの5つのファイルは、\Example1カタログ内に位置しています。結果を見るためには、この例をコピーし、\Example1のカタログ内でExample1.htmlファイルを開いてください。チャートはexdata.txtからのデータに沿って作成されます。
図2Example1.htm
もちろん、Example1.mq5を稼働するためにクライアントターミナルの\MQL5\Scriptsフォルダに位置されている必要があり、コンパイルされなければなりません。
以前述べた通り、exdat.txtファイルの起動は、\MQL5\Filesフォルダーにて行われます。しかし、ライブラリからのファイルや、HTMLファイル、データファイルは、すべて同じフォルダーに保存されなければなりません。従って、jquery.min.js、highcharts.jsやExample1.htmを\MQL5\Filesフォルダーにコピーするか、これらのファイルが位置するフォルダーにexdat.txtファイルをコピーする必要があります。
この例では、HTMLページやライブラリは異なるファイルに保存されています。デザインの段階にて、プロジェクトの異なる部分は個別のファイルに保存されている方が便利です。これにより、例えば、HTMLファイルを編集する際にライブラリのコードにランダムな変更を避けることができます。しかし、HTMLページが編集sあれ、さらなる変更が追加されない場合、ライブラリは直接HTMLコードファイルに統合されることができます。
これは、JavaScriptsライブラリが単純なテキストファイル以外の何物でもないためです。もしquery.min.jsやhighcharts.js をテキストエディターにて開く際、ライブラリのソースを最大限に圧縮しないので、とくに難しい点はありません。
圧縮は、スペースなどをサービス記号を除去することで実行されます。そのような圧縮ののち、すべてのフォーマットが失われますが、ファイルの種類は変わらないためテキストは残ります。従って、ブラウザがライブラリコードに外部ファイルからextension.jsで接続するか、否か、現在のHTMLファイルから読み込むかなどはとくに違いをうみません。
ファイルを組み合わせるために、Example1.htmlの以下の行を変更します。
<script src="jquery.min.js" type="text/javascript"></script> <script src="highcharts.js" type="text/javascript"></script>
と
<script type="text/javascript"> </script>
次に、Notepadなどのテキストエディターを使用して、jqeruy.min.jsファイルを開き、「Select all」コマンドを選択し、ファイルの内容をコピーしてください。次に、Example1.htmlファイルを開き、<script type=\"text/javascript\">と</script>の間にライブラリのコピーしたテキストを貼り付けてください。Example2.htmlとして取得したファイルを保存してください。同じ手法で、highcharts.jライブラリの内容をこのファイルにコピーして、以前コピーしたライブラリのテキストと</script>の間に配置してください。
コピーの結果、HTMLファイルのサイズが増え、正しい表示のためにライブラリの個別のファイルを必要としません。Example2.htmファイルを含むFolder\Example2フォルダーに、exdat.txtを持つだけで十分で、exdat.txtはこの記事の終わり、添付ファイルセクションにてあります。
トレーディング履歴に関するレポートは、グラフィカル形式です。
図式での情報を表示するためのメソッドの実行のため、特定の時間感覚でトレーディングレポートの履歴を表示するレポートを作成します。「History」タブのコンテクストメニュー内「Report」コマンドを選んだ際に、MetaTrader5で作成されるHTMLレポートはプロトタイプとして機能します。このレポートは、一つの図表にて要約されている数多くの異なる特徴を示します。チャートやダイヤグラムの形で示されることで、これらの特徴がより視覚的になると想定し、highcharts.jsグラッフィクライブラリを使用し表示しましょう。
チャートの構築のために、highcharts.jsライブラリにあるデフォルトの表示パラメーターを使用しました。
実用的な使用のためにはこのオプションは、個別の要求に対応するためチャートの表示を調整するため、うまくいきません。このため、highcharts.jsライブラリは、チャートやダイヤグラムに適用できるたくさんのオプションを含んだものを提供します。すでに述べられた通り、オプションリストは詳細な記述や例とともに、 http://www.highcharts.comで見ることができます。
この記事は、MetaTrader5から取得される情報を表示するブラウザの使用についてグラフィックライブラリのオプションの詳細や使用方法にとどまりません。とくに、webページの作成のための特定の要求に依存しているため、その他のJavaScriptライブラリが使用されています。読者の方は、適したライブラリを選び、使用にあたった要求されることを深く勉強できます。
トレーディング口座の履歴を表示するために、ProfitReport.htmlファイルを作成しました。添付ファイルで見ることができます。\Repotフォルダは、表示するデータを持つdata.txtを含みます。data.txtファイルhあ、例のようにそのフォルダー内に配置されます。
\Reportフォルダをコピーしtえ、ProfitReport.htmlを開くと、この例のために作成さえたテスト用アカウントのトレーディングの特徴をグラフにて見ることができます。
図3. ProfitReport.htm
ProfileReport.htmlを作成する際、まず簡単なページのレイアウトを作成し、適当な場所や配置する情報の種類を決定しました。
それから、チャートをデフォルトのオプションをページに設置します。
8このテンプレートの作成の後、それぞれのチャートに適切なオプションを選択します。編集が終了したのち、ライブラリのテキストをそのページにコピーします。述べた通り、表示のためのデータを含むdata.txtと同じカタログに位置しています。
data.txtファイルは、MetaTrader5にて、ProitReport.mq5スクリプトを使用して作成されます。このスクリプトの実行に成功した場合、data.txtファイルは、\MQL5\Filesに作成されます。それは、現在の口座のトレードの情報を含んでいます。
そのスクリプトは、\MQL5\Scriptsフォルダーに配置され、コンパイルされる必要があることを忘れてはいけません。
//----------------------------------------------------------------------------------- // ProfitReport.mq5 // Copyright 2011, MetaQuotes Software Corp. // https://www.mql5.com //----------------------------------------------------------------------------------- #property copyright "Copyright 2011, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property script_show_inputs #include <Arrays\ArrayLong.mqh> #include <Arrays\ArrayDouble.mqh> #include <Arrays\ArrayString.mqh> #include <Arrays\ArrayInt.mqh> //--- input parameters input int nD=30; // Number of days //--- global double balabce_cur=0; // balance double initbalance_cur=0; // Initial balance (not including deposits to the account) int days_num; // number of days in the report (including the current day) datetime tfrom_tim; // Date from datetime tend_tim; // Date to double netprofit_cur=0; // Total Net Profit double grossprofit_cur=0; // Gross Profit double grossloss_cur=0; // Gross Loss int totaltrades_num=0; // Total Trades int longtrades_num=0; // Number of Long Trades double longtrades_perc=0; // % of Long Trades int shorttrades_num=0; // Number of Short Trades double shorttrades_perc=0; // % of Short Trades int proftrad_num=0; // Number of All Profit Trades double proftrad_perc=0; // % of All Profit Trades int losstrad_num=0; // Number of All Loss Trades double losstrad_perc=0; // % of All Loss Trades int shortprof_num=0; // Number of Short Profit Trades double shortprof_perc=0; // % of Short Profit Trades double shortloss_perc=0; // % of Short Loss Trades int longprof_num=0; // Number of Long Profit Trades double longprof_perc=0; // % of Long Profit Trades double longloss_perc=0; // % of Long Loss Trades int maxconswins_num=0; // Number of Maximum consecutive wins double maxconswins_cur=0; // Maximum consecutive wins ($) int maxconsloss_num=0; // Number of Maximum consecutive losses double maxconsloss_cur=0; // Maximum consecutive losses ($) int aveconswins_num=0; // Number of Average consecutive wins double aveconswins_cur=0; // Average consecutive wins ($) int aveconsloss_num=0; // Number of Average consecutive losses double aveconsloss_cur=0; // Average consecutive losses ($) double largproftrad_cur=0; // Largest profit trade double averproftrad_cur=0; // Average profit trade double larglosstrad_cur=0; // Largest loss trade double averlosstrad_cur=0; // Average loss trade double profitfactor=0; // Profit Factor double expectpayoff=0; // Expected Payoff double recovfactor=0; // Recovery Factor double sharperatio=0; // Sharpe Ratio double ddownabs_cur=0; // Balance Drawdown Absolute double ddownmax_cur=0; // Balance Drawdown Maximal double ddownmax_perc=0; // % of Balance Drawdown Maximal int symbols_num=0; // Numbre of Symbols string Band=""; double Probab[33],Normal[33]; CArrayLong TimTrad; CArrayDouble ValTrad; CArrayString SymNam; CArrayInt nSymb; //----------------------------------------------------------------------------------- // Script program start function //----------------------------------------------------------------------------------- void OnStart() { int i,n,m,k,nwins=0,nloss=0,naverw=0,naverl=0,nw=0,nl=0; double bal,sum,val,p,stdev,vwins=0,vloss=0,averwin=0,averlos=0,pmax=0; MqlDateTime dt; datetime ttmp,it; string symb,br; ulong ticket; long dtype,entry; if(!TerminalInfoInteger(TERMINAL_CONNECTED)){printf("Terminal not connected.");return;} days_num=nD; if(days_num<1)days_num=1; // number of days in the report (including the current day) tend_tim=TimeCurrent(); // date to tfrom_tim=tend_tim-(days_num-1)*86400; TimeToStruct(tfrom_tim,dt); dt.sec=0; dt.min=0; dt.hour=0; tfrom_tim=StructToTime(dt); // date from //---------------------------------------- Bands ttmp=tfrom_tim; br=""; if(dt.day_of_week==6||dt.day_of_week==0) { Band+=(string)(ulong)(ttmp*1000)+","; br=",";ttmp+=86400; } for(it=ttmp;it<tend_tim;it+=86400) { TimeToStruct(it,dt); if(dt.day_of_week==6){Band+=br+(string)(ulong)(it*1000)+","; br=",";} if(dt.day_of_week==1&&br==",") Band+=(string)(ulong)(it*1000); } if(dt.day_of_week==6||dt.day_of_week==0) Band+=(string)(ulong)(tend_tim*1000); //---------------------------------------- balabce_cur=AccountInfoDouble(ACCOUNT_BALANCE); // Balance if(!HistorySelect(tfrom_tim,tend_tim)){Print("HistorySelect failed");return;} n=HistoryDealsTotal(); // Number of Deals for(i=0;i<n;i++) { ticket=HistoryDealGetTicket(i); entry=HistoryDealGetInteger(ticket,DEAL_ENTRY); if(ticket>=0&&(entry==DEAL_ENTRY_OUT||entry==DEAL_ENTRY_INOUT)) { dtype=HistoryDealGetInteger(ticket,DEAL_TYPE); if(dtype==DEAL_TYPE_BUY||dtype==DEAL_TYPE_SELL) { totaltrades_num++; // Total Trades val=HistoryDealGetDouble(ticket,DEAL_PROFIT); val+=HistoryDealGetDouble(ticket,DEAL_COMMISSION); val+=HistoryDealGetDouble(ticket,DEAL_SWAP); netprofit_cur+=val; // Total Net Profit if(-netprofit_cur>ddownabs_cur)ddownabs_cur=-netprofit_cur; // Balance Drawdown Absolute if(netprofit_cur>pmax)pmax=netprofit_cur; p=pmax-netprofit_cur; if(p>ddownmax_cur) { ddownmax_cur=p; // Balance Drawdown Maximal ddownmax_perc=pmax; } if(val>=0) //win { grossprofit_cur+=val; // Gross Profit proftrad_num++; // Number of Profit Trades if(val>largproftrad_cur)largproftrad_cur=val; // Largest profit trade nwins++;vwins+=val; if(nwins>=maxconswins_num) { maxconswins_num=nwins; if(vwins>maxconswins_cur)maxconswins_cur=vwins; } if(vloss>0){averlos+=vloss; nl+=nloss; naverl++;} nloss=0;vloss=0; } else //loss { grossloss_cur-=val; // Gross Loss if(-val>larglosstrad_cur)larglosstrad_cur=-val; // Largest loss trade nloss++;vloss-=val; if(nloss>=maxconsloss_num) { maxconsloss_num=nloss; if(vloss>maxconsloss_cur)maxconsloss_cur=vloss; } if(vwins>0){averwin+=vwins; nw+=nwins; naverw++;} nwins=0;vwins=0; } if(dtype==DEAL_TYPE_SELL) { longtrades_num++; // Number of Long Trades if(val>=0)longprof_num++; // Number of Long Profit Trades } else if(val>=0)shortprof_num++; // Number of Short Profit Trades symb=HistoryDealGetString(ticket,DEAL_SYMBOL); // Symbols k=1; for(m=0;m<SymNam.Total();m++) { if(SymNam.At(m)==symb) { k=0; nSymb.Update(m,nSymb.At(m)+1); } } if(k==1) { SymNam.Add(symb); nSymb.Add(1); } ValTrad.Add(val); TimTrad.Add(HistoryDealGetInteger(ticket,DEAL_TIME)); } } } if(vloss>0){averlos+=vloss; nl+=nloss; naverl++;} if(vwins>0){averwin+=vwins; nw+=nwins; naverw++;} initbalance_cur=balabce_cur-netprofit_cur; if(totaltrades_num>0) { longtrades_perc=NormalizeDouble((double)longtrades_num/totaltrades_num*100,1); // % of Long Trades shorttrades_num=totaltrades_num-longtrades_num; // Number of Short Trades shorttrades_perc=100-longtrades_perc; // % of Short Trades proftrad_perc=NormalizeDouble((double)proftrad_num/totaltrades_num*100,1); // % of Profit Trades losstrad_num=totaltrades_num-proftrad_num; // Number of Loss Trades losstrad_perc=100-proftrad_perc; // % of All Loss Trades if(shorttrades_num>0) { shortprof_perc=NormalizeDouble((double)shortprof_num/shorttrades_num*100,1); // % of Short Profit Trades shortloss_perc=100-shortprof_perc; // % of Short Loss Trades } if(longtrades_num>0) { longprof_perc=NormalizeDouble((double)longprof_num/longtrades_num*100,1); // % of Long Profit Trades longloss_perc=100-longprof_perc; // % of Long Loss Trades } if(grossloss_cur>0)profitfactor=NormalizeDouble(grossprofit_cur/grossloss_cur,2); // Profit Factor if(proftrad_num>0)averproftrad_cur=NormalizeDouble(grossprofit_cur/proftrad_num,2);// Average profit trade if(losstrad_num>0)averlosstrad_cur=NormalizeDouble(grossloss_cur/losstrad_num,2); // Average loss trade if(naverw>0) { aveconswins_num=(int)NormalizeDouble((double)nw/naverw,0); aveconswins_cur=NormalizeDouble(averwin/naverw,2); } if(naverl>0) { aveconsloss_num=(int)NormalizeDouble((double)nl/naverl,0); aveconsloss_cur=NormalizeDouble(averlos/naverl,2); } p=initbalance_cur+ddownmax_perc; if(p!=0) { ddownmax_perc=NormalizeDouble(ddownmax_cur/p*100,1); // % of Balance Drawdown Maximal } if(ddownmax_cur>0)recovfactor=NormalizeDouble(netprofit_cur/ddownmax_cur,2); // Recovery Factor expectpayoff=netprofit_cur/totaltrades_num; // Expected Payoff sum=0; val=balabce_cur; for(m=ValTrad.Total()-1;m>=0;m--) { bal=val-ValTrad.At(m); p=val/bal; sum+=p; val=bal; } sum=sum/ValTrad.Total(); stdev=0; val=balabce_cur; for(m=ValTrad.Total()-1;m>=0;m--) { bal=val-ValTrad.At(m); p=val/bal-sum; stdev+=p*p; val=bal; } stdev=MathSqrt(stdev/ValTrad.Total()); if(stdev>0)sharperatio=NormalizeDouble((sum-1)/stdev,2); // Sharpe Ratio stdev=0; for(m=0;m<ValTrad.Total();m++) { p=ValTrad.At(m)-expectpayoff; stdev+=p*p; } stdev=MathSqrt(stdev/ValTrad.Total()); // Standard deviation if(stdev>0) { ArrayInitialize(Probab,0.0); for(m=0;m<ValTrad.Total();m++) // Histogram { i=16+(int)NormalizeDouble((ValTrad.At(m)-expectpayoff)/stdev,0); if(i>=0 && i<ArraySize(Probab))Probab[i]++; } for(m=0;m<ArraySize(Probab);m++) Probab[m]=NormalizeDouble(Probab[m]/totaltrades_num,5); } expectpayoff=NormalizeDouble(expectpayoff,2); // Expected Payoff k=0; symbols_num=SymNam.Total(); // Symbols for(m=0;m<(6-symbols_num);m++) { if(k==0) { k=1; SymNam.Insert("",0); nSymb.Insert(0,0); } else { k=1; SymNam.Add(""); nSymb.Add(0); } } } p=1.0/MathSqrt(2*M_PI)/4.0; for(m=0;m<ArraySize(Normal);m++) // Normal distribution { val=(double)m/4.0-4; Normal[m]=NormalizeDouble(p*MathExp(-val*val/2),5); } filesave(); } //----------------------------------------------------------------------------------- // Save file //----------------------------------------------------------------------------------- void filesave() { int n,fhandle; string loginame,str="",br=""; double sum; ResetLastError(); fhandle=FileOpen("data.txt",FILE_WRITE|FILE_TXT|FILE_ANSI); if(fhandle<0){Print("File open failed, error ",GetLastError());return;} loginame="\""+(string)AccountInfoInteger(ACCOUNT_LOGIN)+", "+ TerminalInfoString(TERMINAL_COMPANY)+"\""; str+="var PName="+loginame+";\n"; str+="var Currency=\""+AccountInfoString(ACCOUNT_CURRENCY)+"\";\n"; str+="var Balance="+(string)balabce_cur+";\n"; str+="var IniBalance="+(string)initbalance_cur+";\n"; str+="var nDays="+(string)days_num+";\n"; str+="var T1="+(string)(ulong)(tfrom_tim*1000)+";\n"; str+="var T2="+(string)(ulong)(tend_tim*1000)+";\n"; str+="var NetProf="+DoubleToString(netprofit_cur,2)+";\n"; str+="var GrossProf="+DoubleToString(grossprofit_cur,2)+";\n"; str+="var GrossLoss="+DoubleToString(grossloss_cur,2)+";\n"; str+="var TotalTrad="+(string)totaltrades_num+";\n"; str+="var NProfTrad="+(string)proftrad_num+";\n"; str+="var ProfTrad="+DoubleToString(proftrad_perc,1)+";\n"; str+="var NLossTrad="+(string)losstrad_num+";\n"; str+="var LossTrad="+DoubleToString(losstrad_perc,1)+";\n"; str+="var NLongTrad="+(string)longtrades_num+";\n"; str+="var LongTrad="+DoubleToString(longtrades_perc,1)+";\n"; str+="var NShortTrad="+(string)shorttrades_num+";\n"; str+="var ShortTrad="+DoubleToString(shorttrades_perc,1)+";\n"; str+="var ProfLong ="+DoubleToString(longprof_perc,1)+";\n"; str+="var LossLong ="+DoubleToString(longloss_perc,1)+";\n"; FileWriteString(fhandle,str); str=""; str+="var ProfShort="+DoubleToString(shortprof_perc,1)+";\n"; str+="var LossShort="+DoubleToString(shortloss_perc,1)+";\n"; str+="var ProfFact="+DoubleToString(profitfactor,2)+";\n"; str+="var LargProfTrad="+DoubleToString(largproftrad_cur,2)+";\n"; str+="var AverProfTrad="+DoubleToString(averproftrad_cur,2)+";\n"; str+="var LargLosTrad="+DoubleToString(larglosstrad_cur,2)+";\n"; str+="var AverLosTrad="+DoubleToString(averlosstrad_cur,2)+";\n"; str+="var NMaxConsWin="+(string)maxconswins_num+";\n"; str+="var MaxConsWin="+DoubleToString(maxconswins_cur,2)+";\n"; str+="var NMaxConsLos="+(string)maxconsloss_num+";\n"; str+="var MaxConsLos="+DoubleToString(maxconsloss_cur,2)+";\n"; str+="var NAveConsWin="+(string)aveconswins_num+";\n"; str+="var AveConsWin="+DoubleToString(aveconswins_cur,2)+";\n"; str+="var NAveConsLos="+(string)aveconsloss_num+";\n"; str+="var AveConsLos="+DoubleToString(aveconsloss_cur,2)+";\n"; str+="var ExpPayoff="+DoubleToString(expectpayoff,2)+";\n"; str+="var AbsDD="+DoubleToString(ddownabs_cur,2)+";\n"; str+="var MaxDD="+DoubleToString(ddownmax_cur,2)+";\n"; str+="var RelDD="+DoubleToString(ddownmax_perc,1)+";\n"; str+="var RecFact="+DoubleToString(recovfactor,2)+";\n"; str+="var Sharpe="+DoubleToString(sharperatio,2)+";\n"; str+="var nSymbols="+(string)symbols_num+";\n"; FileWriteString(fhandle,str); str="";br=""; for(n=0;n<ArraySize(Normal);n++) { str+=br+"["+DoubleToString(((double)n-16)/4.0,2)+","+DoubleToString(Normal[n],5)+"]"; br=","; } FileWriteString(fhandle,"var Normal=["+str+"];\n"); str=""; str="[-4.25,0]"; for(n=0;n<ArraySize(Probab);n++) { if(Probab[n]>0) { str+=",["+DoubleToString(((double)n-16)/4.0,2)+","+DoubleToString(Probab[n],5)+"]"; } } str+=",[4.25,0]"; FileWriteString(fhandle,"var Probab=["+str+"];\n"); str=""; sum=0; if(ValTrad.Total()>0) { sum+=ValTrad.At(0); str+="["+(string)(ulong)(TimTrad.At(0)*1000)+","+DoubleToString(sum,2)+"]"; for(n=1;n<ValTrad.Total();n++) { sum+=ValTrad.At(n); str+=",["+(string)(ulong)(TimTrad.At(n)*1000)+","+DoubleToString(sum,2)+"]"; } } FileWriteString(fhandle,"var Prof=["+str+"];\n"); FileWriteString(fhandle,"var Band=["+Band+"];\n"); str="";br=""; for(n=0;n<SymNam.Total();n++) { str+=br+"{name:\'"+SymNam.At(n)+"\',data:["+(string)nSymb.At(n)+"]}"; br=","; } FileWriteString(fhandle,"var Sym=["+str+"];\n"); FileClose(fhandle); }
ご覧の通り、そのスクリプトはむしろやっかいですが、これは、そのタスクの複雑さのせいではありません。トレーディング情報の多さや、決定される必要のある値の多さのためです。これらの値の保存のために、 スクリプトの初めにグローバル変数を宣言します。
OnStart()関数は、ターミナルがトレーディングサーバーと接続されているか確認し、もし接続されていなければ、そのスクリプトは終了します。サーバーへの接続がない場合、アクティブなアカウントを定義することができず、それについての情報も得ることができません。
その次のステップとして、データの計算があります。現在の口座のトレード用データがレポート内に含まれます。最終の日付として、現在の日付とそのスクリプトの実行時の現在時刻の値を使用します。レポートに含まれる日数は、30日に等しい「日数」入力パラメーターを変更することで、スクリプトロード時にセットすることができます。レポートの始まりと終わりの時刻を定義すれば、Band変数の週末の始まりと終わりに一致する時間の値が形成されます。この情報は、土曜日と日曜日に一致するバランスチャートのタイムインターバルにて、黄色く色付けされるように使用されます。
次に、HistorySelect()関数を使用すると、特定のインターバルにおいての取引や注文の履歴が取得可能になります。HistoryDealsTotal()関数を呼び出すことで、履歴の取引数を決定します。この後、取引数に基づき、サイクルが調整され、トレーディングの特徴を計算するために必要な統計を集めます。そのサイクルの終わりに、それらの値が決定されます。
スクリプトを作成した際に、目的として、MetaTrader5で生成されたレポートに沿ったトレーディングの特徴を保護するというものでした。スクリプトによってはじき出された特徴は、ターミナルのHelpファイルにて与えられている記述に一致する必要があります。
アカウント履歴とトレーディングの特徴の計算へのアクセスに関する情報は、以下の記事で見ることができます。
- MetaTrader 5の注文、ポジション、取引;
- 標準ライブラリクラスとGoogle Chart Apiを使用し、インフォメーションボードを作成する:
- レポートをテストするエキスパート内の数字が意味するもの
- トレードにおける数学:トレード結果を予測する方法.
大半のトレード特徴は、簡単に計算されます。なので、この記事では、それぞれの計算における処理は紹介せず、標準のレポートなどからの既存の違いのみを考えます。
ターミナルにより生成されるレポート内では、そのバランスチャートは、変化する時間ごとに値を表示することで構築されます。X軸はそのような数の変化を反映します。そのチャートの構築のために、時間尺度を使用します。
従って、利益チャートは、ターミナルから生成されるチャートとは異なっています。時間的な尺度でのポジションのクローズ時刻を表示するためにチャートの構築のこの選択肢を選びました。従って、トレーディング活動が上下動をいつしたかを見ることができます。
チャートの構築時、MWL5は、1970年1月から数えた秒数として表示される日付の値を処理し、グラフィックライブラリは1970年1月からミリ秒単位での値を必要とします。従って、取得された日付の値は、正しく表示するためには1000でかける必要があります。
利益やクローズ時刻を保存するために、スクリプトは、 標準ライブラリからCArrayDoubleとCArrayLongを使用します。結果として生じる取引をループにて発見されるたび、Add()メソッドを用いて、それについての情報が、配列の最後尾に追加されます。これにより、前もって要素の必要な数を決定する必要をカットすることができます。配列のサイズは、履歴にて見つかった取引数に伴って拡大します。
それぞれの取引ごとに、チェックが実行されたシンボルに行われ、そのシンボル名と取引数を保持します。利益チャートと同じく、履歴を見る際にこのデータは、配列の後尾の要素に記録され積み重なります。シンボル名と取引数を保存するために、標準ライブラリのクラスCArrayStringとCArrayIntを使用します。
チャートのシングルカラムは、取引が一つのシンボルにて実行された場合、広すぎます。これを避けるために、データ配列は常に7つの要素を保持します。0の値を持つため、使用されていない配列要素はダイヤグラム上に表示されません。従って、カラムが広くなりすぎません。いくつかのシンボルがあることを確認するためには、カラムはX軸の中間に位置し、配列の要素は配列の最後か初めに挿入されます。
次の標準レポートからの違いは、それぞれの取引における利益値の連続値における確率分布チャートを作成する試みです。
図4. 確率密度
このチャートのタイプは、ヒストグラムの形式で表示されます。確率チャートは、既存のヒストグラムのカラムの値に基づいたスプライン曲線を構築することで、作成されます。計算された確率密度の値は、0の値でチャートの右、左側にて完成されます。これは、スプライン曲線によって構築されたチャートが、最後の未知の値によって邪魔されず、0を超えて続くようにするためには必要です。
確率密度においての比較に関して、ヒストグラムの値に基づいて作成されたチャートのようなものに等しい形で標準化された標準分布のチャートをハイライトして表示するためグレー色が使用されます。例として示されたレポートにて、取引数は、おおかえ少なかれ信頼できうる利益トレードの値の確率分布の予測を提供しません。履歴内に多くの取引があるとき、このチャートはより信頼のできるものになると想定できます。
すべてのトレーディングの特徴が計算されれば、filesave()関数がスクリプトの最後に呼び出されます。この関数は、data.txtファイルを変数名や値がテキストの形で記録されているファイルへ展開します。これらの変数の値は計算されたパラメーターと一致し、名前はHTMLファイルでパラメーターのグラフィックライブラリ関数へ移した際に使用されていた名前に一致します。
ファイルへの記述中にディスクへのアクセス回数を減らすためには、短い行が、長い行に統合され、ファイルに記録されます。data.txtファイルは、MetaTrader5にて習慣的であるように、MQL5\Filesカタログ内に作成されます; もしこのファイルがすでに存在する場合は、上書きされます。ProfitReport.htmファイルをこのカタログ内にコピーし、そこから稼働させることもできます。
MetaTrader 5ターミナルでは、HTML形式にてレポートを保存する際に、自動的に登録されているブラウザから開かれます。この記事にて提供されている例では実行されていませんでした。
以下の記述をProfitReport.mq5スクリプトの初めに挿入し、自動再生を追加してください。
#import "shell32.dll" int ShellExecuteW(int hwnd,string lpOperation,string lpFile,string lpParameters, string lpDirectory,int nShowCmd); #import
そshちえ、最後にfilesave()関数を呼び出した後に、以下を追加します。
string path=TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\ProfitReport.htm"; ShellExecuteW(NULL,"open",path,NULL,NULL,1);
もし、その変数のパス内にProfitReport.htmが存在すれば、ShellExecuteW()が呼ばれたときにブラウザにより開かれます。ShellExecuteW()関数は、shell32.dllシステムライブラリに位置しています。この関数の宣言は、それにアクセスするためファイルの最初に追加されています。
結論
ウェブブラウザの使用により、役に立つであろう異なる情報を同時に表示することができます。例えば、エキスパートアドバイザーの個々のモジュールの内部状態の視覚的なコントロールなどです。
資金管理データ、トレーディングシグナル、その他モジュールデーターが便利に、そして同時に表示されます。マルチページHTMLレポートはもし情報が多すぎる場合使用されます。
JavaScript言語の可能性は、チャートを描くだけにとどまりません。この言語を使用し、本格的なWebページを作成できます。インターネット上に、すでに出来上がっているJavaScriptのコード、この言語の使用例などが載っています。
もしターミナルとブラウザ間のに方向のデータ交換が構築されれば、ターミナルはブラウザウィンドウから直接管理できます。
この記事で紹介されているメソッドが便利であることを願います。
ファイル
JS_Lib.zip - highcharts.jsとjquery.min.js
librariesTest.zip - highcharts.js、jquery.min.jsとTest_01.htm
Example1.zip - highcharts.js、jquery.min.js、Example1.htm、Example1.mq5とexdat.txt
Example2.zip - Example2.htmとexdat.txt
Report.zip - ProfitReport.htmとdata.txt
ProfitReport.mq5 - 統計の収集やdata.txtファイルの生成のためのスクリプト
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/244




- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索