MQL5におけるリソースの使用

2 10月 2015, 15:21
MetaQuotes Software Corp.
0
426

最新プログラムインターフェースの重要性

かつては、コンピュータプログラムの主要な目的は、複雑な数学的演算や大量のデータ処理を行うことでした。しかし、コンピュータの性能向上とともに、優先されるべきことが変化しました。今や、同じ機能を持つ2つのプログラムの間では、ユーザは、より作業しやすいものを選択します。

今日、演算アルゴリズムにしたがってプログラムを書くだけでは不十分であって、ユーザフレンドリなグラフィックインターフェースも提供しなければならないのです。マーケットの現状をビジュアルに表現したいというトレーダーの要望から生まれた技術分析においても然りで、現在起きていることの客観的な状況を示すために、トレンドライン、サポートとレジスタンスの水準、各種チャネル、そしてテクニカル指標が開発されました。

新しいMQL5言語が、完全に機能的なアプリケーションを作成するためのより一層パワフルなツールを提供しているおかげで、アプリケーションとしてはメタトレーダー5クライアントターミナル以外には何も必要としません。本稿では、リソースをどのように使って、ユーザフレンドリなインターフェースを含む実行可能なEX5ファイルを作成するかを示します。このファイルは、インストールや起動といったルーチンの操作を必要としません。


MQL5の可能性

もちろん、とりわけ第1に、グラフィックで動作する可能性は非常に重要です。活用例が、以下の記事にあります。これらはその一部です。

ユーザの視点でいえば、グラフィックエレメントの使用によって、プログラムはより面白く、またコントロールしやすくなります。テクニカル分析のための従来ツールに加えて、メタトレーダー5 ターミナルは幅広いグラフィックオブジェクトを提供しており、これを、独自のグラフィックインターフェースを作成するためのれんが(部品)のように使うことができます。


インターフェース作成のための画像ファイルの利用

特定のインターフェースを作成するため、大抵の場合、グラフィックファイルから画像が用いられます。これによって、独自で視認性の高いさまざまなコントロールエレメントを設計することができます。MQL5言語は、グラフィックを用いた2つのグラフィックオブジェクト を提供します:

  • OBJ_BITMAP-このビットマップオブジェクトによって、BMPファイルから画像をダウンロードし、チャートに表示することができます;
  • OBJ_BITMAP_LABEL-このグラフィックラベルは実際には、画像がそのステータス(押離)によって変わるボタンです

これら2つのオブジェクトによって、たいへん幅広いコントロールを作成することができ、またそれらを「マウスクリック」によってイベントハンドラ―と比較することができます(CHARTEVENT_OBJECT_CLICK)。OBJ_BITMAPもしくはOBJ_BITMAP_LABELで好みの画像をセットするには、お好みのBMPファイルをOBJPROP_BMPFILEプロパティで特定します。この操作は、グラフィックオブジェクトの「パラメータ」タブによって手動で行うことができます。

MQL5プログラマにとっての第2の主な活用法は、ObjectSetString()関数を使って、OBJPROP_BMPFILEプロパティ用の名前を特定することです。以下がその例です:

//--- Load an image for the "Pressed" button state
   bool set=ObjectSetString(0,object_name,OBJPROP_BMPFILE,0,bmp_file_name);

OBJ_BITMAPまたはOBJ_BITMAP_LABELを用いるための標準アルゴリズム

  1. ObjectCreate()関数を使ってオブジェクトを作成します。
  2. 必要に応じて、ObjectSetInteger()関数を使ってオブジェクトを好みのチャート領域に固定します。この領域に関して、ピクセル表示によるアンカーポイントのX座標とY座標がセットされます。
  3. ObjectSetInteger()で、X座標とY座標(OBJPROP_XDISTANCE and OBJPROP_YDISTANCE)の値をセットします。
  4. ObjectSetString()を使って、グラフィックオブジェクトにOBJPROP_BMPFILEプロパティ(BITMAPの場合は1つ、もしくはOBJ_BITMAP_LABELの場合は2つ)の値をセットします。
  5. OBJ_BITMAP_LABELオブジェクトではObjectSetInteger() を使って、ボタンの初期状態-すなわち押離(OBJPROP_STATEの真偽)、をセットすることができます。

