English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
3つのラインブレイクチャートを作成するためのインディケータ

3つのラインブレイクチャートを作成するためのインディケータ

MetaTrader 5 | 23 12月 2015, 15:06
1 864 0
Dmitriy Zabudskiy
Dmitriy Zabudskiy

はじめに

先行記事では ポイント&フィギュアカギ足およびレンコチャートを考察しました。20世紀のチャートについてのシリーズを続け、今回は3つのラインブレイクチャート、正確には、プログラムコードを用いたその実装についてお話します。このチャートの出自についてはほとんど情報がありません。私は日本で始まったのではないかと思っています。USA では人は1994年に出版された Steve Nison 氏の著書"Beyond Candlesticks" by からそれを学びました

上記チャート同様、3つのラインブレイクチャートを作成する際、時間範囲は考慮されません。新たに形成される特定のタイムフレームの終値を基にしており、それにより前の変動に関して価格のマイナー変動にフィルターを描けることができるのです。

Steve Nison 氏は著書 "Beyond Candlesticks"の中でこのチャートをプロットするうえで11の原則を説明しています(p. 185)。それを私は3個にまとめました。

  • 原則 No.1:作成のために開始価格を選択し、マーケットの上下により上昇線または下降線を引く。それが新しい最大値、最小値をマークします。
  • 原則 No.2:新しい価格が最低値より落ちる、または最大値を超えるとき、下降線または上昇線を描く。
  • 原則 No.3:前回の動きと逆方向の線を引くには、最小値または最大値を横切る必要がある。同時に、複数の同一ラインがある場合、最小値/最大値はそのうちの2つ(連続した同一ラインが2本ある場合)または3つ(連続した同一ラインが3本以上ある場合)を基に計算されます。

履歴データに基づく古典的チャートの作成例を詳しくみます(図1)。

図1 3つのラインブレイクチャート例(EURUSD H1 27.06.2014)

図1 3つのラインブレイクチャート例(EURUSD H1 27.06.2014)

図1は左側にろうそく足チャートを、右側に3つのラインブレイクチャートを表示しています。これはEURUSD についてタイムフレーム H1 の チャートです。チャートの開始日は2014年6月27日、価格は 1.3613(ろうそくのクロース時刻は 00:00)、ろうそく(01:00)は1.3614でクローズしています。このとき3つのラインブレイクチャートの最初の下降線を形成しています。続くベア方向のろうそく(02:00)は上昇ラインを形成し、1.3612(終値は前回の最小値より低くなっています) でクローズしています。

それからブルのろうそく足が価格を 1.3619 (03:00) マークに向かって動かしています。このとき新しい最大値とラインを形成しています。04:00 のろうそくは最小値より下がらず構成に影響はありませんでした。05:00 のろうそくは1.3623 でクローズし、新しい最大値(新しい上昇ライン)をマークしています。

ここで下降トレンドを伸ばすために、2つの最小値(1.3613)を渡す必要がありますが、ブルは叔父ションをあきらめず、新しい最大値1.3626 (06:00)を形成します。それからブルは2時間上昇トレンドを逆行しようとしていますが、1.3634 (09:00)で達成された新しい最大値を持つ同じトレンドが継続します。ブルが牽引しています。ここで下降ラインを描くためには3つの最小値(1.3626;1.3623 と 1.3619)が渡される必要があります。

みてのとおり、次の3時間はベアがマーケットを引継ぎ、1.3612 (12:00)ポイントまで下げています。それは新しい上昇ラインに反映されています。ただし、次の5時間、ブルがポジションを奪い返し、マーケットを1.3641ポイントまで戻し、前回の最大値を 1.3626で渡し、17:00に新しい上昇ラインを形成しています。ベアは 18:00 に前回の最小値を渡すのを失敗し、続く5時間にブルが1.3649ポイントまでマーケットを上げ、毎時新しい上昇ラインを形成しています。


チャート作成の基礎

コードを取得する前に、インディケータそのものについてお話し、その他との差別化のポイントとどのようにそれを行うか明確にします。その他のインディケータ同様、3つのラインブレイクが効率的なマーケット分析を促し新しい戦略を模索するために作られたのは明白です。みなさんが、何か変わっている点があるのか知りたいとお思いなのはわかっています。実際数点あります。このインディケータでは計算のために価格タイプを変更できます。それは4つのバー価格すべてに対応しています。古いタイプは1つの価格タイプ対応でチャート構成がなされていますが、最新のものは4つの価格タイプ(open、high、low、close)すべてに対応するようになっています。それはラインに『ヒゲ』を追加し、日本式のろうそく足のように見せることで古典的なチャート構造の外観を変えます。それによりチャートの視覚に加わるものです。

近代化されたバージョンは優先価格で不足価格を代用するオンタイムのデータ同期化の設定機能を備えています。

近代化されたチャートタイプの構造は図2に表示しています。

図2 4つの価格タイプに基づく修正済みチャート

図2 4つの価格タイプに基づく修正済みチャート

近代化された構造は異なる価格タイプの3つのラインブレイクチャートを4つ組み合わせているので、価格間の不一致を見つけるのは当然です。それを避けるには、オンタイムの同期が必要となります。価格同期化のバリエーションは2つあります。完全同期(図2の右)と部分同期(図2の左)です。完全同期はフィルターにかけられた部分同期です。ここえデータはすべてチャート上に描かれ、不足データは設定で指定される優先価格で代用されます。完全同期モードでは不足データはただ省略され、完全なデータセットを持つろうそく足だけが描かれます。

その他の改良点はピリオドセパレータです。これはシグナルの分割が便利なように導入されました。ご承知のとおり、ピリオドセパレータはチャート設定で有効にすることができます。インディケータではそれは設定で指定されるタイムフレームによって変化します。期間が縦の破線で分けられる MetaTrader 5チャートとは異なり、このインディケータでは新しい期間はライン色(図3のろうそく)を変えることで表現されます。

図3 インディケータのピリオドセパレータ

図3 インディケータのピリオドセパレータ

もう一つの追加事項は、テクニカルインディケータr iMAの導入です。それはメインチャートの価格を基に構築されますが、オンタイムでインディケータデータと同期します。そのためデータは移動平均によってフィルターにかけられます(図4)。

