English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
MQL5でのティックインディケーターの作成

MQL5でのティックインディケーターの作成

MetaTrader 5インディケータ | 18 9月 2015, 17:32
3 131 0
Denis Zyatkevich
Denis Zyatkevich

はじめに

トレーディングでは価格変更の画像を詳細に見るために、できるだけ情報があることが望ましいです。 ティックチャートを使用できます。MQL5でティックチャートを作成してみましょう。

本記事はティック価格チャートと指定ティック数を含むロウソク足を作画する「Tick Candles」チャートの2つのインディケーター作成を説明します。 考察された各インディケーターは、クライアントターミナルの再起動後にインディケーターデータを構築するため、受信価格値をファイルに書きます。(このデータは他のプログラムにも使われます。)


Tickインディケーター作成

チャートで Tickデータを作画するインディケーターをMQL5で書きましょう。このようなインディケーター例は図. 1に表されます。 :

図 1. Tickチャートの例

インディケーターは売値と買値の2つのラインをプロットします。それらの作画はそれぞれインディケーターのオプションでオフにできます。

インディケーターはブローカーから受領した現シンボルの価格をテキストファイル内に以下のフォーマットで保存します。: サーバータイム、売値と買値:

2010.03.26 19:43:02 1.33955 1.33968

ファイル名は金融商品名に対応します。 (例、EURUSD.txt)。ファイルは以下のパスにあります。: MT5_Folder\MQL5\Files。ファイルの追加ディレクトリとファイル名の固定文字はインディケーターオプションで指定できます。 (同じシンボルでチャートに添付されているインディケーターがいくつかあると便利かもしれません。)

インディケーターを作成するには、MetaTrader 5 クライアントターミナルを立ち上げ、 F4 キーを押してMetaQuotes言語 Editorを立ち上げ ます。プログラムコードを書き始めましょう。

価格チャート下別のウインドウでインディケーターがプロットされるように指定します。:

// indicator in a separate window
#property indicator_separate_window

2つのインディケーターライン (売値と買値それぞれ) が作画されるはずなので2つのグラフィックプロットを使わなければなりません。:

// two graphic plots are used: for Bid and Ask lines
#property indicator_plots 2

チャートにプロットされるデータを含む2つインディケーターバッファーを指定しなければなりません。 :

// two indicator's buffers
#property indicator_buffers 2

各インディケーターラインで、作画タイプ DRAW_LINE (ライン), 作画スタイル STYLE_SOLID (実線) とテキストラベル 「Bid」と 「Ask」を定義しましょう。:

// drawing type of a Bid line
#property indicator_type1 DRAW_LINE
// drawing color of a Bid line
#property indicator_color1 Red
// drawing style of a Bid line
#property indicator_style1 STYLE_SOLID
// text label of a Bid line
#property indicator_label1 "Bid"
// drawing type of an Ask line
#property indicator_type2 DRAW_LINE
// drawing color of an Ask line
#property indicator_color2 Blue
// drawing style of an Ask line
#property indicator_style2 STYLE_SOLID
// text label of an Ask line
#property indicator_label2 "Ask"

入力変数を指定しましょう。 その値はユーザーがインディケーターのオプションメニューで変えられます。

// the BidLineEnable indicates showing of a Bid line
input bool BidLineEnable=true; // Show Bid Line
// the AskLineEnable indicates showing of an Ask line
input bool AskLineEnable=true; // Show Ask Line
// the path_prefix defines a path and file name prefix
input string path_prefix=""; // FileName Prefix

BidLineEnable AskLineEnable 変数でBidとAskラインをインディケーター内に表示したり無効にしたりできます。path_prefix 変数でファイル名の前にあるファイル名の固定文字を指定できます。この変数を使って、パスをサブディレクトリにも指定できます。例えばもし path_prefix = "MyBroker/test_"の場合、ファイルへのパスが以下になります。: "MetaTrader5_Folder\MQL5\Files\MyBroker"、シンボル「EURUSD」の場合ファイル名は「test_EURUSD.txt」でしょう。

グローバルレベルで、 インディケーターのいろいろな関数で使用される変数を宣言しましょう。これらの変数の値はインディケーターの呼び出しの間で保存されます。 :

