English Русский 中文 Español Deutsch Português
グラフィカルインタフェースを備えたユニバーサルチャンネル

グラフィカルインタフェースを備えたユニバーサルチャンネル

MetaTrader 5 | 10 4月 2017, 10:08
1 317 0
Dmitry Fedoseev
Dmitry Fedoseev

コンテンツ

イントロダクション

前の記事では、グラフィカルインターフェイスを使用したユニバーサルオシレーターの作成について説明しました。 その記事では、かなり簡素化し、チャートの分析を高速化する非常に便利なインジケータを作成しました。 オシレーターに加えて、他の種類のテクニカルインジケータがあり、それらはオシレーターとして興味深いものになるかもしれません。 トレンド、ボラティリティ、ボリュームだけでなく、様々なカテゴリに分けることができるインジケーターがあります。 この記事では、ユニバーサルチャネルインジケータの作成を検討します。

普遍的なオシレーターについての前の記事は非常に複雑であり、ベテランのプログラマー向けに意図されていました。 この記事のトピックはユニバーサルオシレーターの作成に近いので、ここでは一般的な問題を繰り返すことはありません。 ユニバーサルオシレーターに基づいてユニバーサルチャンネルを作成します。 したがって、初心者のプログラマも、グラフィカルインターフェイスを持つ普遍的なインジケーターの作成のすべてを理解することなく、変更を加えることによって、ユニバーサルインジケータを作成することができます。

インジケーターの類似性によらず、根本的な違いがあるでしょう。 すべてのチャネルインジケータは、上中下の3ラインとして表示されます。 移動平均インジケーターは主にチャネルに使用されますが、中央の線の描画原理は移動平均に似ています。 上下の線は中心線から等しい距離に位置します。 この距離は、標準偏差値 ( ボリンジャーバンドバンド)、またはatr値 (ケルトナーチャネル) を使用して、価格の割合 (エンベロープインジケータ) としてポイント単位で決定できます。 したがって、チャネルインジケータは、2つの独立したブロックを使用して構築されます。

  1. 中心線の計算ブロック
  2. チャンネルの幅を定義するブロック (または図面チャネルの境界線)

ドンチャン チャンネル (価格チャンネル) など、異なるタイプのチャンネルがあります。 通常、ボーダーライン (価格帯) の作成から始まり、その後、中心線の値が(その範囲の真ん中に) 計算されます。 しかし、このチャネルは、上記のスキームによって構築することができます。すなわち、最初に価格の範囲の真ん中として定義し、そして値幅の半分に等しいチャネルの境界線を描くというスキームです。 もちろん、通常のチャネルよりも多くの計算が必要になります。 しかし、この記事の主な目的は、ユニバーサルインジケータを作成することなので、このアプローチは中心線とボーダーの可能な組み合わせの数を増やし、例外を入れることができます。 例えば、ボリンジャーバンドなどのような標準偏差の境界線と、価格チャネルで使用される中心線を持つインジケーターを作成することができます。 

中心線の種類

中心線にはさまざまな移動平均が使用されます。 その型とパラメータの数を定義してみましょう。 インジケーターで使用される中心線のすべてのバリアントを表1に示します。

表 1. 中心線の種類

Standard
function
Name Parameters
iAMA アダプティブ移動平均 1. nt ama_period — ama 期間
2. nt fast_ma_period-短期移動平均期間
3. nt slow_ma_period —長期移動平均期間
4. nt ama_shift —インジケーターの水平方向のシフト
5. ENUM_APPLIED_PRICE APPLIED_PRICE-ハンドルハンドルの価格タイプ 
iDEMA 2重指数移動平均 1. nt ma_period-平均化期間
2. nt ma_shift —インジケーターの水平方向のシフト
3. ENUM_APPLIED_PRICE APPLIED_PRICE-価格タイプ
iFrAMA フラクタル適応移動平均 1. nt ma_period-平均化期間
2. nt ma_shift —インジケーターの水平方向のシフト
3. ENUM_APPLIED_PRICE APPLIED_PRICE-価格タイプ
iMA 移動平均 1. nt ma_period-平均化期間
2. nt ma_shift —インジケーターの水平方向のシフト
3. ENUM_MA_METHOD MA_METHOD-スムージングタイプ
4. ENUM_APPLIED_PRICE APPLIED_PRICE-価格タイプ
iTEMA 3重指数移動平均 1. nt ma_period-平均化期間
2. nt ma_shift —インジケーターの水平方向のシフト
3. ENUM_APPLIED_PRICE APPLIED_PRICE-価格タイプ
iVIDyA 可変インデックスの動的平均 1. nt cmo_period-シャンデリア勢いの期間
2. nt ema_period-スムージングファクター期間
3. nt ma_shift —インジケーターの水平方向のシフト
4. ENUM_APPLIED_PRICE APPLIED_PRICE-価格タイプ
- 価格チャネルの中心線 1. int period

表1の「パラメタ」欄の解析に基づき、必要最低限のパラメータセットを得ました (表 2)。

表 2. チャネルの中心線の計算のパラメータのセット 

Type Name
int period1
int period2
int period3
int shift
ENUM_MA_METHOD ma_method 
ENUM_APPLIED_PRICE  price
中心線のすべてのパラメータは、インジケータのプロパティウィンドウに "c_" プレフィックスと共に表示されます。 

ボーダーの種類

チャネルの境界計算バリアントを決定しましょう (表 3)。

表 3. チャネル幅の計算バリアント 

Standard
function
Name  Parameters
iATR トゥルーレンジの平均 1. nt ma_period-平均化期間
iStdDev  標準偏差 1. nt ma_period-平均化期間
2. nt ma_shift —インジケーターの水平方向のシフト
3. ENUM_MA_METHOD-スムージングタイプ
4. ENUM_APPLIED_PRICE APPLIED_PRICE-価格タイプ 
in points  int width—ポイントの幅 
パーセンテージ (エンベロープのライン)  double width-価格のパーセンテージとしての幅   
価格チャンネル  double width-価格チャネルの実際の幅に対する尺度の比率

表3の「パラメータ」欄に基づき、必要なパラメータセットを取得しました(表 4)。

表4. チャネル幅を計算するための普遍的なパラメータセット

Type Name
int period
int  shift 
ENUM_MA_METHOD  ma_method  
ENUM_APPLIED_PRICE  price
double  width  

ポイント単位で計算に int 変数が必要ですが、代わりに double 変数を使用できるため、表4に含まれていません。 これにより、[プロパティ] ウィンドウの変数の総数が減ります。

すべての境界線の計算パラメータは、インジケータのプロパティウィンドウに "w_" プレフィックスと共に表示されます。 

中心線のクラス

中心線の基本クラスは、基本的な原理とメソッドのセットに関して、「ユニバーサルオシレーター gui 」で説明した CUniOsc クラスに似ています。 したがって、若干変更されます。

MQL5/include フォルダで、UniChannelフォルダを作成し、 URCUniOsc.mqh ファイル (インクルード/UniOsc) からコピーして、URCUniChannel.mqh に名前を変えます。 基本クラス (COscUni) 、子クラス Calculate1 (その完全な名前は COscUni_Calculate1) とその子クラス COscUni_ATRをファイルに残します。 他のクラスを削除する必要があります。

クラスの名前を変更しましょう。: "CChannelUni" に "COscUni" フラグメントを置き換える。 置き換えるために、エディタ関数 (メインメニュー-[編集]-[検索と置換]-置換) を使用します。 しかし、"すべてを置き換える" ボタンは使用しないでください。 インスタンスを1つずつ置き換えて、すべての置換が正しいことを確認します。

中心線クラスは常に1つの実線を描画するため、基本クラスのメソッドの多くは必要ありません。 不要なメソッドを削除した後、次の基本クラスが残されます。

class CChannelUniWidth{
   protected:
      int m_handle;      // indicator handle
      string m_name;     // indicator name
      string m_label1;   // name of buffer 1      
      string m_help;     // a help on indicator parameters
      double m_width;    // channel width
   public:
  
      // constructor
      void CChannelUniWidth(){
         m_handle=INVALID_HANDLE;
      }
      
      // destructor
      void ~CChannelUniWidth(){
         if(m_handle!=INVALID_HANDLE){
            IndicatorRelease(m_handle);
         }
      }
  
      // the main method called from the OnCalculate() function of the indicator
      virtual int Calculate( const int rates_total,
                     const int prev_calculated,
                     double & bufferCentral[],
                     double & bufferUpper[],
                     double & bufferLower[],
      ){
         return(rates_total);
      }
      
      // getting the handle of the loaded indicator
      int Handle(){
         return(m_handle);
      }
      
      // handle checking method, which allows to check if the indicator has been loaded successfully  
      bool CheckHandle(){
         return(m_handle!=INVALID_HANDLE);
      }
      
      // getting the indicator name
      string Name(){
         return(m_name);
      }    
      // getting the label text for the buffers
      string Label1(){
         return(m_label1);
      }
      
      // getting the hint on parameters
      string Help(){
         return(m_help);
      }
};

2番目のバッファに関連するすべては、calculate クラスから削除できます。 その後、1つだけ計算メソッドが残されます:

class CChannelUni_Calculate1:public CChannelUni{
   public:
      // the main method called from the OnCalculate() function of the indicator
      // The first two parameters are similar to the first two parameters 
      // of the OnCalculate() function of the indicator
      // The third parameter is the indicator buffer for the central line
      int Calculate( const int rates_total,    
                     const int prev_calculated,
                     double & buffer0[]
      ){
        
         // determining the number of copied elements
        
         int cnt;
        
         if(prev_calculated==0){
            cnt=rates_total;
         }
         else{
            cnt=rates_total-prev_calculated+1;
         }  
        
         // copying data to the indicator buffer
         if(CopyBuffer(m_handle,0,0,cnt,buffer0)<=0){
            return(0);
         }
        
         return(rates_total);
      }
    };