図4 内部移動平均

図4 内部移動平均

このインディケータはラインを描くポイントの最小の移動と逆転に必要なライン数を設定する機能も備えています。それはフィルターの役目をします。


インディケータコード

インディケータのアルゴリズムはかなりシンプルで、3段階です。データのコピー、コピーされたデータを基にした計算、インディケータバッファの書き込み(受け取りデータを基にチャート作成)です。コードは関数同士または入力データと相互連携する関数に分けられます。コードを詳しくみていきます。

1. インディケータの入力パラメータ

インディケータのプリアンブルにはグラフィック構成の宣言が入っています。インディケータにはそれが2つあります。:チャート"ABCTB" (DRAW_COLOR_CANDLES) と追加の移動平均"LINE_TLB" (DRAW_LINE)です。したがって、バッファは6個ということです。それからインターフェースの設定とそれ自体の設定を改善する enumタイプのデータが続きます。

  • magic_numb -マジックナンバーのタイプは longです。それはインディケータを表記するユニークな数字です。必要に応じ、いくつかの修正で string タイプに変換可能です。
  • time_frame -計算時間範囲はENUM_TIMEFRAMESタイプで、メインパラメータ(インディケータのタイムフレーム)です。
  • time_redraw ―チャート更新間隔。タイプは ENUM_TIMEFRAMESです。それはチャート再計算が行われる間のタイムフレームです。チャートを速く再作成するにはキーボードの "R" キーを押します。インディケータの統合制御です。
  • first_date_start -開始日付。タイプは datetime。これはデータコピーとチャート化を開始するポイントであるメインパラメータです。
  • chart_price-計算用の価格タイプ(0-クローズ、1-オープン、2-高、3-低)。古いタイプのチャート構造では価格タイプを一つ選択する必要があります。すでにお話したとおり、このパラメータは修正済み構造が有効な場合無視されます。
  • step_min_f -新しい行(>0, type int)に対する最小ステップまたはライン描写のために必要なジャンプ。
  • line_to_back_f -逆転を表示するライン数(>0, type int) 。古いタイプは逆転を表示するのに3本のラインを提案します。
  • chart_type-チャート構造タイプ(0-古い、1-修正後)、タイプ 選択。それは構造タイプ間の切り替えです。
  • chart_color_period-新しい期間開始時の色変更(booleanタイプ)。新しい期間開始時にライン色変更に使用します。
  • chart_synchronization -完全同期でのみチャートを作成(boolean タイプ。真であればチャート作成前に不足値をすべてドロップして完全同期が起こります)。
  • chart_priority_close-終値の優先順位(タイプselect、4つのバリエーションがあります)。これは部分同期で終値の優先順位を指摘し、完全同期では無視されます。
  • chart_priority_open -始値の優先順位ここでも同様です。
  • chart_priority_high -高値の優先順位ここでも同様です。
  • chart_priority_low-安値の優先順位ここでも同様です。
  • ma_draw-平均値を描きます(booleanタイプ。真であれば移動平均を描きます。)
  • ma_price-平均を構築するための価格タイプ。 ENUM_APPLIED_PRICEの一つの可能性があります。
  • ma_method-構造タイプ。 ENUM_MA_METHODの一つの可能性があります。
  • ma_period移動平均期間を平均化します。

それからバッファ配列、変数、計算に必要なストラクチャを宣言します。

//+------------------------------------------------------------------+
//|                                                        ABCTB.mq5 |
//|                                 "Azotskiy Aktiniy ICQ:695710750" |
//|                        "" |
//+------------------------------------------------------------------+
// ABCTB - Auto Build Chart Three Line Break
#property copyright "Azotskiy Aktiniy ICQ:695710750"
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   2
//--- plot ABCTB
#property indicator_label1  "ABCTB"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue,clrRed,clrGreenYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot LINE_TLB
#property indicator_label2  "LINE_TLB"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- Price type for calculation
enum type_price
  {
   close=0, // Close
   open=1,  // Open
   high=2,  // Hight
   low=3,   // Low
  };
//--- type of chart construction
enum type_build
  {
   classic=0,  // Classic
   modified=1, // Modified
  };
//--- priority
enum priority
  {
   highest_t=4, // Highest
   high_t=3,    // High
   medium_t=2,  // Medium
   low_t=1,     // Low
  };
//--- input parameters
input long               magic_numb=65758473787389;                // Magic number
input ENUM_TIMEFRAMES    time_frame=PERIOD_CURRENT;                // Calculation time range
input ENUM_TIMEFRAMES    time_redraw=PERIOD_M1;                    // Period of chart updates
input datetime           first_date_start=D'2013.03.13 00:00:00';  // Start date
input type_price         chart_price=close;                        // Price type for calculation (0-Close, 1-Open, 2-High, 3-Low)
input int                step_min_f=4;                             // Minimum step for a new column (>0)
input int                line_to_back_f=3;                         // Number of lines to display a reversal(>0)
input type_build         chart_type=classic;                       // Type of chart construction (0-classic, 1-modified)
input bool               chart_color_period=true;                  // Changing color for a new period
input bool               chart_synchronization=true;               // Constructing a chart only upon complete synchronization
input priority           chart_priority_close=highest_t;           // Priority of the closing price
input priority           chart_priority_open=highest_t;            // Priority of the opening price
input priority           chart_priority_high=highest_t;            // Priority of the maximum price
input priority           chart_priority_low=highest_t;             // Priority of the minimum price
input bool               ma_draw=true;                             // Draw the average
input ENUM_APPLIED_PRICE ma_price=PRICE_CLOSE;                     // Price type for constructing the average
input ENUM_MA_METHOD     ma_method=MODE_EMA;                       // Construction type
input int                ma_period=14;                             // Averaging period
//--- indicator buffers
//--- buffer of the chart
double         ABCTBBuffer1[];
double         ABCTBBuffer2[];
double         ABCTBBuffer3[];
double         ABCTBBuffer4[];
double         ABCTBColors[];
//--- buffer of the average
double         LINE_TLBBuffer[];
//--- variables
MqlRates rates_array[];// bar data array for analysis
datetime date_stop;    // current date
datetime date_start;   // start date variable for calculation
//+------------------------------------------------------------------+
//| Struct Line Price                                                |
//+------------------------------------------------------------------+
struct line_price// structure for storing information about the past lines
  {
   double            up;  // value of the high price
   double            down;// value of the low price
  };