オブジェクトの作成構築後には、MQL5プログラムの起動中、グラフィックオブジェクトの位置や状態を動的に変更するだけでなく、OBJ_BITMAP_LABELプロパティの値を変更して画像を表示することもできます。このように、たいへんフレキシブルで再構築可能なインターフェースを実現することができます。


音声を再生する

その他にプログラムに求められる利便性としては、ある状況下において、ユーザにアクションについて問い合わせる機能があります。このリバースインタラクションを実行するために、イベントに応じて、異なる音声の再生がたびたび用いられます。これによって、トレーダーは必要な場合にのみ価格チャートに注意を向けることができ、継続的にチャートを観ることから解放されるでしょう。オーディオファイルを再生するために、MQL5ではPlaySound()関数が用いられます。

PlaySound()はたいへん使いやすく、必要な設定は音声ファイルパスの指定のみです:

//--- The path to a sound file  
string wav_file_name="Ok.wav";
...
//--- Play a sound from the file terminal_directory\Sounds\Ok.wav
bool played=PlaySound(wav_file_name);
if(!played)
  //--- Failed to play the sound, notify of this
  {
   PrintFormat("Failed to play file %s. Error code=%d", wav_file_name, GetLastError());
  }


音声ファイルと画像ファイルの格納場所

ObjectSetString()PlaySound()では、ファイルのパスを指定する必要があります。セキュリティ上、MQL5プログラムで使用するすべてのファイルは、ファイルサンドボックス内に格納されています。これは、ファイルはある特定のディレクトリにのみ保存されることを意味しており、他のディレクトリにあるファイルを用いる作業は認められていません。そこでまず、ファイルの操作や起動のためにどのディレクトリが利用可能で、それがどのように名前付けされているかを知る必要があります。

3つの異なるディレクトリがあります。

  • Terminalディレクトリ-クライアントターミナルのインストールディレクトリです。メタトレーダー5はこのディレクトリから起動し、フォルダを参照するには、ターミナルメニューの「ファイル」-「ターミナルデータを開く」を選択します。
  • Terminal dataディレクトリ-特定のWindowsユーザのデータを格納するフォルダ。オペレーティングシステム内蔵の保護メカニズムによってユーザ単位で異なるアクセスコントロールが可能なため、個々のユーザのデータを、他のユーザのデータと分けて保存することができます。したがってMQL5のサブフォルダであるこのディレクトリには、Navigatorウィンドウに表示されるすべてのインディケータ、エキスパートアドバイザ、ならびにスクリプトが保存されます。
  • (コンピュータにインストールされているすべてのメタトレーダー5クライアントターミナル)すべての共有フォルダFILE_COMMONフラグを用いてファイル操作を行うフォルダ。

これらのディレクトリの位置を判別するためには、WhereMyFolders.mq5スクリプトを使用できます。

//+------------------------------------------------------------------+
//|                                               WhereMyFolders.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"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- The folder from which the terminal is started - terminal_directory
   string terminal_path=TerminalInfoString(TERMINAL_PATH);
//--- The folder that stores the terminal data - terminal_data_directory
   string terminal_data_path=TerminalInfoString(TERMINAL_DATA_PATH);
//--- The shared folder of all client terminals - common_terminal_folder
   string common_data_path=TerminalInfoString(TERMINAL_COMMONDATA_PATH);   
   //--- Show all the paths 
   Print("TERMINAL_PATH(terminal_directory) = ",TerminalInfoString(TERMINAL_PATH));
   Print("TERMINAL_DATA_PATH(terminal_data_directory) = ",TerminalInfoString(TERMINAL_DATA_PATH));
   Print("TERMINAL_COMMONDATA_PATH(comon_terminal_folder) = ",TerminalInfoString(TERMINAL_COMMONDATA_PATH));   
  }