iMAインジケータを使用して子クラスを記述します。 CChannelUni_ATR クラスを CChannelUni_MA に変更する必要があります。 呼び出されたインジケータを交換し、必要ない部品を削除してみましょう。 その結果、次のクラスを取得します。

class CChannelUni_MA:public CChannelUni_Calculate1{
   public:
   // constructor
   // the first two parameters are the same for all child classes
   // then parameters of the loaded indicator 
   void CChannelUni_MA( bool use_default,
                        bool keep_previous,
                        int & ma_period,
                        int & ma_shift,
                        long & ma_method,
                        long & ma_price){
      if(use_default){ // use of default values is selected
         if(keep_previous){
            // no modification of previously used parameters
            if(ma_period==-1)ma_period=14;
            if(ma_shift==-1)ma_shift=0;
            if(ma_method==-1)ma_method=MODE_SMA;
            if(ma_price==-1)ma_price=PRICE_CLOSE;
         }
         else{
            ma_period=14;
            ma_shift=0;
            ma_method=MODE_SMA;
            ma_price=PRICE_CLOSE;            
         }      
      }    
      
      // loading the indicator
      m_handle=iMA(Symbol(),Period(),ma_period,ma_shift,(ENUM_MA_METHOD)ma_method,(ENUM_APPLIED_PRICE)ma_price);
      
      // forming a line with the indicator name
      m_name=StringFormat( "iMA(%i,%i,%s,%s)",
                           ma_period,
                           ma_shift,        
                           EnumToString((ENUM_MA_METHOD)ma_method),              
                           EnumToString((ENUM_APPLIED_PRICE)ma_price)
                        );
      
      // String for the buffer name
      m_label1=m_name;
      // hint on parameters
      m_help=StringFormat( "ma_period - c_Period1(%i), "+
                           "ma_shift - c_Shift(%i), "+
                           "ma_method - c_Method(%s)"+
                           "ma_price - c_Price(%s)",
                           ma_period,
                           ma_shift,
                           EnumToString((ENUM_MA_METHOD)ma_method),
                           EnumToString((ENUM_APPLIED_PRICE)ma_price)
                           );
   }
    };

文字列が変数 m_name と mlabel1 で形成されるメソッドを詳しく見てみましょう。 サブウィンドウの左上隅にインジケータ名 (m_name 変数) が表示されます (サブウインドウ)。 チャンネルは価格チャートに表示されますが, その名前は表示されません。したがって、 m_label 変数に割り当てられている同じ m_name 変数に, すべてのパラメータがポップアップヘルプで表示されたときに中央のチャネル上にマウスを置くようにします。 

他のすべての標準インジケータのクラスは、iMAと同様に作成されます。 例外は、価格チャネルです。 価格チャネルは、標準のターミナルインジケータのセットに含まれていないため、計算する必要があります。 2つの方法が可能です。

  1. 計算型の子クラスの作成とその計算です。
  2. 追加のインジケーターを作成し、iCustom 関数を使用して呼び出します。
両方のオプションを均等に使用することができます。 最初のケースでは、この記事で作成されたインジケーターが依存するファイルが少なくなりますが、同じ計算を複数する必要があります。 (最初に、中心線を計算するためにチャネルの境界線を決定し、チャネルの幅を決定するためにチャネルのボーダーを再度決定します)。 2番目のケースでは、計算は繰り返されません。 加えて、独立して使用することができる完全な価格チャネルインジケータを取得します。      

下の添付ファイルには、他のすべてのインジケータと iPriceChannel インジケータの子クラスを持つ URCUniChannel.mqh があります。 iPriceChannel インジケータの中心線のデータは、バッファ0です。 必要なデータがゼロ以外のバッファに配置されている場合は、別の計算サブクラスを作成するか、基本クラスのバッファインデックスの変数を作成し、そのサブクラスのコンストラクターで目的の値を代入する必要があります。   

幅を計算し、チャネルを描画するためのクラス

再び基本クラスの基礎として CUniChannel を使用してみましょう。 中心線の値と、メソッドで計算された値で満たされるチャネルボーダーの2つのバッファのインジケーターバッファが、calculate クラスメソッドに渡されます。 CUniChannel とは対照的に、ここでは、各ボーダーの計算オプションの子クラスを別々に計算します。 サブクラスにはインジケータが読み込まれ、インジケータとバッファの名前がその中に形成されます。 また、基本クラスを若干変更する必要があります。チャネルの幅の変数を追加するため、変数の値は、子クラスのコンストラクターを通じて設定されます。

URCUniChannelWidth.mqh として URCUniChannel.mqh filde を保存し、変更してみましょう。 まず、すべての子クラスを削除し、基本クラスのみを残して計算します。 CChannelUni の名前を CChannelUniWidth に変更 (コンストラクター、デストラクター、および子クラスの親名を忘れないでください)する必要もあります。 結果のファイルは次のとおりです。

class CChannelUniWidth{
   protected:
      int m_handle;           // indicator handle
      string m_name;          // indicator name
      string m_label1;        // name of buffer 1      
      string m_help;          // a hint on indicator parameters
      double m_width;         // channel width
   public:
  
      // constructor
      void CChannelUniWidth(){
         m_handle=INVALID_HANDLE;
      }
      
      // destructor
      void ~CChannelUniWidth(){
         if(m_handle!=INVALID_HANDLE){
            IndicatorRelease(m_handle);
         }
      }
  
      // the main method called from the OnCalculate() function of the indicator
      virtual int Calculate( const int rates_total,
                     const int prev_calculated,
                     double & bufferCentral[],
                     double & bufferUpper[],
                     double & bufferLower[],
      ){
         return(rates_total);
      }
      
      // getting the handle of the loaded indicator
      int Handle(){
         return(m_handle);
      }
      
      // handle checking method, which allows to check if the indicator has been loaded successfully  
      bool CheckHandle(){
         return(m_handle!=INVALID_HANDLE);
      }
      
      // getting the indicator name
      string Name(){
         return(m_name);
      }    
      // getting the label text for the buffers
      string Label1(){
         return(m_label1);
      }
      
      // getting the hint on parameters
      string Help(){
         return(m_help);
      }
};
  

CChannelUni_Calculate クラスの名前を CChannelUni_Calculate_ATR に変更し、コンストラクタを追加してみましょう。 コンストラクタは、ユニバーサルオシレーターの COscUni_ATR クラスから取得できますが、 幅パラメータを変更する必要があります。 他に何を変更する必要があるでしょうか。インジケータとバッファの名前の生成を追加する必要があります。 そして最後に、ATR に基づいてボーダーを計算します。

class CChannelUni_Calculate_ATR:public CChannelUniWidth{
   public:
      // constructor
      // the first two parameters are standard for all child classes 
      // followed by parameters of the loaded indicator
      // the last parameter is the channel width
      void CChannelUni_Calculate_ATR(bool use_default,
                                     bool keep_previous,
                                     int & ma_period,
                                     double & ch_width){
         if(use_default){ // use of default values is selected
            if(keep_previous){ // no modification of previously used parameters
               if(ma_period==-1)ma_period=14;
               if(ch_width==-1)ch_width=2;
            }
            else{
               ma_period=14;
               ch_width=2;
            }      
         } 
         
         // saving width parameters for use in the calculation metho  
         m_width=ch_width; 
         // loading the indicator
         m_handle=iATR(Symbol(),Period(),ma_period);
         // forming a line with the indicator name
         m_name=StringFormat("ATR(%i)",ma_period);
         // string with the names of the buffers
         m_label1=m_name;
         // hint on parameters 
         m_help=StringFormat("ma_period - Period1(%i)",ma_period); // a hint   
      }   
      
      // the main method called from the OnCalculate() function of the indicator
      // the first two parameters are similar to the first two parameters
      // of OnCalculate() function
      // then indicator buffers are passed 
      int Calculate( const int rates_total,
                     const int prev_calculated,
                     double & bufferCentral[],
                     double & bufferUpper[],
                     double & bufferLower[],
      ){
      
         // defining the beginning of calculation
         
         int start;
         
         if(prev_calculated==0){
            start=0; 
         }
         else{ 
            start=prev_calculated-1;
         }  
         // the main loop of calculation and buffer filling 
         for(int i=start;i<rates_total;i++){
            
            // getting indicator data for the calculated bar
            double tmp[1];
            if(CopyBuffer(m_handle,0,rates_total-i-1,1,tmp)<=0){
               return(0);
            }
            
            // multiplying by the width parameter
            tmp[0]*=m_width;   
            // calculating the values of the upper and lower borders
            bufferUpper[i]=bufferCentral[i]+tmp[0];
            bufferLower[i]=bufferCentral[i]-tmp[0];
         }   
         
         return(rates_total);
      }
        };

1つの足のATRインジケータの値は、メインループ内にコピーされることに注意してください、 このバリアントは、系列をバッファにコピーするよりもはるかに低速です。 しかし、このアプローチでは、1つのインジケーターバッファを保存しますが、チャートにインジケータを裁量でアタッチするときにのみ表示されます。 しかし、2番目の遅延は、ユーザーにとって不可欠ではありません。 ストラテジーテスタでは、テストの開始時にチャート上のわずかな足が利用可能であるため、各足のデータをコピーしても時間が失われることはありません。

チャネル幅の計算に、幅がポイントまたはエンベロープチャネルで設定されている場合などは、追加のインジケータは必要ありません。 この場合、基本クラスの m_handle 変数に0を代入します (INVALID_HANDLE 値とは異なります)。

下の添付ファイルに、他のチャネル計算オプションの子クラスを持つ URCUniChannelWidth.mqh があります。   

ユニバーサルチャネルインジケータの作成