//+------------------------------------------------------------------+
//| Struct Line Information                                          |
//+------------------------------------------------------------------+
struct line_info// structure for storing information about the shared lines
  {
   double            up;
   double            down;
   char              type;
   datetime          time;
  };
line_info line_main_open[];  // data on the opening prices chart
line_info line_main_high[];  // data on the maximum prices chart
line_info line_main_low[];   // data on the minimum prices chart
line_info line_main_close[]; // data on the closing prices chart
//+------------------------------------------------------------------+
//| Struct Buffer Info                                               |
//+------------------------------------------------------------------+
struct buffer_info// structure for storing data for filling a buffer
  {
   double            open;
   double            high;
   double            low;
   double            close;
   char              type;
   datetime          time;
  };
buffer_info data_for_buffer[];// data for filling the modified construction buffer
datetime array_datetime[];    // array for storing information of the time for every line
int time_array[3];            // array for the function func_date_color
datetime time_variable;       // variable for the function func_date_color
bool latch=false;             // variable-latch for the function func_date_color
int handle;                   // handle of the indicator iMA
int step_min;                 // variable of the minimum step
int line_to_back;             // variable of the number of lines to display a reversal

2. 関数 OnInit

インディケータバッファはすべて関数OnInit 内で宣言され、配列表示はtimeseriesのようにセットアップされます。

それからチャートに反映されないインディケータ値を設定し、 名前を設定し、精度を指定し、チャートをオーバーロードさせるため現在値を消去します。ここでインディケータ iMA のハンドルを設定し入力したデータが正確か確認します。エラーが発生した場合はメッセージが表示され、値が最小値に変更されます。

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
//--- buffers for a chart
   SetIndexBuffer(0,ABCTBBuffer1,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer1,true);
   SetIndexBuffer(1,ABCTBBuffer2,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer2,true);
   SetIndexBuffer(2,ABCTBBuffer3,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer3,true);
   SetIndexBuffer(3,ABCTBBuffer4,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer4,true);
   SetIndexBuffer(4,ABCTBColors,INDICATOR_COLOR_INDEX);
   ArraySetAsSeries(ABCTBColors,true);
//--- buffer for constructing the average
   SetIndexBuffer(5,LINE_TLBBuffer,INDICATOR_DATA);
   ArraySetAsSeries(LINE_TLBBuffer,true);
//--- set the values that are not going to be reflected on the chart
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); // for the chart
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0); // for the average
//--- set the indicator appearance
   IndicatorSetString(INDICATOR_SHORTNAME,"ABCTB "+IntegerToString(magic_numb)); // name of the indicator
//--- accuracy of display
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- prohibit displaying the results of the indicator current value
   PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(1,PLOT_SHOW_DATA,false);
//---
   handle=iMA(_Symbol,time_frame,ma_period,0,ma_method,ma_price);
   if(step_min_f<1)
     {
      step_min=1;
      Alert("Minimum step for a new column must be greater than zero");
     }
   else step_min=step_min_f;
//---
   if(line_to_back_f<1)
     {
      line_to_back=1;
      Alert("The number of lines to display a reversal must be greater than zero");
     }
   else line_to_back=line_to_back_f;
//---
   return(INIT_SUCCEEDED);
  }

3. データコピーを行う関数

インディケータは価格の4タイプすべてを処理するようにできているため、データすべてをコピーするのは基本です。これには時間のコピーも含まれます。MQL5 では MqlRatesと呼ばれるストラクチャがあります。それはトレードセッション開始時刻、価格、ボリューム、スプレッドに関する情報を格納するのに使用されます。

この関数の入力パラメータは開始日と終了日、タイムフレーム、MqlRatesタイプの対象配列です。この関数はコピーが正常に行われると真を返します。データは内部配列にコピーされます。計算された不足データプラス1セッションはそこにコピーされ、データは永久に更新され続けます。内部配列へのコピーが正常に行われれば、データは配列にコピーされ、関数の正常な動作を確認するため渡されます。

//+------------------------------------------------------------------+
//| Func All Copy                                                    |
//+------------------------------------------------------------------+
bool func_all_copy(MqlRates &result_array[],// response array
                   ENUM_TIMEFRAMES period,  // timeframe
                   datetime data_start,     // start date
                   datetime data_stop)      // end date
  {
//--- declaration of auxiliary variables
   bool x=false;       // variable for the function response
   int result_copy=-1; // copied data count
//--- adding variables and arrays for calculation
   static MqlRates interim_array[]; // temporary dynamic array for storing copied data
   static int bars_to_copy;         // number of bars for copying
   static int bars_copied;          // number of copied bars since the start date
//--- find out the current number of bars in the time range
   bars_to_copy=Bars(_Symbol,period,data_start,data_stop);
//--- count the number of bars to be copied
   bars_to_copy-=bars_copied;
//--- if it is not the first time when data is being copied
   if(bars_copied>0)
     {
      bars_copied--;
      bars_to_copy++;
     }
//--- change the size of the receiving array
   ArrayResize(interim_array,bars_to_copy);
//--- copy data to a temporary array
   result_copy=CopyRates(_Symbol,period,0,bars_to_copy,interim_array);
//--- check the result of copying data
   if(result_copy!=-1) // if copying to the temporary array was successful
     {
      ArrayCopy(result_array,interim_array,bars_copied,0,WHOLE_ARRAY); // copy the data from the temporary array to the main one
      x=true;                   // assign the positive response to the function
      bars_copied+=result_copy; // increase the value of the copied data
     }
//---
   return(x);
  }

4. データ計算を行う関数う

この関数は3つのラインブレイクチャートの古い構造についてデータを計算するプロトタイプです。すでにお話しましたが、この関数はデータ計算のみ行い、それをコードの最初に宣言されるストラクチャタイプ line_info の特殊配列にそれを構成します。