注意:場合によってはterminal_directoryterminal_data_directoryの場所が偶然同じになりますが、この結果に頼らず、したがって、これらのコンセプトを混同しないほうがより望ましいです。

画像ファイルと音声ファイルは、ターミナルのランタイムシステムによって以下の順序で検索することができます:

  • バックスラッシュ「\」セパレータ(「\\」と表記されます)がパスの先頭に配置されている場合は、リソースを terminal_data_directory\MQL5\以下の相対ディレクトリとして検索します。
  • もしパスの先頭にバックスラッシュがなければ、ファイルはObjectSetString(... , OBJPROP_BMPFILE, ...)関数 もしくはPlaySound()関数がが呼び出されるEX5ファイルの位置から相対的に検索されます。

PlaySound()関数に関しては追加事項が1つあります:上記の2つの方法でファイルが見つからない場合に、この音声ファイルは、terminal_directory\Sounds\以下の相対ファイルとして検索されます。

音声ファイルの例:

  • ファイルone.wavを検索して、 terminal_data_directory\MQL5\内ににあることが分かった場合は、以下のように指定します。

    PlaySound("\\one.wav");
  • ファイルtwo.wavを検索して、terminal_data_directory\MQL5\Files\内にあることが分かった場合は、以下のように指定します。

    PlaySound("\\Files\\two.wav");
  • ファイルthree.wavを検索して、 terminal_data_directory\MQL5\MySounds\内にあることが分かった場合は、以下のように指定します。

    PlaySound("\\MySounds\\three.wav");
  • ファイルfour.wavを検索して、実行可能なEX5が起動しているフォルダにあることが分かった場合は、以下のように指定します。なお、もしこのフォルダにファイルが見つからないときには、 terminal_directory\Sounds\フォルダ内を検索に行きます。

    PlaySound("four.wav");

画像ファイルの例:

  • ファイルbird.bmpを検索して、terminal_data_directory\MQL5\内にあることが分かった場合は、以下のように指定します。

    //--- Setting an image for the OBJ_BITMAP_LABEL object
    bool res=ObjectSetString(0,object_name,OBJPROP_BMPFILE,0,"bird.bmp");// Modifier 0 is specified
  • ファイルswan.bmpを検索して、terminal_data_directory\MQL5\Files\内にあることが分かった場合は、以下のように指定します。

    //--- Setting an image for the OBJ_BITMAP object
    bool set=ObjectSetString(0,object_name,OBJPROP_BMPFILE,"\\Files\\swan.bmp");// No modifier
  • ファイルdog.bmpを検索して、 terminal_data_directory\MQL5\MyPictures\内にあることが分かった場合は、以下のように指定します。

    //--- Setting an image for OBJ_BITMAP
    bool done=ObjectSetString(0,object_name,OBJPROP_BMPFILE,"\\MyPictures\\dog.bmp");// No modifier
  • ファイルcat.bmpを検索して、実行可能なEX5が起動しているフォルダにあることが分かった場合は、以下のように指定します。

    //--- Setting an image for OBJ_BITMAP
    bool result=ObjectSetString(0,object_name,OBJPROP_BMPFILE,"cat.bmp");// No modifier

バックスラッシュ「\\」は、パスを記述する際のセパレータとして用いられていることに注意してください。

重要:パスを指定する際には、セパレータとして常にバックスラッシュを2つ使用します。なぜならコンパイラでは、単一のバックスラッシュは、プログラムソースコード内の定数行と文字定数をパースする際に制御文字と見なされるからです。


新しい可能性-リソース

MQL5プログラムで画像と音声を用いるために、使用されるすべてのメディアファイルが適切なフォルダに配置されていることを確認する必要があります。このため、コンパイルされたEX5ファイルを1つのターミナルから他のターミナルへ転送する際に、間違いなく不便をきたすことになります。しかし、コード記述の段階で、この問題を解決することができます。このような場合に、リソースを使用します。

プログラムでリソースを使うためには、コンパイラ指令#resourceを使って宣言する必要があります。

#resource path_to_resource_file