上記のクラスを用意したので、ユニバーサルチャネルインジケータを作成することもできますが、グラフィカルインターフェイスはまだありません。

エディタで新しい iUniChannel カスタムインジケータを作成しましょう。 MQL5 ウィザードでインジケーターを作成するときは、次の関数を選択します。 OnCalculate (...,始値、高値、安値、終値), OnTimer, OnChartEvent, ラインタイプの3つのバッファを作成します。

中心線とチャネルの種類を選択するには、2つの列挙型を作成する必要があります。 列挙体は URUniChannelDefines.mqh ファイルに配置されます。 表1および3に従って列挙を作成します:

// enumeration of central line types
enum ECType{
   UniCh_C_AMA,
   UniCh_C_DEMA,
   UniCh_C_FrAMA,
   UniCh_C_MA,
   UniCh_C_TEMA,
   UniCh_C_VIDyA,
   UniCh_C_PrCh
};
// enumeration of border types
enum EWType{
   UniCh_W_ATR,
   UniCh_W_StdDev,
   UniCh_W_Points,
   UniCh_W_Percents,
   UniCh_W_PrCh
            };

中心線の種類の列挙体は ECType と呼ばれ、チャネル幅の種類の列挙は EWType です。 列挙体と、以前に作成された2つのファイルとクラスを持つファイルをインジケーターに接続します。

#include <UniChannel/UniChannelDefines.mqh>
#include <UniChannel/CUniChannel.mqh>
#include <UniChannel/CUniChannelWidth.mqh>
    

次に、2つの外部変数を宣言して、中心線の種類とチャネル幅を選択し、表2および表4に従ってパラメータの変数を指定します。

// central line parameters
input ECType               CentralType   =  UniCh_C_MA;
input int                  c_Period1     =  5;
input int                  c_Period2     =  10;
input int                  c_Period3     =  15;
input int                  c_Shift       =  0;
input ENUM_MA_METHOD       c_Method      =  MODE_SMA;
input ENUM_APPLIED_PRICE   c_Price       =  PRICE_CLOSE;
// border parameters
input EWType               WidthType     =  UniCh_W_StdDev;
input int                  w_Period      =  20;
input int                  w_Shift       =  0;
input ENUM_MA_METHOD       w_Method      =  MODE_SMA;
input ENUM_APPLIED_PRICE   w_Price       =  PRICE_CLOSE;
      input double               w_Width       =  2.0;

2つの変数を宣言し、後で GUI を使用してインジケータのプロパティウィンドウに表示されます:

bool                 UseDefault  =  false;
      bool                 KeepPrev    =  false;

変数の目的は、ユニバーサルオシレーターについての記事で詳しく説明されています。UseDefault 変数は、新しく選択された各インジケータがデフォルト設定で読み込まれるモードを有効にし、KeepPrev 変数がインジケータを切り替えるときにパラメータを保存するモードを有効にします。 GUIを使用しないインジケーターバージョンでは、インジケータは [プロパティ] ウィンドウのパラメータで読み込まれ、UseDefault 値は false になります。 KeepPrev も false に設定されているため、インジケータスイッチはありません。 

インジケーターの初期化中にパラメータを準備する必要があります。 ユニバーサルオシレーターのように、別の関数 PrepareParameters () でパラメータを準備しますが、最初にすべての外部変数のコピーを作成します:

ECType               _CentralType;
int                  _ma_Period1;
int                  _ma_Period2;
int                  _ma_Period3;
int                  _ma_Shift;
long                 _ma_Method;
long                 _ma_Price;
EWType               _WidthType;
int                  _w_Period;
int                  _w_Shift;
long                 _w_Method;
long                 _w_Price;
      double               _w_Width;

次に、パラメータの準備関数を記述します。

void PrepareParameters(){
   _CentralType=CentralType;
   _WidthType=WidthType;
  
   if(UseDefault && KeepPrev){
      _c_Period1=-1;
      _c_Period2=-1;
      _c_Period3=-1;
      _c_Shift=0;
      _c_Method=-1;
      _c_Price=-1;
      _w_Period=-1;
      _w_Shift=0;
      _w_Method=-1;
      _w_Price=-1;
      _w_Width=-1;
   }
   else{  
      _c_Period1=c_Period1;
      _c_Period2=c_Period2;
      _c_Period3=c_Period3;
      _c_Shift=c_Shift;
      _c_Method=c_Method;
      _c_Price=c_Price;
      _w_Period=w_Period;
      _w_Shift=w_Shift;
      _w_Method=w_Method;
      _w_Price=w_Price;
      _w_Width=w_Width;
   }
            }

UseDefault & & KeepPrev 条件が満たされると、すべての変数が-1 に設定され、ユーザーインターフェイス (インジケータのプロパティウィンドウまたは gui) から設定されるので、shift 変数に0が割り当てられます。   

パラメータを準備した後、中心線とチャネルを計算するオブジェクトを作成できます。 ユニバーサルオシレーターでは、LoadOscillator () 関数をその目的で使用します。 ここでは、LoadCentral () と LoadWidth () の2つの関数がありますが、最初にポインタを宣言する必要があります。

CChannelUni * central;
            CChannelUniWidth * width;

すべてのインジケータがシフトすることは共通ですが、水平方向のシフトのパラメータを持つものともたないものがあります。 したがって、付加的な変数 shift0 を0の値で宣言し、クラスコンストラクタで渡します。 このシフトは、インジケーターバッファをシフトすることによって描画されます。

LoadCentral () 関数:

void LoadCentral(){
   switch(_CentralType){ // an appropriate class is created depending on the selected type
      case UniCh_C_AMA:
         central=new CChannelUni_AMA(  UseDefault,
                                       KeepPrev,
                                       _c_Period1,
                                       _c_Period2,
                                       _c_Period3,
                                       shift0,
                                       _c_Price);
      break;
      case UniCh_C_DEMA:
         central=new CChannelUni_DEMA( UseDefault,
                                       KeepPrev,
                                       _c_Period1,
                                       shift0,
                                       _c_Price);
      break;
      case UniCh_C_FrAMA:
         central=new CChannelUni_FrAMA(UseDefault,
                                       KeepPrev,
                                       _c_Period1,
                                       shift0,
                                       _c_Price);
      break;
      case UniCh_C_MA:
         central=new CChannelUni_MA(   UseDefault,
                                       KeepPrev,
                                       _c_Period1,
                                       shift0,
                                       _c_Method,
                                       _c_Price);
      break;
      case UniCh_C_TEMA:
         central=new CChannelUni_TEMA( UseDefault,
                                       KeepPrev,
                                       _c_Period1,
                                       shift0,
                                       _c_Price);
      break;
      case UniCh_C_VIDyA:
         central=new CChannelUni_VIDyA(UseDefault,
                                       KeepPrev,
                                       _c_Period1,
                                       _c_Period2,
                                       shift0,
                                       _c_Price);
      break;
      case UniCh_C_PrCh:
         central=new CChannelUni_PriceChannel(  UseDefault,
                                                KeepPrev,
                                                _c_Period1);
      break;
   }
}
    

チャネル幅の計算オプション (CChannelUni_Calculate_InPoints クラス) の1つがポイントで測定されたパラメータを含み、クラスはシンボルクオートの小数点以下の桁数に従ってパラメータ値を調整します。 関数を操作するには、オブジェクトを作成するときに、パラメータをクラスコンストラクタに渡す必要があります。 2桁4 桁のクオートでは、乗数は1に等しくなり、3桁5桁のクオートでは10になります。 外部パラメータで、bool 型の Auto5Digits 変数を宣言します。

input bool                 Auto5Digits   =  true;

Auto5Digits が true の場合、false-値がそのまま使用される場合には修正されます。 Auto5Digits の下で、変数をもう1つ宣言します。

int mult;

OnInit () 関数の冒頭で、mult の値を計算します。

   if(Auto5Digits && (Digits()==3 || Digits()==5)){
      mult=10; // parameters in points will be multiplied by 10
   }
   else{
      mult=1; // parameters in points will not be corrected
         }

LoadWidth () 関数:

void LoadWidth(){
   switch(_WidthType){ // an appropriate class is created depending on the selected type
      case UniCh_W_ATR:
         width=new CChannelUni_Calculate_ATR(UseDefault,KeepPrev,_w_Period,_w_Width);
      break;
      case UniCh_W_StdDev:
         width=new CChannelUni_Calculate_StdDev(UseDefault,KeepPrev,_w_Period,shift0,_w_Method,_w_Price,_w_Width);
      break;
      case UniCh_W_Points:
         width=new CChannelUni_Calculate_InPoints(UseDefault,KeepPrev,_w_Width,mult);
      break;
      case UniCh_W_Percents:
         width=new CChannelUni_Calculate_Envelopes(UseDefault,KeepPrev,_w_Width);
      break;
      case UniCh_W_PrCh:
         width=new CChannelUni_Calculate_PriceChannel(UseDefault,KeepPrev,_w_Period,_w_Width);
      break;
   }
            }

各オブジェクト (中心線と幅) を作成した後、正常に作成されたかどうかを確認する必要があります。 オブジェクトが作成された場合は、インジケータのショートネームを設定し、print () 関数を使用してパラメータのヘルプ情報を表示します。 

Print("Central line parameters matching:",central.Help());
      Print("Width parameters matching:",width.Help());  

バッファのラベルとシフトは、setstyles () 関数を使用して設定されます。

void SetStyles(){
   // buffer names
   PlotIndexSetString(0,PLOT_LABEL,"Central: "+central.Label1());
   PlotIndexSetString(1,PLOT_LABEL,"Upper: "+width.Label1());  
   PlotIndexSetString(2,PLOT_LABEL,"Lower: "+width.Label1());  
  
   // shift of buffers
   PlotIndexSetInteger(0,PLOT_SHIFT,_c_Shift);
   PlotIndexSetInteger(1,PLOT_SHIFT,_w_Shift);
   PlotIndexSetInteger(2,PLOT_SHIFT,_w_Shift);
            }