// the tick_stored variable is a number of served quotes
int ticks_stored;
// the BidBuffer[] and AskBuffer[] arrays - are indicator's buffers
double BidBuffer[],AskBuffer[];

tick_stored 変数は利用できる気配値の数を保存するのに使用されます。BidBuffer[]AskBuffer[] はインディケーターバッファーとして使用される 動的配列で、チャートにBid とAskラインとしてプロットされる価格データはこれらのバッファーに保存されます。

OnInit 関数は、 BidBuffer[]AskBuffer[] 配列がプロット用のデータを含むことを示しています。インディケーターバッファー値付きのゼロに等しいデータはチャートにプロットされないように指定しましょう。

void OnInit()
  {
   // the BidBuffer[] is an indicator buffer
   SetIndexBuffer(0,BidBuffer,INDICATOR_DATA);
   // the AskBuffer[] is an indicator buffer
   SetIndexBuffer(1,AskBuffer,INDICATOR_DATA);
   // setting EMPTY_VALUE for a Bid line
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
   // setting EMPTY_VALUE for an Ask line
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0);
  }

では、OnCalculate 関数を作成し、呼び出し時、その関数に渡される全てのパラメータをリストしましょう。:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])

変数を宣言しましょう。:

// the file_handle variable is a file handle
// the BidPosition and AskPosition - are positions of Bid and Ask prices in the string;
// the line_string_len is a length of a string, read from the file, i is a loop counter;
int file_handle,BidPosition,AskPosition,line_string_len,i;
// the last_price_bid is the last Bid quote
double last_price_bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
// the last_price_ask is the last Ask quote
double last_price_ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
// the filename is a name of a file, the file_buffer is a string, 
// used as a buffer for reading and writing of string data
string filename,file_buffer;

整数タイプの file_handle 変数は、ファイルのハンドルをファイルオペレーションに保存するために使用され、 BidPositionAskPositionは文字列の売値と買値開始ポジションの保管に使用され、line_string_len はファイルから読まれる文字列長に使用され、 i 変数はループカウンターとして使用されます。最後に受信した売値と買値の値はlast_price_bidlast_price_ask 変数に保管されます。ファイル名文字列変数がファイル名を保管するのに使用され、file_bufferはファイルの読み込みと書き込みに使用される文字列です。

ファイル名は path_prefix 変数、金融商品名と".txt" ファイル拡張子から成ります。 StringConcatenate 関数を使用した方が作動が早くメモリ上経済的なので、加算演算子を使った文字列の連結よりも好まれます。

// File name formation from the path_prefix variable, name
// of financial instrument and ".Txt" symbols
StringConcatenate(filename,path_prefix,Symbol(),".txt");

さらに使用するためにFileOpen 関数を使ってファイルを開きます。 :

// Opening a file for reading and writing, codepage ANSI, shared reading mode
file_handle=FileOpen(filename,FILE_READ|FILE_WRITE|FILE_ANSI|FILE_SHARE_READ);

データをファイルへ読み書きするため FILE_READ と FILE_WRITEフラグを使います。FILE_ANSI フラグはANSI コードページが使用される事を示します。 (デフォルトは Unicode)、FILE_SHARE_READ フラグは他のアプリケーションによってそれが一緒に働く時にアクセスが共有されることを意味します。