この関数には他に2つの関数を持ちます。:func_regrouping(関数の再グループ化を行います)とfunc_insert(関数を挿入します)がそれです。それらを最初からみていきます。

4.1. グループか関数

この関数は同方向の連続ラインについての情報をグループ化します。それはそれに渡される配列サイズ、または正確にはインディケータ設定のパラメータline_to_back_f(逆転を表示するライン数)によって制限されています。この関数にコントロールが渡されるたびに、同一ラインについて受け取られたデータはすべて最後に向かって1ポイント下がり、新しい値によってインデックス0が埋められます。

これはブレイクに必要なラインに関する情報が格納される方法です(古い構造ではブレイクのラインは3本です)。

//+------------------------------------------------------------------+
// Func Regrouping                                                   |
//+------------------------------------------------------------------+
void func_regrouping(line_price &input_array[],// array for regrouping
                     double new_price,         // new price value
                     char type)                // type of movement
  {
   int x=ArraySize(input_array);// find out the size of the array for regrouping
   for(x--; x>0; x--)           // regrouping loop
     {
      input_array[x].up=input_array[x-1].up;
      input_array[x].down=input_array[x-1].down;
     }
   if(type==1)
     {
      input_array[0].up=new_price;
      input_array[0].down=input_array[1].up;
     }
   if(type==-1)
     {
      input_array[0].down=new_price;
      input_array[0].up=input_array[1].down;
     }
  }

4.2. 挿入を行う関数

この関数は応答配列に値を挿入します。オードはシンプルですから細かい説明は必要ありません。

//+------------------------------------------------------------------+
// Func Insert                                                       |
//+------------------------------------------------------------------+
void func_insert(line_info &line_m[],  // target array
                 line_price &line_i[], // source array
                 int index,            // array element being inserted
                 char type,            // type of the target column
                 datetime time)        // date
  {
   line_m[index].up=line_i[0].up;
   line_m[index].down=line_i[0].down;
   line_m[index].type=type;
   line_m[index].time=time;
  }

データ計算用の関数は従来3つの部分に分けられます。最初の部分はオペレータ switch.の助けを借りて分析中のデータを中間配列にコピーします。関連する価格のみコピーされます。2番目の部分はデータ配列にスペースが必要とされる計算のテスト実行を行います。それから応答のために最初に関数に渡されるデータ配列line_main_array[]に変更が加えられます。3番目の部分は今度は調整済みデータ配列に書き込みを行います。

//+------------------------------------------------------------------+
//| Func Build Three Line Break                                      |
//+------------------------------------------------------------------+
void func_build_three_line_break(MqlRates &input_array[],      // array for analysis
                                 char price_type,              // type of the price under analysis (0-Close, 1-Open, 2-High, 3-Low)
                                 int min_step,                 // minimum step for drawing a line
                                 int line_back,                // number of lines for a reversal
                                 line_info &line_main_array[]) // array for return (response) of the function
  {
//--- calculate the size of the array for analysis
   int array_size=ArraySize(input_array);
//--- extract data required for calculation to an intermediate array
   double interim_array[];// intermediate array
   ArrayResize(interim_array,array_size);// adjust the intermediate array to the size of the data
   switch(price_type)
     {
      case 0: // Close
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].close;
           }
        }
      break;
      case 1: // Open
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].open;
           }
        }
      break;
      case 2: // High
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].high;
           }
        }
      break;
      case 3: // Low
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].low;
           }
        }
      break;
     }
//--- enter the variables for storing information about current situation
   line_price passed_line[];// array for storing information about the latest prices of the lines (type structure line_price)
   ArrayResize(passed_line,line_back+1);
   int line_calc=0;// number of lines
   int line_up=0;// number of the last ascending lines
   int line_down=0;// number of the last descending lines
   double limit_up=0;// upper limit necessary to pass
   double limit_down=0;// lower limit necessary to pass
/* Fill variables informing of the current situation with the first values */
   passed_line[0].up=interim_array[0];
   passed_line[0].down=interim_array[0];
//--- start the first loop to calculate received data for filling a buffer for drawing
   for(int x=0; x<array_size; x++)
     {
      if(line_calc==0)// no lines have been drawn
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_down++;
           }
        }
      if(line_up>line_down)// last ascending line (lines)
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[(int)MathMin(line_up,line_back-1)].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<limit_down)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_up=0;
            line_down++;
           }
        }
      if(line_down>line_up)// last descending line (lines)
        {
         limit_up=passed_line[(int)MathMin(line_down,line_back-1)].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>limit_up)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_down=0;
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_down++;
           }
        }
     }
   ArrayResize(line_main_array,line_calc);// change the size of the target array
//--- zeroise variables and fill with the the initial data
   line_calc=0;
   line_up=0;
   line_down=0;
   passed_line[0].up=interim_array[0];
   passed_line[0].down=interim_array[0];
//--- start the second loop to fill a buffer for drawing
   for(int x=0; x<array_size; x++)
     {
      if(line_calc==0)// no lines have been drawn
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_down++;
           }
        }
      if(line_up>line_down)// last ascending line (lines)
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[(int)MathMin(line_up,line_back-1)].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<limit_down)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_up=0;
            line_down++;
           }
        }
      if(line_down>line_up)// last descending line (lines)
        {
         limit_up=passed_line[(int)MathMin(line_down,line_back-1)].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>limit_up)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_down=0;
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_down++;
           }
        }
     }
  }

5. チャート作成を行う関数

選択された作成パラメータ(古いものまたは改善後)を基にチャートのためのデータを計算し、表示データでインディケータバッファに書き込みを行うのがこの関数の目的です。前出の関数同様、チャート作成関数にもあと3つの関数があります。それらは色、同期、移動平均の関数です。それらについて詳しくお話します。

5.1. 色関数

この関数には入力パラメータが1つしかありません。時間です。この関数の応答はブール変数です。渡されたデータが期間の境界であれば、この関数は真を返します。期間は選択されたタイムフレームに依存するため、この関数は条件演算子 ifによる内蔵期間分離を持ちます。期間が選択されると、それは新しい期間がもう開始されたか確認されます。それは日付をクトラクチャMqlDateTimeに変換し比較することで行われます。 H2を含むここまでのタイムフレームに対しては、日付の値における変更は新しい期間の始まりを示します。H12 ~ D1 のタイムフレームは包括的に月間の変更、W1 と MN の間では変更を年間で確認します。