その結果、次の OnInit () 関数を取得します。

int OnInit(){
  
   // preparing a multiplier to adjust the parameter in points
   if(Auto5Digits && (Digits()==3 || Digits()==5)){
      mult=10;
   }
   else{
      mult=1;
   }
  
   // preparing parameters
   PrepareParameters();
  
   // loading the central line indicator
   LoadCentral();
  
   // checking if the central line has been loaded successfully 
   if(!central.CheckHandle()){
      Alert("Central line error "+central.Name());
      return(INIT_FAILED);
   }    
  
   // loading the width calculating indicator
   LoadWidth();
  
   // checking if the width calculating indicator has been loaded successfully
   if(!width.CheckHandle()){
      Alert("Width error "+width.Name());
      return(INIT_FAILED);
   }      
   // showing hint on parameters
   Print("Central line parameters matching: "+central.Help());
   Print("Width parameters matching: "+width.Help());  
  
   // setting the name
   ShortName="iUniChannel";  
   IndicatorSetString(INDICATOR_SHORTNAME,ShortName);  
  
   // a standard part of the OnInit function
   SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,Label2Buffer,INDICATOR_DATA);
   SetIndexBuffer(2,Label3Buffer,INDICATOR_DATA);
  
   // setting labels and buffer shift
   SetStyles();
   return(INIT_SUCCEEDED);
            }

この時点で、グラフィカルインターフェイスを持たないインジケーターが完了すると想定できます。 すべてのクラスとパラメータの操作をテストすることができ、その後、グラフィカルインターフェイスの作成に進むことができます。

テスト中、インジケータの操作で不便な点がありました。 1つは、中心線の期間と幅の計算期間を別々に管理しなければならないことです。 もちろん、このような管理は、インジケーターの可能性を広げることができますが、1つのパラメータを使用して2つの期間の同時制御が必要になる場合もあります。 中心線の3つの期間のいずれかに等しいチャネルの幅の期間を作るためにマイナーチェンジしてみましょう。 4つのオプションのうち1つが(URUniChannelDefines.mqh ファイルにある) 選択されます。

enum ELockTo{
   LockTo_Off,
   LockTo_Period1,
   LockTo_Period2,
   LockTo_Period3
            };

LockTo_Off オプションを選択すると、期間は別々に調整されます。 その他の場合、w_Period パラメータの値は、中心線に対応する期間と等しくなります。 w_Period 変数の直後に ELockTo 型の変数を宣言してみましょう:

input ELockTo              w_LockPeriod  =  LockTo_Off;

PrepareParameters () 関数の下部に次のコードを追加します。

switch(w_LockPeriod){ // depending on the lock type
   case LockTo_Period1:
      _w_Period=_c_Period1;
   break;
   case LockTo_Period2:
      _w_Period=_c_Period2;      
   break;
   case LockTo_Period3:
      _w_Period=_c_Period3;      
   break;
            }

もう一つの欠点は、パラメータに関するメッセージが「エキスパート」タブに表示され、その一部が表示されないということです。 情報を表示するようにコードを変更してみましょう。 Printではなく、独自の PrintColl () 関数を使用します。 2つのパラメータがこの関数に渡されます: キャプションとヘルプ文字列。 この関数では、ヘルプ文字列は別々にPrintされる部分に分割されます。

void PrintColl(string caption,string message){
   Print(caption); // print the caption
   string res[];
   // splitting the message
   int cnt=StringSplit(message,',',res);
   // printing the message in parts
   for(int i=0;i<cnt;i++){
      StringTrimLeft(res[i]);
      Print(res[i]);
   }
            }

したがって、2つのヘルプPrintラインはOnInit () 関数で変更されます。

PrintColl("Central line parameters matching:",central.Help());
            PrintColl("Width parameters matching:",width.Help());    

インジケータの準備が整いました。添付ファイルの名前は "iUniChanhel" です。 今度はグラフィカルインターフェイスを作成しましょう。   

グラフィカルインターフェイスクラスの作成

グラフィカルインタフェースは、ユニバーサルオシレーターのグラフィカルインタフェースに基づきます。 URUniOsc/UniOscGUI.mqh を UniChannel フォルダにコピーし、その名前を URUniChannelGUI.mqh に変更します。 ユニバーサルチャネルのグラフィカルインターフェイスは、ユニバーサルオシレーターのインターフェイスとは異なりますので、ここでは多くのタスクを行う必要があります。

主な違いは、ユニバーサルチャネルの2つのインジケーター (中心線とボーダー) の選択を必要とするので、2つの主要なインジケータの選択リストが必要です。 最初のリストには、中心線のパラメータを管理するためのコントロールが続きます。 次に、2番目のリストとボーダー線パラメータのコントロールが付属します。 したがって、2番目のリストには固定座標がないため、計算する必要があります。 2種類の選択リストに加えて、常にオフセット値の2つのエントリーフィールドを持つ必要があります。 フィールドの座標も固定されていません。 もう1つの重要な点は、w_LockPeriod パラメータに対応する変数を選択するためのリストです。 幅コントロールのグループに w_Period パラメータエントリーフィールドを表示する場合は、その他のドロップダウンリストを表示する必要があります。

まず、URUniChannelGUI.mqh ファイルの全般的な変更をラインいます。

1. 列挙型のファイルへのパス:

# include <uniosc/unioscdefines.mqh>

次のように置き換える必要があります。

# include <unichannel/unichanneldefines.mqh>

2. ELockTo 列挙値を持つ配列を追加。

ELockTo e_lockto[]={LockTo_Off,LockTo_Period1,LockTo_Period2,LockTo_Period3};
  

3. ENUM_APPLIED_VOLUME と ENUM_STO_PRICE の列挙体を使用して配列を削除。

CUniOscControls クラスの変更に進みます。  

中心線コントロールのクラス

1. CUniOscControls クラスを CUniChannelCentralControls に再命名。

2. 変数 m_volume と m_sto_price の宣言は、クラスから削除する必要があります。 したがって、コントロールに関連付けられているすべての SetPointers ()、hide ()、およびイベント () メソッドを削除します。

3. グループからの最後のコントロールの y 座標が記録される m_last_y 変数を追加します。 この変数の値を受け取るメソッドを追加します (GetLastY)。 FormHeight () メソッドを必要としないので、削除しましょう。 代わりに、子クラスのコントロールの数を返す ControlsCount () メソッドを追加する必要があります。 この数値は、フォームの高さを計算するために使用されます。

次に、親クラスを示します。

class CUniChannelCentralControls{
   protected:
      CSpinInputBox * m_value1; // for period 1
      CSpinInputBox * m_value2; // for period 2
      CSpinInputBox * m_value3; // for period 3
      CComBox * m_price;        // for the price
      CComBox * m_method;       // for the method
      int m_last_y;             // the Y coordinate of the last control
   public:
  
   // getting the Y coordinate of the last control
   int GetLastY(){
      return(m_last_y);
   }
  
   // method for passing object pointers to the object
   void SetPointers(CSpinInputBox & value1,
                        CSpinInputBox & value2,      
                        CSpinInputBox & value3,
                        CComBox & price,
                        CComBox & method){
      m_value1=GetPointer(value1);
      m_value2=GetPointer(value2);      
      m_value3=GetPointer(value3);            
      m_price=GetPointer(price);
      m_method=GetPointer(method);
   }
  
   // hiding the group of controls
   void Hide(){
      m_value1.Hide();
      m_value2.Hide();
      m_value3.Hide();
      m_price.Hide();
      m_method.Hide();
   }
  
   // event handling
   int Event(int id,long lparam,double dparam,string sparam){
      int e1=m_value1.Event(id,lparam,dparam,sparam);
      int e2=m_value2.Event(id,lparam,dparam,sparam);
      int e3=m_value3.Event(id,lparam,dparam,sparam);
      int e4=m_price.Event(id,lparam,dparam,sparam);
      int e5=m_method.Event(id,lparam,dparam,sparam);
      if(e1!=0 || e2!=0 || e3!=0 || e4!=0 || e5!=0){
         return(1);
      }
      return(0);
   }
  
   // methods for the initialization of controls (to change labels) 
   virtual void InitControls(){
   }  
  
   // displaying the group of controls
   virtual void Show(int x,int y){
   }  
  
   // getting the number of controls in the group
   virtual int ControlsCount(){
      return(0);
   }      
        };

CUniOscControls_ATR クラスを変更してみましょう:

1. CUniChannelCentralControls_AMA に名前を変更し, AMAインジケータのクラスになります.

2. 表1の「パラメータ」列に従って、InitControls () メソッド内のすべてのコントロールを初期化し、show () メソッドですべてのコントロールの show () メソッドを呼び出します。 最後のコントロールの値を m_last_y 変数に代入する必要があります。

3. 今度は FormHeight () メソッドを削除し、代わりに ControlsCount () を追加します。

結果のクラスです:

class CUniChannelCentralControls_AMA:public CUniChannelCentralControls{
   void InitControls(){
      // initialization of controls
      m_value1.Init("c_value1",SPIN_BOX_WIDTH,1," ama_period");
      m_value2.Init("c_value2",SPIN_BOX_WIDTH,1," fast_ma_period");      
      m_value3.Init("c_value3",SPIN_BOX_WIDTH,1," slow_ma_period");      
   }
  
   // display 
   void Show(int x,int y){
      m_value1.Show(x,y);
      y+=20;
      m_value2.Show(x,y);
      y+=20;
      m_value3.Show(x,y);
      y+=20;
      m_price.Show(x,y);
      m_last_y=y;
   }
  