これにより、このリソースをファイルパスの代わりに使うことができます。#resourceコマンドは、特定のパス path_to_resource_fileが実行可能なEX5ファイルにインクルードされていることを、コンパイラに伝えます。したがって、すべての必要な画像や音声を、EX5ファイルに直接配置することが可能になります。もはや、MQL5プログラムを他のターミナルで起動するために、それに使われるすべてのファイルを転送する必要がないのです。

いずれのEX5ファイルもリソースを含むことが可能で、いずれのEX5プログラムも他のEX5プログラムにあるリソースを使うことができます。つまり、エキスパートアドバイザがインディケータやEX5ライブラリに配置されているリソースを使うことができるのです。これが、リソースを利用する新たな利点です。

リソースを使うことで、すべてを一括して得ることができます-すなわち、実行ファイル本体とそれが用いるすべてのリソースが、ソースコードのコンパイル中に1つのEX5ファイル内にパッケージされるのです。


コンパイラによるリソースの検索

リソースは、#resource "<path to the resource file>"という指令により特定されます。

#resource "<path_to_resource_file>"
定数列 ><path_to_resource_file>の長さは63文字を超えてはなりません。コンパイラは、以下のシーケンス内の特定のパスで、リソースを検索します:1
  • もしバックスラッシュ「\」がパスの先頭に配置されている際は、 リソースをterminal_data_directory\MQL5\以下の相対ディレクトリとして検索します。
  • バックスラッシュがない場合は、リソースはリソースが記述されているソースファイルの位置から相対的に検索されます。

重要:リソースパスでは、「..\\」と「:\\」のサブストリングは使用できません。

ヘルプ項目「リソース」からのリソースインクルードの例:

//--- Correct specification of a resource
#resource "\\Images\\euro.bmp" // euro.bmp is located in terminal_data_directory\MQL5\Images\
#resource "picture.bmp"        // picture.bmp is locate in the same directory with the source file
#resource "Resource\\map.bmp"  // The resource is located in the folder source_file_directory\Resource\map.bmp
 
//--- incorrect specification of resources
#resource ":picture_2.bmp"     // Use of ":" is not allowed
#resource "..\\picture_3.bmp"  // Use of ".." is not allowed
#resource "\\Files\\Images\\Folder_First\\My_panel\\Labels\\too_long_path.bmp" //More than 63 characters


リソース名

#resource指令を使ってリソースを宣言した後は、プログラムのどのパートでも用いることができます。リソースへのパスを定義する文字列の最初にある、スラッシュを除くパスが、リソース名として用いられます。

例:

//---Examples of specifying resources and their names in the comments
#resource "\\Images\\cat.bmp"           // Resource name - Images\cat.bmp
#resource "dog.bmp"                     // Resource name - dog.bmp
#resource "Resource\\map.bmp"           // Resource name - Resource\map.bmp
#resource "\\Files\\Pictures\\bird.bmp" // Resource name - Files\Pictures\bird.bmp
#resource "\\Files\\good.wav"           // Resource name - Files\good.wav"
#resource "\\Sounds\\thrill.wav"        // Resource name - Sounds\thrill.wav"

リソース名では大文字と小文字が区別されません-コンパイラから見ると、names dog.bmpとDOG.bmpは同一ということになります。


独自リソースとサードパーティーのリソースを使う

リソースを使うには、リソース名を特定する必要があります。リソース名は行の先頭で、バックスラッシュを除くパスを構成します。独自リソースを使う際には、特別な属性「::」をリソース名の前に加えなければなりません。

//--- Use of resources
ObjectSetString(0,bitmap_name,OBJPROP_BMPFILE,0,"::Images\\cat.bmp");
...
ObjectSetString(0,my_bitmap,OBJPROP_BMPFILE,0,"::dog.bmp");
...
set=ObjectSetString(0,bitmap_label,OBJPROP_BMPFILE,1,"::Files\\Pictures\\bird.bmp");
...
PlaySound("::Files\\good.wav");
...
PlaySound("::Sounds\\thrill.wav");