残念ながらストラクチャMqlDateTime は現週の情報を持ちません。この問題は変数time_variableで表される初期ポイントを作成することで解決されました。さらにラインについては、週の秒数がこの日付から差し引かれます。

//+------------------------------------------------------------------+
// Func Date Color                                                   |
//+------------------------------------------------------------------+
bool func_date_color(datetime date_time) // input date
  {
   bool x=false;// response variable
   int seconds=PeriodSeconds(time_frame);// find out the calculation time range
   MqlDateTime date;
   TimeToStruct(date_time,date);// convert data
   if(latch==false) // check the state of the latch
     {
      MqlDateTime date_0;
      date_0=date;
      date_0.hour=0;
      date_0.min=0;
      date_0.sec=0;
      int difference=date_0.day_of_week-1;
      datetime date_d=StructToTime(date_0);
      date_d=date_d-86400*difference;
      time_variable=date_d;
      latch=true;// lock the latch
     }
   if(seconds<=7200)// period is less than or equal to H2
     {
      if(time_array[0]!=date.day)
        {
         x=true;
         time_array[0]=date.day;
        }
     }
   if(seconds>7200 && seconds<=43200)// period is greater than H2 but less than or equal to H12
     {
      if(time_variable>=date_time)
        {
         x=true;
         time_variable=time_variable-604800;
        }
     }
   if(seconds>43200 && seconds<=86400)// period is greater than H12 but less than or equal to D1
     {
      if(time_array[1]!=date.mon)
        {
         x=true;
         time_array[1]=date.mon;
        }
     }
   if(seconds>86400)// period W1 or MN
     {
      if(time_array[2]!=date.year)
        {
         x=true;
         time_array[2]=date.year;
        }
     }
   return(x);
  }

5.2. 同期の関数

同期の関数には入力パラメータが6個あります。:4個は価格優先順位、完全同期または部分同期のブールタイプパラメータ、分析中の配列そのものです。この関数は2つの部分に分かれます。:完全同期と部分同期の場合です。

完全同期は3段階で行われます。

  1. 配列エレメントの計算、4つの価格タイプすべてのデータを持つ条件を満たすこと。
  2. 同上ケンカの中間配列にエレメントをコピー。
  3. 中間配列からパラメータによって渡される配列へのコピー。

部分同期はもっと複雑です。

渡される一次元ストラクチャ配列は二次元配列に変換されます。ここで最初のインデックスは注文を2番目のインデックスは価格タイプを示します。それから取り入れられるのは、エレメントを4つ持つ一次元配列です。価格優先レベルはこの配列にコピーされ、そうすると配列は優先順位を特定するためにソートされます。その後、ループforと条件演算子 ifにより優先順位に従って分配を行います。同時に、優先順位が同じ場合は、価格シーケンスは次のようになります。:終わり、始め、高、低。オペレータifが優先順位1番の値をみつけるとすぐに、ループ for が先に作成された二次元配列内のゼロデータすべてに優先順位1の値などを代入します。

//+------------------------------------------------------------------+
// Func Synchronization                                              |
//+------------------------------------------------------------------+
void func_synchronization(buffer_info &info[],
                          bool synchronization,
                          char close,
                          char open,
                          char high,
                          char low)
  {
   if(synchronization==true)// carry out a complete synchronization
     {
      int calc=0;// count variable
      for(int x=0; x<ArraySize(info); x++)// count complete data
        {
         if(info[x].close!=0 && info[x].high!=0 && info[x].low!=0 && info[x].open!=0)calc++;
        }
      buffer_info i_info[];    // enter a temporary array for copying
      ArrayResize(i_info,calc);// change the size of the temporary array
      calc=0;
      for(int x=0; x<ArraySize(info); x++)// copy data into the temporary array
        {
         if(info[x].close!=0 && info[x].high!=0 && info[x].low!=0 && info[x].open!=0)
           {
            i_info[calc]=info[x];
            calc++;
           }
        }
      ZeroMemory(info);        // clear the target array
      ArrayResize(info,calc);  // change the size of the main array
      for(int x=0; x<calc; x++)// copy data from the temporary array to the main one
        {
         info[x]=i_info[x];
        }
     }
   if(synchronization==false)  // change zero values to priority ones
     {
      int size=ArraySize(info); // measure the size of the array
      double buffer[][4];       // create a temporary array for calculation
      ArrayResize(buffer,size); // change the size of the temporary array
      for(int x=0; x<size; x++) // copy data into the temporary array
        {
         buffer[x][0]=info[x].close;
         buffer[x][1]=info[x].open;
         buffer[x][2]=info[x].high;
         buffer[x][3]=info[x].low;
        }
      char p[4];// enter an array for sorting by the order
      p[0]=close; p[1]=open; p[2]=high; p[3]=low;// assign variables for further sorting
      ArraySort(p); // sort
      int z=0,v=0;  // initialize frequently used variables
      for(int x=0; x<4; x++)// taking into account the results of the sorting, look through all variables and substitute them according to the priority
        {
         if(p[x]==close)// priority is for the closing prices
           {
            for(z=0; z<size; z++)
              {
               for(v=1; v<4; v++)
                 {
                  if(buffer[z][v]==0)buffer[z][v]=buffer[z][0];
                 }
              }
           }
         if(p[x]==open)// priority is for the opening prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<4; v++)
                 {
                  if(v!=1 && buffer[z][v]==0)buffer[z][v]=buffer[z][1];
                 }
              }
           }
         if(p[x]==high)// priority is for the maximum prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<4; v++)
                 {
                  if(v!=2 && buffer[z][v]==0)buffer[z][v]=buffer[z][2];
                 }
              }
           }
         if(p[x]==low)// priority is for the minimum prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<3; v++)
                 {
                  if(buffer[z][v]==0)buffer[z][v]=buffer[z][3];
                 }
              }
           }
        }
      for(int x=0; x<size; x++)// copy data from the temporary array back
        {
         info[x].close=buffer[x][0];
         info[x].open=buffer[x][1];
         info[x].high=buffer[x][2];
         info[x].low=buffer[x][3];
        }
     }
  }