   // getting the number of controls in the group
   int ControlsCount(){
      return(4);
   }
        };

同様に、中心線に使用されるインジケーターの残りのクラスを作成し、不要なオシレータの子クラスをすべて削除します。

幅計算コントロールのクラス

CUniChannelCentralControls クラスに基づき、チャネル幅パラメータを管理するためのクラスを作成します。 CUniChannelCentralControls クラスのコピーを作成し、その名前を CUniChannelWidthControls に変更します。 このクラスでは、2つのエントリーフィールド (ピリオドと幅)、平均型と価格の2つの標準列挙、および w_LockPeriod パラメータ列挙が必要です。 その結果、次のクラスを取得します。

class CUniChannelWidthControls{
   protected:
      CSpinInputBox * m_value1; // for the period
      CSpinInputBox * m_value2; // for the width
      CComBox * m_price;        // for the price
      CComBox * m_method;       // for the method
      CComBox * m_lockto;       // for the lock type
      int m_last_y;             // the Y coordinate of the last control 
   public:
  
   // getting the Y coordinate of the last control
   int GetLastY(){
      return(m_last_y);
   }
  
   // method for passing object pointers to the object
   void SetPointers(CSpinInputBox & value1,
                        CSpinInputBox & value2,      
                        CComBox & price,
                        CComBox & method,
                        CComBox & lockto){
      m_value1=GetPointer(value1);
      m_value2=GetPointer(value2);      
      m_price=GetPointer(price);
      m_method=GetPointer(method);
      m_lockto=GetPointer(lockto);      
   }
  
   // hiding the group of controls
   void Hide(){
      m_value1.Hide();
      m_value2.Hide();
      m_price.Hide();
      m_method.Hide();
   }
  
   // event handling
   int Event(int id,long lparam,double dparam,string sparam){
      int e1=m_value1.Event(id,lparam,dparam,sparam);
      int e2=m_value2.Event(id,lparam,dparam,sparam);
      int e4=m_price.Event(id,lparam,dparam,sparam);
      int e5=m_method.Event(id,lparam,dparam,sparam);
      int e6=m_lockto.Event(id,lparam,dparam,sparam);      
      if(e1!=0 || e2!=0 || e4!=0 || e5!=0 || e6){
         return(1);
      }
      return(0);
   }
  
   // methods for the initialization of controls (to change labels) 
   virtual void InitControls(){
   }  
  
   // displaying the group of controls
   virtual void Show(int x,int y){
   }  
  
   // getting the number of controls in the group
   virtual int ControlsCount(){
      return(0);
   }    
        };

子クラスを作成してみましょう。 中心線クラスの主な相違点は、ピリオドエントリーフィールドの後に w_LockPeriod パラメータのドロップダウンリストを作成する必要があることです。 ATRを使用して幅の計算をします。

class CUniChannelWidthControls_ATR:public CUniChannelWidthControls{
   void InitControls(){
      // Control initialization
      m_value1.Init("w_value1",SPIN_BOX_WIDTH,1," period");
   }
  
   // Displaying the group of controls
   void Show(int x,int y){
      m_value1.Show(x,y);
      y+=20;
      m_lockto.Show(x,y);
      m_last_y=y;
   }  
  
   // Getting the number of controls in the group
   int ControlsCount(){
      return(2);
   }    
        };

チャネル幅の計算の他のすべてのバリアントのクラスは、上記のいずれかに似ています。 

URUniChannelGUI.mqh ファイルには、コントロールの2つの基本的なクラス、その子クラスとフォームクラスがあります。 後者は調整する必要があります。 サイズが大きく、ファイルの操作が不便な場合があるため、他のファイルのコントロールのクラスを準備します。 URUniChannel/CUniChannelCentralControls.mqh ファイルを作成し、CUniChannelCentralControls クラスとそのすべての子クラスをこのファイルに移動します。 また、追加のファイルを含めます。: 

# include< URIncGUI_v4.mqh >
    # include <unichannel/unichanneldefines.mqh>

FORM_WIDTH、SPIN_BOX_WIDTH、COMBO_BOX_WIDTH は、URUniChannelDefines.mqh ファイルに移動されます。 その後、CUniChannelCentralControls ファイルは、エラーをチェックするためにコンパイルすることができます。 CUniChannelWidthControls クラスも別のファイルに移動する必要があります。 その後、フォームクラスを使用すると、より便利になります。 

フォームクラス

URUniChannelGUI.mqh に新しく作成された2つのファイルを含めます。

# include <unichannel/cunichannelcentralcontrols.mqh>
    # include <unichannel/cunichannelwidthcontrols.mqh>

CUniOscForm を CUniChannelForm に再名前を付けます。 パブリックセクションでは、CUniOscControls 型ポインターを削除します。 代わりに、CUniChannelCentralControls と CUniChannelWidthControls の2つのポインター変数を宣言し、form クラスの他のコントロールを決定します。 次の変数は、パブリックセクションに配置されます。

CComBox           m_c_cmb_main;  // central line selection list
CSpinInputBox     m_c_value1;    // input field for period 1
CSpinInputBox     m_c_value2;    // input field for period 2
CSpinInputBox     m_c_value3;    // input field for period 3
CComBox           m_c_price;     // price selection list
CComBox           m_c_method;    // method selection list
CSpinInputBox     m_c_shift;     // shift input fields
CComBox           m_w_cmb_main;  // border selection list
CSpinInputBox     m_w_value1;    // period input field
CSpinInputBox     m_w_value2;    // width input field
CComBox           m_w_price;     // price selection field
CComBox           m_w_method;    // method selection field
CComBox           m_w_lockto;    // lock option selection field     
CSpinInputBox     m_w_shift;     // shift input field          
// the group of central line controls
CUniChannelCentralControls * m_central_controls;
// the group of border controls
        CUniChannelWidthControls * m_width_controls;  

MainProperties () メソッドでは、m_Name と m_Caption の変数の値を変更し、他のすべての変数は変わらないままです。

void MainProperties(){
      m_Name         =  "UniChannelForm";
      m_Width        =  FORM_WIDTH;
      m_Height       =  150;
      m_Type         =  0;
      m_Caption      =  "UniChannel";
      m_Movable      =  true;
      m_Resizable    =  true;
      m_CloseButton  =  true;
        }

OnInitEvent () メソッドでは、不変のラベルを持つすべてのコントロール (選択したインジケーターに対応するコントロールのセット) の init () メソッドを呼び出し、ドロップダウンリストにします。

void OnInitEvent(){
   // initialization of controls that are not included into the group
  
   m_c_cmb_main.Init("cb_c_main",COMBO_BOX_WIDTH," select central");
   m_w_cmb_main.Init("cb_w_main",COMBO_BOX_WIDTH," select bands");
   m_c_price.Init("c_price",COMBO_BOX_WIDTH," price");
   m_c_method.Init("c_method",COMBO_BOX_WIDTH," method");
   m_c_shift.Init("c_shift",COMBO_BOX_WIDTH,1," shift");    
  
   m_w_price.Init("w_price",COMBO_BOX_WIDTH," price");
   m_w_method.Init("w_method",COMBO_BOX_WIDTH," method");
   m_w_shift.Init("w_shift",COMBO_BOX_WIDTH,1," shift");    
  
   m_w_lockto.Init("cb_w_lockto",COMBO_BOX_WIDTH," lock period");
   m_w_value2.Init("w_value2",SPIN_BOX_WIDTH,0.001," width");
  
   // filling the drop-down lists
  
   for(int i=0;i<ArraySize(e_price);i++){
      m_c_price.AddItem(EnumToString(e_price[i]));
      m_w_price.AddItem(EnumToString(e_price[i]));
   }
   for(int i=0;i<ArraySize(e_method);i++){
      m_c_method.AddItem(EnumToString(e_method[i]));
      m_w_method.AddItem(EnumToString(e_method[i]));
   }            
   for(int i=0;i<ArraySize(e_lockto);i++){
      m_w_lockto.AddItem(EnumToString(e_lockto[i]));            
   }
  
   // allow typing the shift value using keyboard            
   m_c_shift.SetReadOnly(false);
   m_w_shift.SetReadOnly(false);                        
        }  

OnShowEvent () メソッドでは、コントロールを表示します。 グループの表示後、Y座標を取得し、次のコントロールをこの座標に従って表示します。

void OnShowEvent(int aLeft, int aTop){
   m_c_cmb_main.Show(aLeft+10,aTop+10);        // central line type selection list
   m_central_controls.Show(aLeft+10,aTop+30);  // a group of central line parameters controls
   int m_y=m_central_controls.GetLastY();      // getting the coordinate of the last control
   m_c_shift.Show(aLeft+10,m_y+20);            // the shift parameter input field
   m_w_cmb_main.Show(aLeft+10,m_y+40);         // the channel selection list
   m_width_controls.Show(aLeft+10,m_y+60);     // a group of channel parameters controls
   m_y=m_width_controls.GetLastY();            // getting the coordinate of the last control
   m_w_value2.Show(aLeft+10,m_y+20);           // the width input field
   m_w_shift.Show(aLeft+10,m_y+40);            // the shift parameter input field
        }

コントロールは、OnHideEvent () メソッドで非表示にすることができます。

void OnHideEvent(){
   m_c_cmb_main.Hide();       // central line type selection list     
   m_central_controls.Hide(); // a group of central line parameters controls
   m_c_shift.Hide();          // the shift parameter input field
   m_w_cmb_main.Hide();       // channel selection field
   m_width_controls.Hide();   // a group of channel parameters controls
   m_w_shift.Hide();          // the shift parameter input field
   m_w_lockto.Hide();         // period lock type selection
   m_width_controls.Hide();   // width input field
    }

SetValues () メソッドで変更します。 メソッドパラメータのセットを変更すると、パラメータに対応する値をメソッド内のすべてのコントロールに設定します。