独自リソース(をEX5ファイルから)だけでなく、あらゆるEX5ライブラリやモジュールからも用いることができます。したがって、リソースのリポジトリを作成し、多くの他のmql5プログラム内で使うことができます。

他のEX5ファイルからリソースを使う場合は、リソース名は<EX5_file_name_path>::<resource_name>という形式で指定されなければなりません。Draw_Triangles_Script.mq5スクリプトが、triangle.bmpファイル内の画像に対するリソースを含むと仮定すると、リソースは以下のように指定されます。

#resource "\\Files\\triangle.bmp"

次に、スクリプトそのものを用いるために、リソース名は「Files\triangle.bmp」となり、さらに「::」がリソース名に追加されて-すなわち、「::Files\triangle.bmp」とならなければなりません。同じリソースを他のプログラムから使う、例えばエキスパートアドバイザから用いるためには、リソース名に、 terminal_data_directory\MQL5\からEX5ファイルへの相対パスと、さらに スクリプトのEX5ファイル名-Draw_Triangles_Script.ex5を追加しなければなりません。スクリプトが標準フォルダ terminal_data_directory\MQL5\Scripts\に配置されていると仮定すると、呼び出しは以下のように記述されなけばなりません:

//--- Use of a script resource in an Expert Advisor
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,"\\Scripts\\Draw_Triangles_Script.ex5::Files\\triangle_1.bmp");

他のEX5ファイルからリソースを呼び出す際、実行可能ファイルへのパスが特定されない場合には、実行可能ファイルは、リソースを呼び出すプログラムを含む同じフォルダ内で検索されます。これは、次のことを意味します: もしエキスパートアドバイザ がterminal_data_directory\MQL5\Experts\に配置され、Draw_Triangles_Script.ex5ファイルからのリソースがパスの指定なしに呼び出されると、このファイルはterminal_data_directory\MQL5\Experts\以下から検索されることになります。

//--- Request for a resource from a script in an Expert Advisor without path specification
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,"Draw_Triangles_Script.ex5::Files\\triangle_1.bmp");


EX5ファイルにおけるリソースの圧縮-どのように役立つか

BMPやWAVフォーマットのファイルは、実行可能なEX5ファイルにインクルードされる前に自動圧縮されます。これにより、リソースを使ってフル機能のMQL5プログラムを作成することができるだけでなく、MQL5の従来の記法に比べて、画像や音声を使う際にターミナルから呼び出されるファイルのサイズ全体を減らすことにもなります。

リソースファイルのサイズは、16 Mbを超えることはできません。

重要:リソースを用いるもう1つの利点は、実行可能なEX5ファイルをパッケージ化する際に、WAVファイルやBMPファイルが自動圧縮されることです。これによって、処理量だけでなく、プログラムが用いるファイルのサイズも減らすことができます。

例えば、Animals_EA.mq5という小さなプログラムを見てみましょう。リソースを用いた小さなコードブロックを、以下に示します:

//+------------------------------------------------------------------+
//|                                                   Animals_EA.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"
//--- Declare image resources
#resource "\\Images\\cat.bmp"
#resource "\\Images\\dog.bmp"
#resource "\\Images\\cow.bmp"
#resource "\\Images\\bird.bmp"
//--- Declare sound resources
#resource "\\Files\\MySounds\\cat.wav"
#resource "\\Files\\MySounds\\dog.wav"
#resource "\\Files\\MySounds\\cow.wav"
#resource "\\Files\\MySounds\\bird.wav"
//--- Object names
string cat_dog="cat_dog";
string cow_bird="cow_bird";
string canvas="canvas";
string text="text";
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Create a substrate
   CreateCanvas(canvas,50,50,500,500);
//--- Create buttons
   CreateObjectBITMAP_LABEL(cat_dog,110,120,"::Images\\cat.bmp","::Images\\dog.bmp");
   CreateObjectBITMAP_LABEL(cow_bird,110,330,"::Images\\cow.bmp","::Images\\bird.bmp");
   CreateText(text,"Click on any graphical object",200,90,clrTan);