インディケーター立ち上げの最初は、データが何もありません。 (またはチャート期間が変化):

 // At first execution of OnCalculate function, we are reading the quotes from a file
 if(prev_calculated==0)
  {
   // Reading the first line from the file and determine the length of a string
   line_string_len=StringLen(FileReadString(file_handle))+2;
   // if file is large (contains more quotes than rates_total/2)
   if(FileSize(file_handle)>(ulong)line_string_len*rates_total/2)
     {
      // Setting file pointer to read the latest rates_total/2 quotes
      FileSeek(file_handle,-line_string_len*rates_total/2,SEEK_END);
      // Moving file pointer to the beginning of the next line
      FileReadString(file_handle);
     }
   // if file size is small
   else
     {
      // Moving file pointer at the beginning of a file
      FileSeek(file_handle,0,SEEK_SET);
     }
   // Reset the counter of stored quotes
   ticks_stored=0;
   // Reading until the end of the file
   while(FileIsEnding(file_handle)==false)
    {
      // Reading a string from the file
      file_buffer=FileReadString(file_handle);
      // Processing of string if its length is larger than 6 characters
      if(StringLen(file_buffer)>6)
        {
         // Finding the start position of Bid price in the line
         BidPosition=StringFind(file_buffer," ",StringFind(file_buffer," ")+1)+1;
         // Finding the start position of Ask price in the line
         AskPosition=StringFind(file_buffer," ",BidPosition)+1;
         // If the Bid line should be plotted, adding this value to BidBuffer[] array
         if(BidLineEnable) 
         BidBuffer[ticks_stored]=StringToDouble(StringSubstr(file_buffer,BidPosition,AskPosition-BidPosition-1));
         // If the Ask line should be plotted, adding this value to AskBuffer[] array
         if(AskLineEnable) 
         AskBuffer[ticks_stored]=StringToDouble(StringSubstr(file_buffer,AskPosition));
         // Increasing the counter of stored quotes
         ticks_stored++;
        }
     }
  }

チャート上のバー数の半分によって、ファイルから読まれるべき気配値の数を制限します。 最初にファイルから文字列を読み、長さを決めます。ラインの最後に、コード10 と13が付いた2つの追加文字 (「新しいライン」 と 「キャリッジリターン」) があるので、 ラインの長さを2つ増やさなければなりません。

ファイルの残りのラインの平均の長さが同じであると想定します。もしファイルの長さが rates_total/2の数の1つのラインの長さより長い場合(例えばもし、ファイルがrates_total/2よりも多くの気配値を含む) 、 rates_total/2 最後の気配値だけを読みます。そうするには、 ファイル ポインターを rates_total/2 による文字列の長さに等しい距離に設定し(ファイルの最後から) 、ファイルから1つのラインを読み、 ファイルポインターをラインの始めにあわせます。

2つの値を if 演算子を使って比較しますが、それらは別のタイプがあります。: ファイル長はulong タイプ、式の右側は int タイプを持ちます。そのため、式の右側に、ulong タイプへの明示的な型キャストを行います。

もし、ファイルの気配値がrates_total/2よりも少ない場合、ファイルポインターをファイルの最初に移動します。

気配値カウンターをゼロにセットし、 ラインをファイルから、ファイルの最後に到達するまで読みます。6文字より長い文字列に文字列処理が実行されます。 -これは日付・時間・bidとask・それらの区切りの一文字を含む最小文字列長です。もし対応するラインがプロットされ、 気配値カウンターが増える場合、我々はファイルから読まれる文字列から売値と買値を抽出します。

もし、 データが前に読まれている場合、 FileSeek 関数を使ってファイルポインターをファイルの最後に移動します。 (新しい データがファイルに書かれる。) StringConcatenate 関数を使い、FileWrite 関数を使ってファイルに書かれる文字列を作ります。 対応ラインがプロットされ、 気配値カウンターが増える場合、BidBuffer[]AskBuffer[], 配列に売値と買値の新しい値を追加します。

// If the data have been read before
else
  {
   // Moving file pointer at the end of the file
   FileSeek(file_handle,0,SEEK_END);
   // Forming a string, that should be written to the file
   StringConcatenate(file_buffer,TimeCurrent()," ",DoubleToString(last_price_bid,_Digits)," ",DoubleToString(last_price_ask,_Digits));
   // Writing a string to the file
   FileWrite(file_handle,file_buffer);
   // If the Bid line should be plotted, adding the last Bid price to the BidBuffer[] array
   if(BidLineEnable) BidBuffer[ticks_stored]=last_price_bid;
   // If the Ask line should be plotted, adding the last Ask price to the AskBuffer[] array
   if(AskLineEnable) AskBuffer[ticks_stored]=last_price_ask;
   // Increasing the quotes counter
   ticks_stored++;
  }

なぜ、OnInit 関数内のファイルからデータを読まないのかと疑問に思われている方もいるでしょう。理由は以下です。: BidBuffer[]AskBuffer[] 動的配列の長さが定義されていなく、OnCalculate 関数の呼び出し時に指定されます。