5.3. 移動平均の関数

もっともシンプルな関数です。インディケータハンドルを用い、関数で受け取られると、関数のパラメータで渡されるデータに相当する値をコピーします。そうするとこの関数の応答としてその値が返されます。

//+------------------------------------------------------------------+
// Func MA                                                           |
//+------------------------------------------------------------------+
double func_ma(datetime date)
  {
   double x[1];
   CopyBuffer(handle,0,date,1,x);
   return(x[0]);
  }

チャートをプロットする関数は従来2つの部分に分けられます。:古いタイプのプロットと改善後のププロットです。この関数は入力パラメータを2つ持ちます。:構造用価格タイプ(改善後の構造では無視されます)と構造タイプ(古いタイプと改善後)です。

一番最初にインディケータバッファが消去され、それから構造タイプによって二分割されます。最初の部分(改善後構造について話しています)は4つの価格タイプすべてを計算する関数を呼びだすことで始まります。それから共通データ配列を作成し、そこにデータ計算関数を呼ぶときに受け取られる使用中のデータをコピーします。それから取得したデータ配列はソートされ、複製データから消去されます。その後、グル―バルレベルで宣言される配列に以下のデータ同期化を持つ連続データを基に書き込みが行われます。インディケータバッファへの書き込みは改善後構造では最終段階です。

2番目の部分(古い構造)はもっとシンプルです。最初にデータ計算関数が呼びだされ、それからインディケータバッファの書き込みが行われます。

//+------------------------------------------------------------------+
//| Func Chart Build                                                 |
//+------------------------------------------------------------------+
void func_chart_build(char price, // price type for chart construction
                      char type)  // type of chart construction
  {
//--- Zeroise the buffers
   ZeroMemory(ABCTBBuffer1);
   ZeroMemory(ABCTBBuffer2);
   ZeroMemory(ABCTBBuffer3);
   ZeroMemory(ABCTBBuffer4);
   ZeroMemory(ABCTBColors);
   ZeroMemory(LINE_TLBBuffer);
   if(type==1)// construct a modified chart (based on all price types)
     {
      func_build_three_line_break(rates_array,0,step_min,line_to_back,line_main_close);// data on closing prices
      func_build_three_line_break(rates_array,1,step_min,line_to_back,line_main_open);// data on opening prices
      func_build_three_line_break(rates_array,2,step_min,line_to_back,line_main_high);// data on maximum prices
      func_build_three_line_break(rates_array,3,step_min,line_to_back,line_main_low);// data on minimum prices
      //--- calculate data arrays
      int line_main_calc[4];
      line_main_calc[0]=ArraySize(line_main_close);
      line_main_calc[1]=ArraySize(line_main_open);
      line_main_calc[2]=ArraySize(line_main_high);
      line_main_calc[3]=ArraySize(line_main_low);
      //--- gather the date array
      int all_elements=line_main_calc[0]+line_main_calc[1]+line_main_calc[2]+line_main_calc[3];// find out the number of all elements
      datetime datetime_array[];// enter the array for copying
      ArrayResize(datetime_array,all_elements);
      int y[4];
      ZeroMemory(y);
      for(int x=0;x<ArraySize(datetime_array);x++)// copy data into the array
        {
         if(x<line_main_calc[0])
           {
            datetime_array[x]=line_main_close[y[0]].time;
            y[0]++;
           }
         if(x<line_main_calc[0]+line_main_calc[1] && x>=line_main_calc[0])
           {
            datetime_array[x]=line_main_open[y[1]].time;
            y[1]++;
           }
         if(x<line_main_calc[0]+line_main_calc[1]+line_main_calc[2] && x>=line_main_calc[0]+line_main_calc[1])
           {
            datetime_array[x]=line_main_high[y[2]].time;
            y[2]++;
           }
         if(x>=line_main_calc[0]+line_main_calc[1]+line_main_calc[2])
           {
            datetime_array[x]=line_main_low[y[3]].time;
            y[3]++;
           }
        }
      ArraySort(datetime_array);// sort the array
      //--- delete replicated data from the array
      int good_info=1;
      for(int x=1;x<ArraySize(datetime_array);x++)// count useful information
        {
         if(datetime_array[x-1]!=datetime_array[x])good_info++;
        }
      ArrayResize(array_datetime,good_info);
      array_datetime[0]=datetime_array[0];// copy the first element as it is the pattern in the beginning of comparison
      good_info=1;
      for(int x=1;x<ArraySize(datetime_array);x++)// fill the new array with useful data
        {
         if(datetime_array[x-1]!=datetime_array[x])
           {
            array_datetime[good_info]=datetime_array[x];
            good_info++;
           }
        }
      //--- fill the buffer for drawing (colored candles)
      int end_of_calc[4];// variables of storing information about the last comparison
      ZeroMemory(end_of_calc);
      ZeroMemory(data_for_buffer);
      ArrayResize(data_for_buffer,ArraySize(array_datetime));// change the size of the declared global array for storing data before passing it to a buffer
      for(int x=0; x<ArraySize(array_datetime); x++)
        {
         data_for_buffer[x].time=array_datetime[x];
         for(int s=end_of_calc[0]; s<line_main_calc[0]; s++)
           {
            if(array_datetime[x]==line_main_close[s].time)
              {
               end_of_calc[0]=s;
               if(line_main_close[s].type==1)data_for_buffer[x].close=line_main_close[s].up;
               else data_for_buffer[x].close=line_main_close[s].down;
               break;
              }
           }
         for(int s=end_of_calc[1]; s<line_main_calc[1]; s++)
           {
            if(array_datetime[x]==line_main_open[s].time)
              {
               end_of_calc[1]=s;
               if(line_main_open[s].type==1)data_for_buffer[x].open=line_main_open[s].down;
               else data_for_buffer[x].open=line_main_open[s].up;
               break;
              }
           }
         for(int s=end_of_calc[2]; s<line_main_calc[2]; s++)
           {
            if(array_datetime[x]==line_main_high[s].time)
              {
               end_of_calc[2]=s;
               data_for_buffer[x].high=line_main_high[s].up;
               break;
              }
           }
         for(int s=end_of_calc[3]; s<line_main_calc[3]; s++)
           {
            if(array_datetime[x]==line_main_low[s].time)
              {
               end_of_calc[3]=s;
               data_for_buffer[x].low=line_main_low[s].down;
               break;
              }
           }
        }
      //--- start the function of synchronizing data
      func_synchronization(data_for_buffer,chart_synchronization,chart_priority_close,chart_priority_open,chart_priority_high,chart_priority_low);
      //--- preparatory actions before starting the function func_date_color
      ZeroMemory(time_array);
      time_variable=0;
      latch=false;
      //--- fill the buffer for drawing candles
      for(int x=ArraySize(data_for_buffer)-1,z=0; x>=0; x--)
        {
         ABCTBBuffer1[z]=data_for_buffer[x].open;
         ABCTBBuffer2[z]=data_for_buffer[x].high;
         ABCTBBuffer3[z]=data_for_buffer[x].low;
         ABCTBBuffer4[z]=data_for_buffer[x].close;
         if(ABCTBBuffer1[z]<=ABCTBBuffer4[z])ABCTBColors[z]=0;
         if(ABCTBBuffer1[z]>=ABCTBBuffer4[z])ABCTBColors[z]=1;
         if(func_date_color(data_for_buffer[x].time)==true && chart_color_period==true)ABCTBColors[z]=2;
         if(ma_draw==true)LINE_TLBBuffer[z]=func_ma(data_for_buffer[x].time);
         z++;
        }
     }
   else// construct a classic chart (based on one price type)
     {
      func_build_three_line_break(rates_array,price,step_min,line_to_back,line_main_close);// find data on selected prices
      ArrayResize(array_datetime,ArraySize(line_main_close));
      //--- preparatory actions before starting the function func_date_color
      ZeroMemory(time_array);
      time_variable=0;
      latch=false;
      //--- the buffer for drawing candles
      for(int x=ArraySize(line_main_close)-1,z=0; x>=0; x--)
        {
         ABCTBBuffer1[z]=line_main_close[x].up;
         ABCTBBuffer2[z]=line_main_close[x].up;
         ABCTBBuffer3[z]=line_main_close[x].down;
         ABCTBBuffer4[z]=line_main_close[x].down;
         if(line_main_close[x].type==1)ABCTBColors[z]=0;
         else ABCTBColors[z]=1;
         if(func_date_color(line_main_close[x].time)==true && chart_color_period==true)ABCTBColors[z]=2;
         if(ma_draw==true)LINE_TLBBuffer[z]=func_ma(line_main_close[x].time);
         z++;
        }
     }
  }