void SetValues(int c_value1,
               int c_value2,
               int c_value3,
               long c_method,
               long c_price,
               long c_shift,                    
               int w_value1,
               int w_value2,
               long w_method,
               long w_price,
               long w_lockto,
               long w_shift  
){
   // central line input field
   m_c_value1.SetValue(c_value1);
   m_c_value2.SetValue(c_value2);      
   m_c_value3.SetValue(c_value3);
   m_c_shift.SetValue(c_shift);        
   // channel parameters input fields
   m_w_value1.SetValue(w_value1);
   m_w_value2.SetValue(w_value2);        
   m_w_shift.SetValue(w_shift);            
  
   // display of selected types in the smoothing method selection lists
   for(int i=0;i<ArraySize(e_method);i++){
      if(c_method==e_method[i]){
         m_c_method.SetSelectedIndex(i);
      }
      if(w_method==e_method[i]){
         m_w_method.SetSelectedIndex(i);
      }            
   }
  
   // display of selected types in the price type selection lists
   for(int i=0;i<ArraySize(e_price);i++){
      if(c_price==e_price[i]){
         m_c_price.SetSelectedIndex(i);
      }
      if(w_price==e_price[i]){
         m_w_price.SetSelectedIndex(i);
      }            
   }
   // display of the selected type of channel period lock
   for(int i=0;i<ArraySize(e_lockto);i++){
      if(w_lockto==e_lockto[i]){
         m_w_lockto.SetSelectedIndex(i);
         break;
      }
   }                    
        }  

settype () の代わりに、中心線の種類を設定するための SetCentralType () と、ボーダーの種類を設定するための SetWidthType () の2つのメソッドを作成します。 各メソッドの最後に、オブジェクトが作成されると、プロパティはコントロールに設定され、キーボードを使用して値をエントリーできます。 また、最小許容値を設定し、フォームの高さの計算のプライベートメソッドを呼び出します。  

Метод SetCentralType():

void SetCentralType(long type){
   // If an object has already been created, we need to delete it
   if(CheckPointer(m_central_controls)==POINTER_DYNAMIC){
      delete(m_central_controls);
      m_central_controls=NULL;
   }
   switch((ECType)type){ // create an object depending on the selected class
      case UniCh_C_AMA:
         m_central_controls=new CUniChannelCentralControls_AMA();
      break;
      case UniCh_C_DEMA:
         m_central_controls=new CUniChannelCentralControls_DEMA();            
      break;
      case UniCh_C_FrAMA:
         m_central_controls=new CUniChannelCentralControls_FrAMA();            
      break;
      case UniCh_C_MA:
         m_central_controls=new CUniChannelCentralControls_MA();            
      break;
      case UniCh_C_TEMA:
         m_central_controls=new CUniChannelCentralControls_TEMA();            
      break;
      case UniCh_C_VIDyA:
         m_central_controls=new CUniChannelCentralControls_VIDyA();            
      break;
      case UniCh_C_PrCh:
         m_central_controls=new CUniChannelCentralControls_PrCh();            
      break;
   }    
  
   // passing pointers to control objects
   m_central_controls.SetPointers(m_c_value1,m_c_value2,m_c_value3,m_c_price,m_c_method);
   // initialization of group controls
   m_central_controls.InitControls();
  
   // allowing entering values from keyboard
   m_c_value1.SetReadOnly(false);
   m_c_value2.SetReadOnly(false);
   m_c_value3.SetReadOnly(false);
  
   // setting the minimum allowed values
   m_c_value1.SetMinValue(1);        
   m_c_value2.SetMinValue(1);
   m_c_value3.SetMinValue(1);            
  
   // calculating the height of the form
   this.SolveHeight();
        }

 SetWidthType () メソッド:

void SetWidthType(long type){
   // If an object has already been created, we need to delete it
   if(CheckPointer(m_width_controls)==POINTER_DYNAMIC){
      delete(m_width_controls);
      m_width_controls=NULL;
   }
   switch((EWType)type){ // creating an object depending on the selected class
      case UniCh_W_ATR:
         m_width_controls=new CUniChannelWidthControls_ATR();
      break;
      case UniCh_W_StdDev:
         m_width_controls=new CUniChannelWidthControls_StdDev();            
      break;
      case UniCh_W_Points:
         m_width_controls=new CUniChannelWidthControls_InPoints();            
      break;
      case UniCh_W_Percents:
         m_width_controls=new CUniChannelWidthControls_Envelopes();            
      break;
      case UniCh_W_PrCh:
         m_width_controls=new CUniChannelWidthControls_PrCh();                        
      break;
   }    
   // passing pointers to control objects
   m_width_controls.SetPointers(m_w_value1,m_w_value2,m_w_price,m_w_method);
   // initialization of group controls
   m_width_controls.InitControls();
  
   // setting the minimum allowed values
   m_w_value1.SetReadOnly(false);
   m_w_value2.SetReadOnly(false);
  
   // setting the minimum allowed values
   m_w_value1.SetMinValue(1);        
   m_w_value2.SetMinValue(0);
  
   // calculating the height of the form
   this.SolveHeight();
              
        }  

SetCentralType () および SetWidthType () メソッドのトレーリングストップには、フォームの高さを計算する SolveHeight () メソッドが呼び出されます。

void SolveHeight(){
   // if both objects exist (central line and width)
   if(CheckPointer(m_central_controls)==POINTER_DYNAMIC && CheckPointer(m_width_controls)==POINTER_DYNAMIC){
      m_Height=(m_width_controls.ControlsCount()+m_central_controls.ControlsCount()+6)*20+10;
   }      
        }  

インジケーターとグラフィカルユーザーインターフェイスの接続に進みます。  

インジケータとグラフィカルインタフェースの接続

UniChannel インジケーターを iUniChannelGUI として保存します。 UniOscGUI inbdicator と同様に、そのプロパティウィンドウの上部に外部 UseGUI パラメータを追加します。 UseDefault と KeepPrev を追加した後、デフォルトで true に設定し、[プロパティ] ウィンドウに表示します。

input bool                 UseGUI        =  true;
input bool                 UseDefault    =  true;
  input bool                 KeepPrev      =  true;

グラフィカルインターフェイスを含むファイル (インジケータークラスを含むファイルが含まれている場合):

# include <unichannel/unichannelgui.mqh>

OnInit () 関数の最下部で、gui ブートコードを追加します。 しかし、これを行う前に、中心線とボーダーの種類を持つ配列が必要です。 インジケータの外部パラメータの下にを追加:

// array of the central line types
ECType ctype[]={
   UniCh_C_AMA,
   UniCh_C_DEMA,
   UniCh_C_FrAMA,
   UniCh_C_MA,
   UniCh_C_TEMA,
   UniCh_C_VIDyA,
   UniCh_C_PrCh
};
// array with the border types
EWType wtype[]={
   UniCh_W_ATR,
   UniCh_W_StdDev,
   UniCh_W_Points,
   UniCh_W_Percents,
   UniCh_W_PrCh
};

また、フォームクラスへのポインターをここに追加します。

CUniChannelForm * frm;

OnInit () 関数の最後に、GUIオブジェクトの作成を実装します。

if(UseGUI){
  
   // creation and initialization of the form object
   frm=new CUniChannelForm();
   frm.Init();
  
   // auxiliary variables
   int ind1=0;
   int ind2=0;
  
   // search for the selected type of the central line in the array of central line types
   for(int i=0;i<ArraySize(ctype);i++){        
      frm.m_c_cmb_main.AddItem(EnumToString(ctype[i]));
      if(ctype[i]==_CentralType){
         ind1=i;
      }
   }
  
   // search for the selected type of the channel border in the array of border types
   for(int i=0;i<ArraySize(wtype);i++){        
      frm.m_w_cmb_main.AddItem(EnumToString(wtype[i]));
      if(wtype[i]==_WidthType){
         ind2=i;
      }
   }      
  
   // showing the selected type of the central line in the list
   frm.m_c_cmb_main.SetSelectedIndex(ind1);      
   // preparing controls corresponding to the type
   frm.SetCentralType(_CentralType);
  
   // showing the selected border type in the list
   frm.m_w_cmb_main.SetSelectedIndex(ind2);      
   frm.SetWidthType(_WidthType);      
  
   // setting values
   frm.SetValues(
                  _c_Period1,
                  _c_Period2,
                  _c_Period3,
                  _c_Method,
                  _c_Price,
                  _c_Shift,
                  _w_Period,
                  _w_Width,
                  _w_Method,
                  _w_Price,
                  _w_LockPeriod,
                  _w_Shift
   );
  
   // setting the form properties
   frm.SetSubWindow(0);
   frm.SetPos(10,30);
   // showing the form
   frm.Show();
    }    

フォームオブジェクトの作成に加えて、インジケーターの選択リストがいっぱいになり、選択されたバリアントが割り当てられます。 また、コントロール内の他のすべての値を設定してみましょう。 その後、インジケーターをチャートに添付すると、コントロールを持つフォームが表示されます (図1)。


図1. ユニバーサルチャネルコントロールを持つフォーム

コントロールが正しく表示され、フォームボタンの操作を確認する必要があります。 6つの異なるイベントが OnChartEvent () 関数で処理されます。 イベントの処理は非常に複雑なので、別の関数が使用されます:

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   // form events
   if(frm.Event(id,lparam,dparam,sparam)==1){
      EventForm();
   }
  
   // selecting the central line type
   if(frm.m_c_cmb_main.Event(id,lparam,dparam,sparam)==1){
      EventCentralTypeChange();
   }  
  
   // selecting the border type
   if(frm.m_w_cmb_main.Event(id,lparam,dparam,sparam)==1){
      EventWidthTypeChange();
   }  
  
   // changing the central line parameters
   if(frm.m_central_controls.Event(id,lparam,dparam,sparam)==1){
      EventCentralParametersChange();
   }  
  
   // changing the border parameters
   if(frm.m_width_controls.Event(id,lparam,dparam,sparam)==1){
      EventWidthParametersChange();
   }  
   // changing the shift parameters
   if(frm.m_c_shift.Event(id,lparam,dparam,sparam)!=0 ||
      frm.m_w_shift.Event(id,lparam,dparam,sparam)
   ){
      EventShift();
   }    
    }  