以前の開いたファイルを閉じます。:

// Closing the file
FileClose(file_handle);

ファイルからの読み込み後または BidBuffer[]AskBuffer[] 配列の追加後、もし気配値カウンターがチャートのバー数以上の場合、古い気配値の半分が削除され、 残りがそれらの場所に移動されます。

// If number of quotes is more or equal than number of bars in the chart
if(ticks_stored>=rates_total)
  {
   // Removing first tick_stored/2 quotes and shifting remaining quotes
   for(i=ticks_stored/2;i<ticks_stored;i++)
     {
      // If the Bid line should be plotted, shifting the values of BidBuffer[] array on tick_stored/2
      if(BidLineEnable) BidBuffer[i-ticks_stored/2]=BidBuffer[i];
      // If the Ask line should be plotted, shifting the values of AskBuffer[] array on tick_stored/2
      if(AskLineEnable) AskBuffer[i-ticks_stored/2]=AskBuffer[i];
     }
   // Changing the value of a counter
   ticks_stored-=ticks_stored/2;
  }

インディケーターバッファーの BidBuffer[]AskBuffer[] 配列は時系列ではないので、 最近のエレメントは ticks_stored-1,に等しいインデックスを持ち、最近のチャートはrates_total-1に等しいインデックスを持ちます。それらを同じレベルに複合するには、インディケーターのラインをPlotIndexSetInteger 関数を使ってシフトしましょう。:

// Shifting the Bid line to align with the price chart
PlotIndexSetInteger(0,PLOT_SHIFT,rates_total-ticks_stored);
// Shifting the Ask line to align with the price chart
PlotIndexSetInteger(1,PLOT_SHIFT,rates_total-ticks_stored);

最近受信した価格は BidBuffer[]AskBuffer[]rates_total-1 に等しいインデックスと共に保管され、(もし対応ラインがプロットされる場合)、インディケーターウインドウの左角に表示されます。

// If the Bid line should be plotted, placing the value to the last element 
// of BidBuffer [] array to show the last Bid price in the indicator's window  
if(BidLineEnable) BidBuffer[rates_total-1]=last_price_bid;
// If the Ask line should be plotted, placing the value to the last element 
// of AskBuffer [] array to show the last Ask price in the indicator's window
if(AskLineEnable) AskBuffer[rates_total-1]=last_price_ask;

OnCalculate 関数の実行は、return of rates_totalの戻しで完了します。 (ゼロ以外のどんな番号も戻せます。) 関数のコードは丸括弧で終わります。

// Return from OnCalculate(), return a value, different from zero   
return(rates_total);
}

Tickインディケーターが書かれました。インディケーターの完全なソースコード記事下のリンクでダウンロードできます。


「Tick Candles」 インディケーターの作成

いわゆる「ティックロウソク足」をプロットするインディケーターを書きましょう。各ロウソク足が指定時間期間に対応していた以前のロウソク足チャートと違って、「ティックロウソク足」 チャートは違った構造を持ちます。: 各ロウソク足は、ブローカーからの受け取ったティックの事前定義ナンバーがあります。(equivolume ロウソク足)。インディケーターは図 2のように見えます。:

図 2. 「Tick Candles」インディケーター

「Tick Candles」インディケーターは上記のTick インディケーターと同様、 ファイルに全ての受信気配値を書きます。データフォーマットとファイルの位置は同じです。ロウソク足のファイルパス・名前接頭辞・ティック数と価格のタイプ (BidまたはAsk) はインディケーターのオプションで指定できます。

インディケーターを作成するには、MetaTrader 5 クライアントターミナルを立ち上げ、 F4 キーを押してMetaQuotes言語 Editorを立ち上げ ます。

別のウインドウでプロットされるよう指定しましょう。:

// Indicator is plotted in a separate window
#property indicator_separate_window

インディケーターは一つのグラフィックプロットのみ持ちます。: カラーロウソク足。

// One graphic plot is used, color candles
#property indicator_plots 1

カラーロウソク足と各ロウソク足の価格データ値 (始値・高値・安値・終値) を表示するには4つのバッファーが必要です。 またロウソク足のカラーインデックスを保存するのにバッファーがもう一つ必要です。