//--- Give a command for an immediate refresh to see the object
   ChartRedraw();
//---
   return(0);
  }
//+------------------------------------------------------------------+
//|  Creating OBJ_BITMAP_LABEL with the specified images          |
//+------------------------------------------------------------------+
bool CreateObjectBITMAP_LABEL(string obj_name,int X,int Y,string res_name1,string res_name2)
  {
//--- If there is no such an object on the chart
   if(ObjectFind(0,obj_name)==-1)
     {
      //--- Create it
      bool res=ObjectCreate(0,obj_name,OBJ_BITMAP_LABEL,0,0,0);
      //--- Check the result
      if(!res)
        {
         PrintFormat("%s: Failed to create OBJ_BITMAP_LABEL with the name %s. Error code=%d",
                     __FUNCTION__,
                     GetLastError());
         return false;
        }
     }

//--- Set the coordinates
   ObjectSetInteger(0,obj_name,OBJPROP_XDISTANCE,X);
   ObjectSetInteger(0,obj_name,OBJPROP_YDISTANCE,Y);
//--- Disable display on the background
   ObjectSetInteger(0,obj_name,OBJPROP_BACK,false);
//--- Reset the error code
   ResetLastError();
//--- Set an image for the pressed condition
   bool res=ObjectSetString(0,obj_name,OBJPROP_BMPFILE,0,res_name1);
//--- Check the operation result
   if(!res)
     {
      PrintFormat("%s: Failed to upload an image from the resource %s. Error code=%d",
                  __FUNCTION__,
                  res_name1,
                  GetLastError());
      return false;
     }
//--- Set an image for the depressed state
   res=ObjectSetString(0,obj_name,OBJPROP_BMPFILE,1,res_name2);
//--- Check the operation result
   if(!res)
     {
      PrintFormat("%s: Failed to upload an image from the resource %s. Error code=%d",
                  __FUNCTION__,
                  res_name2,
                  GetLastError());
      return false;
     }
//--- Set the button pressed
   ObjectSetInteger(0,obj_name,OBJPROP_STATE,true);
   return true;
  }
//+------------------------------------------------------------------+

このプログラムのタスクは、青い背景上(ベース)に、マウスクリックによって外観が変わる2つのグラフィックボタンを表示することです。ベースをクリックすると、青からベージュに、またその逆に色が変わります。変更のたびに音声が再生され、マウスクリックのイベントは OnChartEvent()関数内でハンドリングされています。アドバイザであるAnimals_EA.mq5の起動直後に、図形内にチャートが表示されます。

OBJ_BITMAP_LABELオブジェクトのプロパティ、例えばcat_dogを見てみましょう。Bitmap File (On)とBitmap File (Off)というプロパティは、ダイアログボックスから変更ができなくなり、これらは利用できないフィールドとして見えなくなっています。

重要:グラフィックオブジェクトでは、リソースに搭載される画像をプログラムで変更することができます。オブジェクトのプロパティウィンドウから、これらのプロパティを手動で変更することもできません。

エキスパートアドバイザであるAnimals_EA.mq5で使用される画像サイズの合計は、430キロバイトです。

しかし、得られた実行可能ファイルであるAnimals_EA.ex5にはすべての画像が含まれますが、そのサイズは339キロバイトです。したがって、9ファイル(MQ5ファイル1つ、BMPファイル4つ、WAVファイル4つ)の代わりに、プログラムに必要なすべてのリソースを含む1つのEX5ファイルを得たことになります。

リソースには、24ビットまたは32ビットのBMP画像のみを使用できます。32ビットBMPはアルファ成分を含むことができます-この場合、画像を透過チャートとして用いることができます。

エキスパートアドバイザファイルであるAnimals_EA.mq5、また画像ファイルと音声ファイルは、本稿に添付されています:

  • 画像はimages.zipアーカイブから、terminal_data_directory\MQL5\Images\内に解凍されなければなりません。
  • MySounds.zipに含まれる音声は、 terminal_data_directory\MQL5\Files\MySounds\内に解凍されなければなりません。