6. 連結の関数

この関数はすべての制御インディケータエレメントを統合します。まず、現データが決定され、それからデータコピーを行う関数とチャート作成関数が呼ばれます。

//+------------------------------------------------------------------+
//| Func Consolidation                                               |
//+------------------------------------------------------------------+
void func_consolidation()
  {
//--- defining the current date
   date_stop=TimeCurrent();
//--- copying data for analysis
   func_all_copy(rates_array,time_frame,first_date_start,date_stop);
//--- basic construction of the chart
   func_chart_build(chart_price,chart_type);
   ChartRedraw();
  }

7. キー制御および自動制御構造の関数

これら関数はキーボードの "R" キー(OnChartEvent)を押す、または選択された時間範囲に従ってそれを自動で行う(OnCalculate)ことでインディケータを再描画するために作成されています。王者は新規バー関数(func_new_bar)によって分析されます。それは IsNewBarで説明されている関数のシンプルバージョンです。

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   if(func_new_bar(time_redraw)==true)
     {
      func_consolidation();
     };
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- event of a keystroke
   if(id==CHARTEVENT_KEYDOWN)
     {
      if(lparam==82) //--- the key "R" has been pressed
        {
         func_consolidation();
        }
     }
  }
//+------------------------------------------------------------------+
//| Func New Bar                                                     |
//+------------------------------------------------------------------+
bool func_new_bar(ENUM_TIMEFRAMES period_time)
  {
//---
   static datetime old_times; // variable of storing old values
   bool res=false;            // variable of the analysis result
   datetime new_time[1];      // time of a new bar
//---
   int copied=CopyTime(_Symbol,period_time,0,1,new_time); // copy the time of the last bar to the cell new_time
//---
   if(copied>0) // everything is ок. data copied
     {
      if(old_times!=new_time[0]) // if the old time of the bar is not equal to the new one
        {
         if(old_times!=0) res=true; // if it is not the first start, then new bar = true
         old_times=new_time[0];     // remember the time of the bar
        }
     }
//---
   return(res);
  }

展示店ではインディケータコードの説明は終わりとし、その使用方法についてお話します。


インディケータ使用例とトレーディング戦略

古いチャート構造を基にした主要な分析戦略を始めます。

1. 買いと売りのサインとしての白と黒のライン

おおまかに2つのルールがあります。

  1. ルールNo.1:3本連続した上昇ラインがあれば買い3本連続した下降ラインがあれば売り。連続する3本ラインは傾向の出現を示します。
  2. ルールNo.2:逆転ラインが3本の連続ラインより下がったら売り、逆転ラインが3本の連続ラインより上がったら買い。

図6を見ます。これは2013年の初めから(分析の時間範囲は図5にあります)EURUSD H1 に対して古い構造を表しています。

図5 分析された時間範囲 EURUSD H1

図5 分析された時間範囲 EURUSD H1

図6 2013年初頭、EURUSD H1について終値の3つのラインブレイクチャートF

図6 2013年初頭、EURUSD H1について終値の3つのラインブレイクチャートF

チャート(図6)では、ポイント1とポイント2の間に明らかにサイン(ルールNo.1)が見られます。それは売りの開始ポイントです。この場合、収益は4桁に対して200ポイント以上です。次のポイント4は買いの有利な状況(ルールNo.2のように)を示しています。ポイント5での終了時、収益は40ポイントでポイント6の終了ととんとんです。