// We need 4 buffers for OHLC prices and one - for the index of color
#property indicator_buffers 5

作画タイプ: DRAW_COLOR_CANDLES - カラーロウソク足を指定しましょう。

// Specifying the drawing type - color candles
#property indicator_type1 DRAW_COLOR_CANDLES

ロウソク足に使用される色を指定しましょう。:

// Specifying the colors for the candles
#property indicator_color1 Gray,Red,Green

BidまたはAskの値の1つを含む列挙タイプ price_types を作りましょう。 : :

/ / Declaration of the enumeration
enum price_types
  (
   Bid,
   Ask
  )

インディケーターのオプションメニューでユーザーが変更できる 入力パラメータを指定しましょう。:

// The ticks_in_candle input variable specifies the number of ticks,
// corresponding to one candle
input int ticks_in_candle=16; //Tick Count in Candles
// The applied_price input variable of price_types type indicates 
// the type of the data, that is used in the indicator: Bid or Ask prices.
input price_types applied_price=0; // Price
// The path_prefix input variable specifies the path and prefix to the file name
input string path_prefix=""; // FileName Prefix

ticks_in_candle 変数はロウソク足に対応するティック数を指定します。applied_price 変数はロウソク足構築に使用される価格タイプ(BidまたはAsk)を示します。 ディレクトリとヒストリカルTickデータのファイルのファイル名固定文字は path_prefix 変数で指定できます。

インディケーター呼び出しの間に保存されるべき値を持つ変数は グローバルレベルに宣言されます。

// The ticks_stored variable contains the number of stored quotes
int ticks_stored;
// The TicksBuffer [] array is used to store the incoming prices
// The OpenBuffer [], HighBuffer [], LowBuffer [] and CloseBuffer [] arrays
// are used to store the OHLC prices of the candles
// The ColorIndexBuffer [] array is used to store the index of color candles
double TicksBuffer[],OpenBuffer[],HighBuffer[],LowBuffer[],CloseBuffer[],ColorIndexBuffer[];

ticks_stored 変数は、利用できる気配値の数を保存するのに使われます。 TicksBuffer[] 配列は受信気配値の保管に使用され、OpenBuffer[], HighBuffer[], LowBuffer[]そして CloseBuffer[] 配列はチャートにプロットされるロウソク足価格(始値・高値・安値・終値)の保存に使われます。 ColorIndexBuffer[] 配列はロウソク足のカラーインデックスの保存に使用されます。

OnInit 関数は OpenBuffer[], HighBuffer[], LowBuffer[] そして CloseBuffer[] 配列がインディケーターバッファーとして使われることを示し、ColorIndexBuffer[] 配列がロウソク足のカラーインデックスを含み、TicksBuffer[] 配列が中間計算に使用されます。 :

void OnInit()
  {
   // The OpenBuffer[] array is an indicator buffer
   SetIndexBuffer(0,OpenBuffer,INDICATOR_DATA);
   // The HighBuffer[] array is an indicator buffer
   SetIndexBuffer(1,HighBuffer,INDICATOR_DATA);
   // The LowBuffer[] array is an indicator buffer
   SetIndexBuffer(2,LowBuffer,INDICATOR_DATA);
   // The CloseBuffer[] array is an indicator buffer
   SetIndexBuffer(3,CloseBuffer,INDICATOR_DATA);
   // The ColorIndexBuffer[] array is the buffer of the color index
   SetIndexBuffer(4,ColorIndexBuffer,INDICATOR_COLOR_INDEX);
   // The TicksBuffer[] array is used for intermediate calculations
   SetIndexBuffer(5,TicksBuffer,INDICATOR_CALCULATIONS);

次に、OpenBuffer[], HighBuffer[], LowBuffer[], CloseBuffer[] そして ColorIndexBuffer[] 配列を時系列に指定します。 (つまり最新のデータがインデックス 0):

// The indexation of OpenBuffer[] array as timeseries
   ArraySetAsSeries(OpenBuffer,true);
   // The indexation of HighBuffer[] array as timeseries
   ArraySetAsSeries(HighBuffer,true);
   // The indexation of LowBuffer[] array as timeseries
   ArraySetAsSeries(LowBuffer,true);
   // The indexation of CloseBuffer[] array as timeseries
   ArraySetAsSeries(CloseBuffer,true);
   // The indexation of the ColorIndexBuffer [] array as timeseries
   ArraySetAsSeries(ColorIndexBuffer,true);

値が0に等しいインディケーターバッファーはチャートにプロットされるべきではありません。:

// The null values of Open prices (0th graphic plot) should not be plotted
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
   // The null values of High prices (1st graphic plot) should not be plotted
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0);
   // The null values of Low prices (2nd graphic plot) should not be plotted
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0);
   // The null values of Close prices (3rd graphic plot) should not be plotted
   PlotIndexSetDouble(3,PLOT_EMPTY_VALUE,0);