ご自分のターミナルでこのプログラムを検証したい場合には、コンパイル済のエキスパートアドバイザであるAnimals_EA.ex5をそのままダウンロードしてください。必要なリソースはすべて含まれています。この場合、画像ファイルや音声ファイルをダウンロードし、インストールする必要はありません。


リソースとしてインクルードされるカスタムインディケータを使う

MQL5アプリケーション運用のために、1つまたはいくつかのカスタムインディケータが必要な場合があります。これらはすべて、実行可能なMQL5プログラムのコードに含めることができます。リソースとしてインディケータをインクルードすることで、アプリケーションを簡単に配布することができます。

以下に、terminal_data_folder\MQL5\Indicators\ directoryに配置されているSampleIndicator.ex5というカスタムインディケータをインクルードして用いる例を示します:

//+------------------------------------------------------------------+
//|                                                     SampleEA.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#resource "\\Indicators\\SampleIndicator.ex5"
int handle_ind;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   handle_ind=iCustom(_Symbol,_Period,"::Indicators\\SampleIndicator.ex5");
   if(handle_ind==INVALID_HANDLE)
     {
      Print("Expert: iCustom call: Error code=",GetLastError());
      return(INIT_FAILED);
     }
//--- ...
   return(INIT_SUCCEEDED);
  }

OnInit()関数内のカスタムインディケータが1つ以上のコピーを作成する場合には、特別に考慮する必要があります。このリソースは、以下の方法で指定されるべきことに留意してください:<path_EX5_file_name>::<resource_name>

例えば、SampleIndicator.ex5インディケータが、リソースとしてエキスパートアドバイザであるSampleEA.ex5を含む場合、カスタムインディケータの初期関数内でiCustom()を呼び出す時に自身を特定するパスは次のようになります:「\\Experts\\SampleEA.ex5::Indicators\\SampleIndicator.ex5」。このようにパスが明示されている場合、SampleIndicator.ex5カスタムインディケータはエキスパートアドバイザであるSampleEA.ex5への接続が固定され、独自に動作することができなくなります。

自身へのパスは、GetRelativeProgramPath()関数を用いて受け取ることができます。使用例を以下に示します:

//+------------------------------------------------------------------+
//|                                              SampleIndicator.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_plots 0
int handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- the wrong way to provide a link to itself
//--- string path="\\Experts\\SampleEA.ex5::Indicators\\SampleIndicator.ex5";  
//--- the right way to receive a link to itself
  string path=GetRelativeProgramPath();
//--- indicator buffers mapping
   handle=iCustom(_Symbol,_Period,path,0,0);
   if(handle==INVALID_HANDLE)
     {
      Print("Indicator: iCustom call: Error code=",GetLastError());
      return(INIT_FAILED);
     }
   else Print("Indicator handle=",handle);
//---
   return(INIT_SUCCEEDED);
  }
///....
//+------------------------------------------------------------------+
//| GetRelativeProgramPath                                           |
//+------------------------------------------------------------------+
string GetRelativeProgramPath()
  {
   int pos2;
//--- get the absolute path to the application
   string path=MQLInfoString(MQL_PROGRAM_PATH);
//--- find the position of "\MQL5\" substring
   int    pos =StringFind(path,"\\MQL5\\");
//--- substring not found - error
   if(pos<0)
      return(NULL);
//--- skip "\MQL5" directory
   pos+=5;
//--- skip extra '\' symbols
   while(StringGetCharacter(path,pos+1)=='\\')
      pos++;
//--- if this is a resource, return the path relative to MQL5 directory
   if(StringFind(path,"::",pos)>=0)
      return(StringSubstr(path,pos));
//--- find a separator for the first MQL5 subdirectory (for example, MQL5\Indicators)
//--- if not found, return the path relative to MQL5 directory
   if((pos2=StringFind(path,"\\",pos+1))<0)
      return(StringSubstr(path,pos));
//--- return the path relative to the subdirectory (for example, MQL5\Indicators)
   return(StringSubstr(path,pos2+1));
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,        
                const double& price[])
  {
//--- return value of prev_calculated for next call
   return(rates_total);
  }