ポイント6では、売りのサインが見えます(ルールNo.2)。ポイント7で終了するとき10ポイントの収益得、ポイント8の終了ととんとんです。 ポイント8とポイント8は考慮に入れません。シグナルがルールNo.1もルールNo.2も満たしていないからです。ポイント10で買うことができます(ルールNo.1)。またポイント11の終了時に20ポイントの収益を得る、またはポイント12とトントンとなります。数字はすべて四捨五入されています。

最高のシナリオでは、この戦略を使うことで270ポイントの収益を上げることです。これはすばらしい数字です。同時に指定の時間範囲で収益に影響を与える激しい動きがあります。最悪の場合、トレードはとんとんの結果となりこれも悪くはありません。

状況がルールNo.1かルールNo.2を満たしている場合、傾向としての同じ方向のライン1本で表される傾向の反転確認を待つ必要があります。

2. 等距離チャンネル、サポートラインとレジスタンスライン

もう一つのトレーディング戦略は3つのラインブレイクチャートにテクニカル分析を適用することです。図7を見ます。

図7 等距離チャンネル、サポートラインとレジスタンスライン: GBPUSD H1、時間範囲2014.03.01~2014.05.01

図7 等距離チャンネル、サポートラインとレジスタンスライン: GBPUSD H1、時間範囲2014.03.01~2014.05.01

図7では下降等距離チャンネルが赤いラインで、上昇チャンネルはブルーで、サポートラインとレジスタンスラインは黒で描かれているのを確認することができます。最初のレジスタンスラインがサポートラインに変わっていることは明らかです。

3. ろうそく足パターン

2013年初頭のペア USDCAD についてタイムフレーム M30 での改善後のチャート(2つのラインブレイク)はかなりい興味深く見えます。

それらのシグナルを正当化日本式のろうそく足パターンを識別することができます(図8)。

図8 改善後の3つのラインブレイクチャートGBPUSD M30、2013年初め、2つのラインブレイク

図8 改善後の3つのラインブレイクチャートGBPUSD M30、2013年初め、2つのラインブレイク

チャートの初めでNo.1 の『巻き込み』の反転パターンが確認できます。それは2本のろうそくで構成されています。:赤とそれの前のブルーです。上昇トレンドラインの後、マーケットはNo.2に転じました。それは1本分のろうそくの反転パターン "Hammer"です。この時点でマーケットは方向を変えます。同様の事柄がパターンNo.3で起こっています("Spinning Top")。続く反転パターン "Kharami"(No.4)はろうそく4で法事され、その次に大きな下降があります。パターンNo.6 も2本のろうそく足で構成され(『巻き込み』パターン)ていますが、最初に似たモデルと異なり、それはマーケットを逆方向に向けています。

よってこの類の分析にインディケータを使用することはできますが、稀なシグナル発生や大きなドローダウンの可能性などデメリットが伴います。この戦略には一層の進展が必要なのは確かです。

4. 移動平均

ラインを描くためだけに移動平均を追加するといった部分的修正により分析に新たなチャンスが提供されます。

図9を見ましょう。

図9 移動平均分析: EURUSD H4、期間2014.01.01~2014.07.01、3つのラインブレイクチャート、古い構造

図9 移動平均分析: EURUSD H4、期間2014.01.01~2014.07.01、3つのラインブレイクチャート、古い構造

図9の上側は移動平均を伴う高い価格に基づく古い構造を表示しています(平均期間は90。低い価格、平滑化された平均)。下側は移動平均を伴う低い価格に基づく古い構造を表示しています(平均期間は90。高い価格、平滑化された平均)。

図9の上部分では移動平均はサポートラインとみなされ、下部では逆にレジスタンスラインとみなされます。両チャートの価格が平均より低ければ、マーケットには下降トレンドがあり、売る方がよいとなります。価格が平均より上がると、それは買い時です。この戦略のデメリットは長期戦略を意味することです。


おわりに

結論として、3つのラインブレイクにより一貫して良好なシグナルが提供されるか、悪くてとんとんであると言えます。実践によりこれは長期トレンドに取り入れるのがベストであることがわかり、そのため短期トレードにはお薦めしません。それをトレードで利用する方法について新しい発想のある方がいれば、ぜひお話したいと思います。

いつもどおり、コードを詳しくみようとしました。これを拡げる、再加工する、最適化する方法についてアイデアがあれば、本稿に対するコメントをお願いします。

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

添付されたファイル |
abctb.mq5 (68.78 KB)
売買ロボット物語:余計なものがない方がいい? 売買ロボット物語:余計なものがない方がいい?
2年前『最後の聖戦』でひじょうに興味深い、しかし現在広く使用されていないマーケット情報表示方法-ポイント&フィギュアチャート を再検討しました。ここで私はみなさんにポイント&フィギュアチャートで検出されるパターンに基づく売買ロボットを書いてみることを提案します。
SQL と MQL5:SQLite データベースとの連携 SQL と MQL5:SQLite データベースとの連携
本稿はご自身のプロジェクトで SQL を利用することに興味のある開発者を対象としています。ここではSQLite の機能性とメリットについて説明します。SQLite の特別な知識は必要ありませんが、SQL の最小限の知識があれば役に立つと思います。
MQL5 (MQL4)から MySQL データベースにアクセスする方法 MQL5 (MQL4)から MySQL データベースにアクセスする方法
本稿はMQL と MySQLデータベース間のインターフェース作成について説明します。また、既存の実用的ソリューションについて話し、データベースと連携するライブラリのより便利な実装方法を提供します。関数の詳細記述、インターフェースの構成、MySQLと連携する特別な機能を取り上げます。ソフトウェアソリューションについては、本稿の添付に動的ライブラリ、ドキュメンテーション、MQL4 および MQL5 言語のスクリプト例があります。
安くて楽しいニューラルネットワーク - MetaTrader 5 でNeuroPro へリンク 安くて楽しいニューラルネットワーク - MetaTrader 5 でNeuroPro へリンク
トレード用の特定のニューラルネットワークプログラムが高価で複雑そうであったら、反対にシンプル過ぎると思えたら、NeuroPro をお試しください。それは無料でアマチュア用の最適な機能セットが備えられています。本稿では MetaTrader 5 と連携してそれを利用する方法をお伝えします。