OnInit 関数の作成が完了し、丸括弧を使ってその関数を閉じます。

OnCalculate関数を書く時が来ました。その関数に渡される全てのパラメータを指定しましょう。:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

OnInit 関数に使用される変数 を宣言しましょう。

// the file_handle variable is a file handle
// the BidPosition and AskPosition - are positions of Bid and Ask prices in the string;
// the line_string_len is a length of a string, read from the file, 
// CandleNumber - number of candle, for which the prices OHLC are determined,
// i - loop counter;
int file_handle,BidPosition,AskPosition,line_string_len,CandleNumber,i;
// The last_price_bid variable is the recent received Bid price
double last_price_bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
// The last_price_ask variable is the recent received Ask price
double last_price_ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
// the filename is a name of a file, the file_buffer is a string, 
// used as a buffer for reading and writing of string data
string filename,file_buffer;

整数タイプのfile_handle 変数は、ファイル操作の中のファイルのハンドルを保存するのに使用され、BidPositionAskPosition は文字列の売値と買値 開始ポジションの保存に使われ、 line_string_len はファイルから読む文字列長で、 CandleNumber は計算されたロウソク足のインデックスで、 i 変数はループカウンターとして使用されます。

最近受信した売値と買値はダブルタイプのlast_price_bidlast_price_ask 変数に保管されます。文字列タイプのfilename 変数はファイル名の保管に使用され、 file_buffer はファイル操作に使用される文字列です。

インディケーターバッファーである OpenBuffer[], HighBuffer[], LowBuffer[], CloseBuffer[] そして ColorIndexBuffer[]と違って TicksBuffer[] 配列のサイズは自動でセットされないので、配列TicksBuffer[] のサイズを OpenBuffer[], HighBuffer[], LowBuffer[], CloseBuffer[] そして ColorIndexBuffer[] 配列と同じサイズに設定しましょう。:

// Setting the size of TicksBuffer[] array
ArrayResize(TicksBuffer,ArraySize(CloseBuffer));

path_prefix 変数からファイル 名、 金融商品名、そして「.txt」拡張子を準備します。:

// File name formation from the path_prefix variable, name
// of financial instrument and ".Txt" symbols
StringConcatenate(filename,path_prefix,Symbol(),".txt");

上記で説明した以前のインディケーター用のパラメータと共にファイルを開きましょう。

// Opening a file for reading and writing, codepage ANSI, shared reading mode
file_handle=FileOpen(filename,FILE_READ|FILE_WRITE|FILE_ANSI|FILE_SHARE_READ);

もし、 OnCalculate 関数が最初にが呼ばれ、TicksBuffer[] 配列にデータが何もない場合、ファイルから読みます。:

if(prev_calculated==0)
  {
   // Reading the first line from the file and determine the length of a string
   line_string_len=StringLen(FileReadString(file_handle))+2;
   // if file is large (contains more quotes than rates_total/2)
   if(FileSize(file_handle)>(ulong)line_string_len*rates_total/2)
     {
      // Setting file pointer to read the latest rates_total/2 quotes
      FileSeek(file_handle,-line_string_len*rates_total/2,SEEK_END);
      // Moving file pointer to the beginning of the next line
      FileReadString(file_handle);
     }
   // if file size is small
   else
     {
      // Moving file pointer at the beginning of a file
      FileSeek(file_handle,0,SEEK_SET);
     }
   // Reset the counter of stored quotes
   ticks_stored=0;
   // Reading until the end of the file
   while(FileIsEnding(file_handle)==false)
     {
      // Reading a string from thefile
      file_buffer=FileReadString(file_handle);
      // Processing of string if its length is larger than 6 characters
      if(StringLen(file_buffer)>6)
        {
         // Finding the start position of Bid price in the line
         BidPosition=StringFind(file_buffer," ",StringFind(file_buffer," ")+1)+1;
          //Finding the start position of Ask price in the line
         AskPosition=StringFind(file_buffer," ",BidPosition)+1;
         // If the Bid prices are used, adding the Bid price to TicksBuffer[] array
         if(applied_price==0)
         TicksBuffer[ticks_stored]=StringToDouble(StringSubstr(file_buffer,BidPosition,AskPosition-BidPosition-1));
         // If the Ask prices are used, adding the Ask price to TicksBuffer[] array
         if(applied_price==1)
         TicksBuffer[ticks_stored]=StringToDouble(StringSubstr(file_buffer,AskPosition));
         // Increasing the counter of stored quotes
         ticks_stored++;
        }
     }
  }

ファイル からの気配値の読み込みは上記で詳しく説明しました。以前のインディケーターと同じです。

もし、 気配値が TicksBuffer[] 配列で前に読まれたなら、新しい価格値をファイルに書き、新しい価格を TicksBuffer[] 配列に置き、気配値カウンターを増やします。:

// If the data have been read before
else
  {
   // Moving file pointer at the end of the file
   FileSeek(file_handle,0,SEEK_END);
   // Forming a string, that should be written to the file
   StringConcatenate(file_buffer,TimeCurrent()," ",DoubleToString(last_price_bid,_Digits)," ",DoubleToString(last_price_ask,_Digits));
   // Writing a string to the file
   FileWrite(file_handle,file_buffer);
   // If the Bid prices are used, adding the last Bid price to TicksBuffer[] array
   if(applied_price==0) TicksBuffer[ticks_stored]=last_price_bid;
   // If the Ask prices are used, adding the last Ask price to TicksBuffer[] array
   if(applied_price==1) TicksBuffer[ticks_stored]=last_price_ask;
   // Increasing the quotes counter
   ticks_stored++;
  }

ファイルを閉じます:

// Closing the file
FileClose(file_handle);

もし、保管気配値が価格チャートのバー数またはそれ以上になった場合、 最古のデータの半分を除き、 残りのデータをシフトします。:

// If number of quotes is more or equal than number of bars in the chart
if(ticks_stored>=rates_total)
  {
   // Removing the first tick_stored/2 quotes and shifting remaining quotes
   for(i=ticks_stored/2;i<ticks_stored;i++)
     {
      // Shifting the data to the beginning in the TicksBuffer[] array on tick_stored/2
      TicksBuffer[i-ticks_stored/2]=TicksBuffer[i];
     }
   // Changing the quotes counter
   ticks_stored-=ticks_stored/2;
  }

各ロウソク足のOHLC値を計算して、これらの値を対応するインディケーターバッファーに置きましょう。:

// We assign the CandleNumber with a number of invalid candle
   CandleNumber=-1;
   // Search for all the price data available for candle formation
   for(i=0;i<ticks_stored;i++)
     {
      // If this candle is forming already
      if(CandleNumber==(int)(MathFloor((ticks_stored-1)/ticks_in_candle)-MathFloor(i/ticks_in_candle)))
        {
         // The current quote is still closing price of the current candle
         CloseBuffer[CandleNumber]=TicksBuffer[i];
         // If the current price is greater than the highest price of the current candle,
          // it will be a new highest price of the candle
         if(TicksBuffer[i]>HighBuffer[CandleNumber]) HighBuffer[CandleNumber]=TicksBuffer[i];
         // If the current price is lower than the lowest price of the current candle, 
          // it will be a new lowest price of the candle
         if(TicksBuffer[i]<LowBuffer[CandleNumber]) LowBuffer[CandleNumber]=TicksBuffer[i];
         // If the candle is bullish, it will have a color with index 2 (green)
         if(CloseBuffer[CandleNumber]>OpenBuffer[CandleNumber]) ColorIndexBuffer[CandleNumber]=2;
         // If the candle is bearish, it will have a color with index 1 (red)
         if(CloseBuffer[CandleNumber]<OpenBuffer[CandleNumber]) ColorIndexBuffer[CandleNumber]=1;
         // If the opening and closing prices are equal, then the candle will have a color with index 0 (grey)
         if(CloseBuffer[CandleNumber]==OpenBuffer[CandleNumber]) ColorIndexBuffer[CandleNumber]=0;
        }
      // If this candle hasn't been calculated yet
      else
        {
         // Let's determine the index of a candle
         CandleNumber=(int)(MathFloor((ticks_stored-1)/ticks_in_candle)-MathFloor(i/ticks_in_candle));
         // The current quote will be the opening price of a candle
         OpenBuffer[CandleNumber]=TicksBuffer[i];
         // The current quote will be the highest price of a candle
         HighBuffer[CandleNumber]=TicksBuffer[i];
         // The current quote will be the lowest price of a candle
         LowBuffer[CandleNumber]=TicksBuffer[i];
         // The current quote will be the closing price of a candle
         CloseBuffer[CandleNumber]=TicksBuffer[i];
         // The candle will have a color with index 0 (gray)
         ColorIndexBuffer[CandleNumber]=0;
        }
     }

OnCalculate 関数の実行は非ゼロ値の戻しで完了しますが、それはTicksBuffer[] 配列がすでにデータを持ち、 その関数の次の呼び出し時にそれらを読む事が不要である事を意味します。その関数の最後にクロージングの丸括弧を置きます。

 // Return from OnCalculate(), return a value, different from zero   
 return(rates_total);
}

記事の最後にインディケーターの完全なソースコードをダウンロードできるリンクがあります。


結論

本記事では、Tickチャートインディケーターと「tick candles」インディケーターの2つのTickインディケーターの作成を考察しました。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/60

添付されたファイル |
tickindicator.mq5 (8.28 KB)
MQL5でExpert Advisorを書くための初心者向けステップバイステップガイド MQL5でExpert Advisorを書くための初心者向けステップバイステップガイド
MQL5のExpert Advisorプログラミングはシンプルで簡単に学べます。ステップバイステップガイドでは、策定されたトレーディングストラテジーに基づきシンプルなExpert Advisorを書くのに必要な基本的ステップを説明します。Expert Advisorの構造、内蔵 テクニカルインディケーターとトレーディング関数の使用、 デバッグモード の詳細とストラテジーテスターの使用を紹介します。
MQL5での作画スタイル MQL5での作画スタイル
MQL4では、6つ作画スタイルがありますが、MQL5では18の作画スタイルがあります。そのため、MQL5の作画スタイルを紹介する記事を書くに値するかもしれません。本記事では、MQL5での作画スタイルの詳細を考えます。 さらに、 インディケーターを作成してどのようにこれらの作画スタイルを使い、プロットを洗練するかお見せします。
スタンダードライブラリーのクラスとグーグルチャートAPIを用いて情報ボードを生成する スタンダードライブラリーのクラスとグーグルチャートAPIを用いて情報ボードを生成する
MQL5 プログラミング言語は主に自動取引システムと複雑な技術的解析の道具の創造をターゲットとしている。. しかしこのことを別として、これはマーケットの状況の追跡に対する興味深いシステムの創造も可能にし、トレーダーとの相互のつながりを与える。この記事ではMQL5の標準ライブラリーの要素とこのような目的に到達するための実例を示すことにする。またチャート作成のためのグーグルチャートAPIの使用についても例を示す。
MQL5でのインディケーター の呼び方 MQL5でのインディケーター の呼び方
MQLプログラミング言語の新バージョンでは、 インディケーター扱いアプローチが変化しただけでなく、インディケーター作成の新しい方法があります。さらに、 インディケーターバッファーの取り組みがより柔軟になり、今では希望のインデックス方向を指定し、好きなだけインディケーター値を入手できます。本記事ではインディケーター呼び出しとインディケーターバッファーからのデータ検索の基本方法を 説明します。