ターミナルのメモリを節約する

各リソースは、ターミナルメモリ内に1度だけロードされます。通常の使用下では、ファイルにアクセスするごとにファイルロードがメモリに追加されます。例えば、50のOBJ_BITMAPオブジェクトがあり、それぞれがサイズ100キロバイトの同じ画像を含むと仮定します。すると、通常の使用ではこれら50のオブジェクトは、50×100キロバイト=5メガバイトのメモリを必要とすることになります。

もしアップロードされた画像へのリソースを宣言すれば、この画像は、使用されるオブジェクトの数にかかわらず1度だけロードされることになります。

重要:リソースはメモリに1度だけロードされ、複数回利用されたとしてもメモリを節約することができます。


結論

リソースを使うと、MQL5プログラムの利用や配布が容易になります。使いやすく最新のトレーディングツールを作成するには、マルチメディアベースの画像ファイルや音声ファイルを使う必要があります。MQL5におけるリソースの概念は簡単でかつ分かりやすいため、ぜひとも試してみてください。

32ビットBMPフォーマット画像にはアルファ成分を含むことができます-この場合、画像を透過チャートに応用することができます。

リソースには以下の利点があります:

  • コンパクトである-すべてのファイルが実行可能な単一のEX5ファイルにパッケージされるため、プログラムの転送や起動が容易になります;
  • 省メモリ-ターミナルメモリは、プログラム内での利用頻度にかかわらず常に、各リソースにつき1つのインスタンスのみを含みます;
  • 便利なストレージ-すべてのリソースを含む1つのEX5ファイルは、元の画像ファイルや音声ファイルの合計より少なくなります。

MetaQuotes Software Corp.によりロシア語から翻訳された
元の記事: https://www.mql5.com/ru/articles/261

添付されたファイル |
mysounds.zip (65.89 KB)
images.zip (214.29 KB)
wheremyfolders.mq5 (1.46 KB)
animals_ea.mq5 (18 KB)
animals_ea.ex5 (393.38 KB)
メタトレーダー5における検証の原則 メタトレーダー5における検証の原則

メタトレーダー5の3つの検証モードの違いは何でしょうか、また、特に何が求められているのでしょうか?複数手段で同時にトレードを行うEAの検証は、どのように行われるのでしょうか?検証中は、いつどのようにしてインディケータの値が計算され、イベントはどのように処理されるのでしょうか?「始値オンリー」モードの検証中に、異なる金融商品のバーを同期させるにはどうしたらいいでしょうか?本稿ではこれらをはじめとする、多くの質問に答えてみます。

MQL5のExpert Advisorsのテストと最適化を行うためのガイド MQL5のExpert Advisorsのテストと最適化を行うためのガイド

ここでは、コードエラーを見つけ解決するための段階的な手順について説明します。またExpert Advisor(以下EA)への入力パラメータのテストと最適化の手順についても説明します。Meta Trader 5のクライアント端末のStrategy Testerの使い方がわかれば、ご自身のEAに最も適したシンボルや入力パラメータセットを見つけることができるようになります。

MQL5ウィザード:新バージョン MQL5ウィザード:新バージョン

本稿では、最新のMQL5ウィザードで利用できる新しい特徴について述べます。シグナルのアーキテクチャが変更され、さまざまなマーケットパターンにもどつくトレーディングロボットを作成することができるようになっています。本稿に含まれる例では、エキスパートアドバイザのインタラクティブな作成手順を説明しています。

カスタムグラフィックコントロールパート1:簡単なコントロールを作成する カスタムグラフィックコントロールパート1:簡単なコントロールを作成する

本稿では、グラフィックコントロールの一般的な原則を網羅します。グラフィックオブジェクトの作業を早く便利に行うためのツールを用意し、テキストや数値データの入力のために簡単なコントロールを作成する方法や、その使用方法の例を分析していきます。