この関数をすべて検討してみましょう。 EventForm () 関数:

void EventForm(){      
   int win=ChartWindowFind(0,ShortName);  // determining the indicator sub-window
   ChartIndicatorDelete(0,win,ShortName); // deleting the indicator
   ChartRedraw();
    }  

この関数は、十字ボタンを押してフォームを閉じると、インジケータウィンドウが短い名前で検索され、インジケーターが削除されるときに実行されます。 

EventCentralTypeChange () 関数:

void EventCentralTypeChange(){    
   // getting a new type into the variable
   _CentralType=ctype[frm.m_c_cmb_main.SelectedIndex()];
  
   // deleting an old object and creating a new one
   delete(central);
   LoadCentral(true);
  
   // checking the indicator loading
   if(!central.CheckHandle()){
      Alert("Error while loading indicator "+central.Name());
   }
   // setting offsets and buffer names
   SetStyles();
   // setting a new type in the list
   frm.SetCentralType(ctype[frm.m_c_cmb_main.SelectedIndex()]);
   // updating the values of parameters on the form
   frm.SetValues(
                  _c_Period1,
                  _c_Period2,
                  _c_Period3,
                  _c_Method,
                  _c_Price,
                  _c_Shift,
                  _w_Period,
                  _w_Width,
                  _w_Method,
                  _w_Price,
                  _w_LockPeriod,
                  _w_Shift
   );
   // refreshing the form
   frm.Refresh();
  
   // starting the timer for the indicator re-calculation
   EventSetMillisecondTimer(100);
    }

この関数では、中心線インジケータの種類が変更されます。 まず、選択したインジケーターの種類が取得され、古いオブジェクトが削除され、新しいオブジェクトが作成されます。 新しいオブジェクトを作成する場合、そのパラメータの一部を変更することができます (UseDefault 関数のため)、SetValues () メソッドは、コントロールに新しい値を設定するために呼び出され、更新されます (refresh () メソッド)。 再計算時にタイマが起動し、インジケータの再計算が実行されます。      

EventWidthTypeChange () 関数は EventCentralTypeChange () 関数に似ていますので、詳しくは解説しません。 

EventCentralParametersChange () および EventWidthParametersChange () 関数は、パラメータの変化に対するインジケーターを提供します。 この関数は、中心となる点は同じです。 しかし、パラメータを修正するため、この関数は独自のユニークな関数を考慮されます。

void EventCentralParametersChange(){          
  
   // the variable indicates the need to restart the indicator of borders
   bool dolock=false;
  
   // changing the value of period 1
   if((int)frm.m_c_value1.Value()>0){
      // assigning a values received from the control to the variable 
      _c_Period1=(int)frm.m_c_value1.Value();
      // if period 1 is connected with the period of the width indicator
      if(_w_LockPeriod==LockTo_Period1){
         // we set the value of period 1 to the variable with the width indicator period
         _w_Period=_c_Period1;
         // displaying it on the form
         frm.m_w_value1.SetValue(_w_Period);
         // indicating that the second indicator needs to be restarted
         dolock=true;
      }
   }
  
   // changing the value of period 2 similar to period 1
   if((int)frm.m_c_value2.Value()>0){
      _c_Period2=(int)frm.m_c_value2.Value();
      if(_w_LockPeriod==LockTo_Period2){
         _w_Period=_c_Period2;
         frm.m_w_value1.SetValue(_w_Period);
         dolock=true;
      }        
   }
  
   // changing the value of period 3 similar to period 1
   if((int)frm.m_c_value3.Value()>0){
      _c_Period3=(int)frm.m_c_value3.Value();
      if(_w_LockPeriod==LockTo_Period3){
         _w_Period=_c_Period3;
         frm.m_w_value1.SetValue(_w_Period);
         dolock=true;
      }        
   }
  
   // changing the method
   if(frm.m_c_method.SelectedIndex()!=-1){
      _c_Method=e_method[frm.m_c_method.SelectedIndex()];
   }
  
   // changing the price
   if(frm.m_c_price.SelectedIndex()!=-1){
      _c_Price=e_price[frm.m_c_price.SelectedIndex()];
   }
  
   // deleting an old object and creating a new one
   delete(central);
   LoadCentral(false);
   if(!central.CheckHandle()){
      Alert("Error while loading indicator "+central.Name());
   }  
   // deleting and creating a new object of the second indicator
   if(dolock){
      delete(width);
      LoadWidth(false);
      if(!width.CheckHandle()){
         Alert("Error while loading indicator "+width.Name());
      }  
   }  
   // setting offsets and buffer names
   SetStyles();
   // starting the timer for the indicator re-calculation
   EventSetMillisecondTimer(100);
    }  

この関数は、3つの期間のいずれかが変更されると、パラメータのチェックが実行されます。 ボーダーインジケータのパラメータが変更され、フォーム上で更新され、true が dolock 変数に割り当てられます。 最後に、古いインジケーターオブジェクトが削除され、新しいものが作成され、dolock 変数が true と等しい場合は、境界線のオブジェクトが削除されます。 その後、タイマーが開始し、インジケーターが再計算します。

void EventWidthParametersChange(){  
      
   // the variable indicates the need to restart the indicator of the central line
   bool dolock=false;
   // changing the period
   if((int)frm.m_w_value1.Value()>0){
      // assigning a values received from the control to the variable
      _w_Period=(int)frm.m_w_value1.Value();
      // performing the lock
      // the width parameter is connected with the first period of the central line
      if(_w_LockPeriod==LockTo_Period1){
         // assigning a new value to the variable of the central line indicator 
         _c_Period1=_w_Period;
         // updating the value on the form
         frm.m_c_value1.SetValue(_c_Period1);
         // indicating the need to restart the width indicator
         dolock=true;
      }
      else if(_w_LockPeriod==LockTo_Period2){ // if locking with period 2
         _c_Period2=_w_Period;
         frm.m_c_value2.SetValue(_c_Period2);
         dolock=true;
      }
      else if(_w_LockPeriod==LockTo_Period3){ // if locking with period 3
         _c_Period3=_w_Period;
         frm.m_c_value3.SetValue(_c_Period3);
         dolock=true;
      }
   }
  
   // changing the channel width parameter
   if((double)frm.m_w_value2.Value()>0){
      _w_Width=(double)frm.m_w_value2.Value();
   }      
  
   // changing the method
   if(frm.m_w_method.SelectedIndex()!=-1){
      _w_Method=e_method[frm.m_w_method.SelectedIndex()];
   }
  
   // changing the price
   if(frm.m_w_price.SelectedIndex()!=-1){
      _w_Price=e_price[frm.m_w_price.SelectedIndex()];
   }
  
   // the event of a change in the lock type selection list 
   if(frm.m_w_lockto.SelectedIndex()>=0){
      // assigning a values received from the control to the variable
      _w_LockPeriod=e_lockto[frm.m_w_lockto.SelectedIndex()];
      // if locking with some of the periods is selected,
      // its value is copied and the form is refreshed  
      if(_w_LockPeriod==LockTo_Period1){
         _w_Period=_c_Period1;
         frm.m_w_value1.SetValue(_w_Period);
      }
      else if(_w_LockPeriod==LockTo_Period2){
         _w_Period=_c_Period2;
         frm.m_w_value1.SetValue(_w_Period);
      }
      else if(_w_LockPeriod==LockTo_Period3){
         _w_Period=_c_Period3;
         frm.m_w_value1.SetValue(_w_Period);
      }
   }      
   // deleting an old object and creating a new one
   delete(width);
   LoadWidth(false);
   if(!width.CheckHandle()){
      Alert("Error while loading indicator "+width.Name());
   }
  
   // deleting and creating a new object of the second indicator
   if(dolock){
      delete(central);
      LoadCentral(false);
      if(!central.CheckHandle()){
         Alert("Error while loading indicator "+central.Name());
      }
   }
   // setting offsets and buffer names
   SetStyles();
   // starting the timer for the indicator re-calculation
   EventSetMillisecondTimer(100);      
    }    

この関数は、期間を変更する際チェックされ、必要に応じて中心線インジケータに対応する期間が変更されます。 選択リストが受信された場合、中心線インジケータの適切な変数からの値がボーダーインジケータ期間の変数に割り当てられます。

シフト値の変更のイベントの処理は非常に簡単です:

void EventShift(){     
   // receiving new values in the variables 
   _c_Shift=(int)frm.m_c_shift.Value();
   _w_Shift=(int)frm.m_w_shift.Value();
   // setting new styles
   SetStyles();
   // refreshing the chart
   ChartRedraw();
    }  

コントロールの値が変数に代入され、setstyles () が呼び出され、チャートが更新されます。

この時点で、グラフィカルインターフェイスを持つインジケータは、ほぼ準備が整いました。

インジケーターテスト中に次の欠陥が検出されました。 外部 UseDefault パラメータが有効で、ピリオドロックが使用された場合、ロックが失敗しました。 これは、2番目のインジケータ (幅インジケータ) をロードするときに、パラメータの変更がコンストラクタで実行されるという事実に基づいています。 このバグを修正するために、幅インジケータの特定の子クラスを変更しなければなりません。 オプションのパラメータ ' ロック ' は、CChannelUni_Calculate_ATR、CChannelUni_Calculate_StdDev、および CChannelUni_Calculate_PriceChannel のコンストラクタに追加されました。 デフォルト値は false です。 (パラメータがクラスに渡されない場合、すべては変更なしで動作します)。 locked = true と use_default = true の場合、コンストラクタ内のピリオドパラメータは変更されません (locked = true)。 CChannelUni_Calculate_ATR クラスの一部です:

if(use_default){
   if(keep_previous){
      if(ma_period==-1 && !locked)ma_period=14// change
      if(ch_width==-1)ch_width=2;
   }
   else{
      if(!locked)ma_period=14// change
      ch_width=2;
   }      
    }  

デフォルト値は、ロックされた変数が false に設定した場合にのみ ma_period に割り当てられます。 LoadWidth () 関数は応じています。 ロック ' の値は、関数の先頭で計算されます。

bool Locked=(w_LockPeriod!=LockTo_Off);

この変数は、オブジェクトの作成時にクラスのコンストラクタに渡されます。

ユニバーサルオシレーターで行われたように、ここでは、カラースキームを変更し、時間枠を変更するときにインジケータのパラメータの保存を提供する関数を追加します。 ユニバーサルオシレーターの作成時に考慮したため、配色パターンの使用については説明しません。 インジケーターパラメータの保存を提供します。

インジケーターの OnDeinit () 関数は、チャートの変更により初期化が実行された場合、パラメータの値を持つグラフィカルオブジェクトを作成します。 チャートの可視性の外で、グラフィカルオブジェクトを作成してみましょう:

void SaveOrDeleteParameters(const int reason){
   // if it is not chart change, we should delete graphical objects 
   if(reason!=REASON_CHARTCHANGE){
      ObjectDelete(0,"_CentralType");
      ObjectDelete(0,"_c_Period1");
      ObjectDelete(0,"_c_Period2");
      ObjectDelete(0,"_c_Period3");
      ObjectDelete(0,"_c_Shift");
      ObjectDelete(0,"_c_Method");
      ObjectDelete(0,"_c_Price");
      ObjectDelete(0,"_WidthType");
      ObjectDelete(0,"_w_Period");
      ObjectDelete(0,"_w_LockPeriod");
      ObjectDelete(0,"_w_Shift");
      ObjectDelete(0,"_w_Method");
      ObjectDelete(0,"_w_Price");
      ObjectDelete(0,"_w_Width");      
   }
   else// when changing the chart, we create graphical objects with the values of parameters
      SaveParameter("_CentralType",(string)_CentralType);
      SaveParameter("_c_Period1",(string)_c_Period1);
      SaveParameter("_c_Period2",(string)_c_Period2);
      SaveParameter("_c_Period3",(string)_c_Period3);
      SaveParameter("_c_Shift",(string)_c_Shift);
      SaveParameter("_c_Method",(string)_c_Method);
      SaveParameter("_c_Price",(string)_c_Price);
      SaveParameter("_WidthType",(string)_WidthType);
      SaveParameter("_w_Period",(string)_w_Period);
      SaveParameter("_w_LockPeriod",(string)_w_LockPeriod);
      SaveParameter("_w_Shift",(string)_w_Shift);
      SaveParameter("_w_Method",(string)_w_Method);
      SaveParameter("_w_Price",(string)_w_Price);
      SaveParameter("_w_Width",(string)_w_Width);        
   }
}
// an auxiliary function for saving one parameter in a graphical object
void SaveParameter(string name,string value){
   if(ObjectFind(0,name)==-1){
      ObjectCreate(0,name,OBJ_LABEL,0,0,0);
      ObjectSetInteger(0,name,OBJPROP_XDISTANCE,0);
      ObjectSetInteger(0,name,OBJPROP_YDISTANCE,-30);
   }
   ObjectSetString(0,name,OBJPROP_TEXT,value);
    }

oninit () 関数では、PrepareParameters () 関数の呼び出し直後に、LoadSavedParameters () 関数を呼び出します。

bool LoadSavedParameters(){
   // if all objects with parameters exist 
   if(ObjectFind(0,"_CentralType")==0 &&
      ObjectFind(0,"_c_Period1")==0 &&
      ObjectFind(0,"_c_Period2")==0 &&
      ObjectFind(0,"_c_Period3")==0 &&
      ObjectFind(0,"_c_Shift")==0 &&
      ObjectFind(0,"_c_Method")==0 &&
      ObjectFind(0,"_c_Price")==0 &&
      ObjectFind(0,"_WidthType")==0 &&
      ObjectFind(0,"_w_Period")==0 &&
      ObjectFind(0,"_w_LockPeriod")==0 &&
      ObjectFind(0,"_w_Shift")==0 &&
      ObjectFind(0,"_w_Method")==0 &&
      ObjectFind(0,"_w_Price")==0 &&
      ObjectFind(0,"_w_Width")==0
   ){
      // getting values from graphical objects
      _CentralType=(ECType)ObjectGetString(0,"_CentralType",OBJPROP_TEXT);
      _c_Period1=(int)ObjectGetString(0,"_c_Period1",OBJPROP_TEXT);
      _c_Period2=(int)ObjectGetString(0,"_c_Period2",OBJPROP_TEXT);
      _c_Period3=(int)ObjectGetString(0,"_c_Period3",OBJPROP_TEXT);
      _c_Shift=(int)ObjectGetString(0,"_c_Shift",OBJPROP_TEXT);
      _c_Method=(long)ObjectGetString(0,"_c_Method",OBJPROP_TEXT);
      _c_Price=(long)ObjectGetString(0,"_c_Price",OBJPROP_TEXT);
      _WidthType=(EWType)ObjectGetString(0,"_WidthType",OBJPROP_TEXT);
      _w_Period=(int)ObjectGetString(0,"_w_Period",OBJPROP_TEXT);
      _w_LockPeriod=(long)ObjectGetString(0,"_w_LockPeriod",OBJPROP_TEXT);
      _w_Shift=(int)ObjectGetString(0,"_w_Shift",OBJPROP_TEXT);
      _w_Method=(long)ObjectGetString(0,"_w_Method",OBJPROP_TEXT);
      _w_Price=(long)ObjectGetString(0,"_w_Price",OBJPROP_TEXT);
      _w_Width=(double)ObjectGetString(0,"_w_Width",OBJPROP_TEXT);
      return(true);
   }
   else{
      return(false);
   }
    }  

この関数は、オブジェクトが存在するかどうかをチェックします。 存在する場合、オブジェクトが使用されている場合、true を返します。 この関数が true を返した場合、LoadCentral () 関数と LoadWidth () は false パラメータを使用して呼び出す必要があります (デフォルトのパラメータの設定を防ぐため)。 oninit () 関数の断片:

bool ChartCange=LoadSavedParameters();
  
    LoadCentral(!ChartCange);  

LoadWidth () 関数は、同じ方法で呼び出されます。

LoadWidth(!ChartCange);

ユニバーサルチャネルの作成が完全に完了しました。 

結論

ユニバーサルオシレーターから大量のコードを使用するにもかかわらず、ユニバーサルチャネルの作成にはまだかなりのタスクが必要です。 ユニバーサルオシレーターの主な違いは、2つの独立したユニットの存在です。つまり、中心線とチャネルの境界線です。 2倍難しくなりました。 ユニバーサルチャネルには、周期ロック関数によって接続される、より複雑なパラメータ変更アルゴリズムがあります。 新しいインジケータの読み込みは、2つのインジケータが使用されるため、より複雑になりました。 また、新しい関数を追加し、時間枠を切り替えるときにパラメータを保存します。 その結果、有用なインジケーターができました。 さらに、このインジケータは、チャネルの関数を大幅に拡張し、中心線とチャネル境界の構築メソッドを別々に選択することができます。 可能な組み合わせは多岐にわたります。 グラフィカルインターフェイスを使用したインジケータアプリケーションは、視覚的にすべての組み合わせを分析することができます。

添付

この記事の添付ファイルを必要とするダウンロード可能なアーカイブです。 ファイルは右のフォルダにあります。 ターミナルの同じ場所に保存する必要があります。

 

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

添付されたファイル |
files.zip (93 KB)
グラフィカルインタフェースX:レンダーテーブルの新機能(ビルド9) グラフィカルインタフェースX:レンダーテーブルの新機能(ビルド9)
今日までは、ライブラリの最も高度なテーブルはCTableでした。このテーブルは、OBJ_EDIT型のエディットボックスから組み立てられており、さらなる開発は難しいです。したがって、機能の最大化においては、ライブラリ開発の現段階を考慮しても、CCanvasTable型のレンダーテーブルを開発する方が賢明です。その現バージョンはまったく使えない状態ですが、この記事から始めて状況を改善していきましょう。
ハースト指数の計算 ハースト指数の計算
ハースト指数とその計算アルゴリズムの背後にある考え方について紹介します。 金融相場セグメントの数を分析し、MT5でフラクタル解析をする方法を説明します。
通貨バスケットをトレードするときに利用可能なパターン。 パート2 通貨バスケットをトレードするときに利用可能なパターン。 パート2
通貨バスケットのパターンの議論を続けてきました。 このパートでは、複合トレンドインジケーターを用いた場合に形成されるパターンについて考察します。 通貨インデックスに基づくインジケーターは、分析ツールとして使用されます。
可視化の可能性 Rのプロットに似たMQL5のグラフィックス ライブラリ 可視化の可能性 Rのプロットに似たMQL5のグラフィックス ライブラリ
トレードロジックを勉強する際、チャートの視覚的な表現は非常に重要です。科学分野で人気のある数々のプログラミング言語 (R や Python など) は可視化のための関数”プロット”があります。これらは視覚化するために、線、点の分布、ヒストグラムなどを描くことができます。MQL5でも、CGraphics クラスを使用して、同じことができます。