English Русский 中文 Español Deutsch Português
インディケータコードから Expert Advisor コードへの変換インディケータストラクチャ

インディケータコードから Expert Advisor コードへの変換インディケータストラクチャ

MetaTrader 4 | 17 2月 2016, 14:33
2 857 0
Nikolay Kositsin
Nikolay Kositsin

はじめに


よりよくご理解いただくために、以下の資料をご一読ください。


1. MetaQuotes Software Corp. Features of Custom Indicators Creation.
2. Nikolay Kositsin. Multiple Null Bar Re-Count in Some Indicators.

タイトルで示されている本稿のテーマに入る前に、次の質問がふさわしいかもしれません。:「大半の場合、カスタムインディケータ処理を行うEA が、それ自体のコード内でカスタムインディケータを処理するのに必要なものをすべて備えている類似体よりもずっと簡単に思えるなら、インディケータコードを EA コードに転換する目的はなにでしょうか?特に、コードが正確に描かれていることを考慮するとすれば、どちらの場合も結果はまったく同じになるのです。


私見ですが、必要になるのは次の2つの場合です。
1. ゼロバーで計算される EA 計算値が全く使用されなければ、当然ゼロバーや最初のバーでの不要な再計算は省略したいと思います。これによりそのような EA 処理時間を短縮することができます。それは複雑でリソース消費が多いコードに適しています。
2. デコンパイル対策のコード保護を最大限ほどこしたExpert Advisor の商用利用

2番目のケースでは、状況はひじょうに明確でコード転換はかなり合理的です。そして最初のケースでは、大多数の状況では不要な計算を除外したカスタムインディケータコードを書き直すほうが簡単です。当然そのようなインディケータはトレーディングではなく Expert Advisors にのみ適するものです。そんなわけで、問題解決のこのバリアントからお話しを進めていきましょう。

インディケータ最適化例

まず、以下のカスタムインディケータのコードフラグメントに注目していただきたいと思います。

int start()
  {
    int limit;
    int counted_bars = IndicatorCounted();
//---- the last calculated bar will be recalculated
    if(counted_bars > 0) 
        counted_bars--;
    limit = Bars - counted_bars - 1;
//---- the main cycle
    for(int i = limit; i >= 0; i--)
      {
        //---- 
        ExtBlueBuffer[i] = iMA(NULL, 0, JawsPeriod, 0, MODE_SMMA, 
                               PRICE_MEDIAN, i);
        ExtRedBuffer[i] = iMA(NULL, 0, TeethPeriod, 0, MODE_SMMA, 
                              PRICE_MEDIAN, i);
        ExtLimeBuffer[i] = iMA(NULL, 0, LipsPeriod, 0, MODE_SMMA, 
                               PRICE_MEDIAN, i);
      }
//----
     return(0);
  }

この場合、われわれには次の行が適しています。

if(counted_bars > 0) 
    counted_bars--;


'counted_bars' 変数の値の減少を1ずつ行うこのチェックの意味は、カスタムインディケータにこの行がなければ、ゼロバーが変更されるときバッファから EA に対して誤った値が送信されてしまうの、というものです。EA のインディケータ曲線はきわめて『しわくちゃな』形をしています。

カスタムインディケータでは、変数 'limit' および 'counted_bars' は異なる名前を持ちますが、プログラムコードにはこれらのチェックが含まれています。EA プログラマーの方から出るいくらかのクレームにはこの説明で十分だと私は思います。インディケータバッファからのMetaTrader データやカスタムインディケータから受信される同様のデータは同じものではありません。インディケータコードと EA コードが正確に書かれていれば、インディケータコードがどれほどむつかしくてもデータは常に同じです。

ただ、ここで注意が必要なのは、平滑化アルゴリズムの中には、平滑化が開始される参照ポイントに敏感なものもあるということです。すなわち、同じ値を持つために、インディケータと EA 内のインディケータコードのサイクルにおいてすべてのバーの再計算を開始する一番古いバーの番号は一致している必要があります。


ここに EA での処理迅速化のためのインディケータコード最適化方法を説明する例があります。. インディケータがゼロバーでの値の再計算を中断したのち、メインのインディケータでサイクルがゼロを1に変えます。

// instead of
for(int i = limit; i >= 0; i--)      
// write
for(int i = limit; i >= 1; i--)

結果、ソースコードは次のようになります。

int start()
  {
    int limit;
    int counted_bars = IndicatorCounted();
//---- the last bar will be recalculated
    if(counted_bars > 0)
        counted_bars--;
    limit = Bars - counted_bars - 1;
      
  //---- the main cycle //now the cycle ends in 1
    for(int i = limit; i >= 1; i--)
      {
        //---- 
        ExtBlueBuffer[i] = iMA(NULL, 0, JawsPeriod, 0, MODE_SMMA,
                               PRICE_MEDIAN, i);
        ExtRedBuffer[i] = iMA(NULL, 0, TeethPeriod, 0, MODE_SMMA, 
                              PRICE_MEDIAN, i);
        ExtLimeBuffer[i] = iMA(NULL, 0, LipsPeriod, 0, MODE_SMMA, 
                               PRICE_MEDIAN, i);
      }
  //----
    return(0);
  }


繰り返しますが、上記の方法はクローズされたバー、すなわちゼロバー以外すべてのバー、のみを処理する EA 用です。

実トレーディングで本格的にお手持ちの EA を使用しようとしていてご自身の資金を信用されているなら、お手持ちの Expert Advisor および EA が処理を行うインディケータを細かい部分まで注意して確認する必要があります。それに、その確認作業はご自身でおこなわなければならないのです。インディケータストラクチャとそのコードの最適化方法を完全に理解するために数日をそっくり費やすのが、おおざっぱに書かれたインディケータから値を受信する EA を我慢して数か月使用するよりはずっと簡単で賢いやり方だと思います。

そのため、インディケータコードを EA コードに変換するにはそれなりの理由が必要なのは明らかです、インディケータが正確に書かれて入れば、EA の処理はそれなしでもそれほど遅いものにはなりません。最初の EA コードはカスタムインディケータを使ってこの形式でチェックアウトを作成するのが簡単です。And if the EA がreally 完璧な結果を出したら、順番にカスタムインディケータの呼び出しをインディケータコードのフラグメントに変えていき、コードはさらに最適化することが可能です。

また、検証済みの損失および収益値は EA コード変更後修正してはいけないことに注意が必要です。

既存のインディケータ数はひじょうに大きいもので、それぞれが即時のコードを持っています。すべてのインディケータに変換するコードのユニバーサルメソッドを作成することはほどんど不可能なのはこの理由によります。1つあるいはそれおと同じカスタムインディケータが EA コードで複数回表されることで問題はより深刻なものとなります。インディケータコードが多少シンプルであれば、それはカスタム関数に書くことができ、そのような場合にカスタムインディケータを関数に変えることはかなり容易です。ただ、EA コードはひじょうに頻繁にそのようなディメンションを達成するため、そこのエラーを検出することはほとんど不可能です。そうするとすべての努力はむなしくなります。


インディケータストラクチャの一般的スキーム


本稿のメインテーマに入る前に、まず、将来的な EA コードの一部としてインディケータに興味あるプログラマーの視点からインディケータストラクチャを分析します。

//+------------------------------------------------------------------+
//|                                                IndicatorPlan.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"
//---- drawing the indicator in the main window
#property indicator_chart_window 
//---- number of indicator buffers
#property indicator_buffers 1 
//---- indicator color
#property indicator_color1 Gold
//---- INPUT PARAMETERS OF THE INDICATOR
extern int period0 = 15;
extern int period1 = 15;
extern int period2 = 15;
//---- indicator buffers
double Ind_Buffer0[];
double Ind_Buffer1[];
double Ind_Buffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- defining the graph execution style
   SetIndexStyle(0, DRAW_LINE); 
//---- 3 indicator buffers are used for calculation
   IndicatorBuffers(3);
   SetIndexBuffer(0, Ind_Buffer0); 
   SetIndexBuffer(1, Ind_Buffer1);
   SetIndexBuffer(2, Ind_Buffer2);
//---- end of initialization
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
//---- Checking whether the bars number is enough for further calculation
   if(Bars < period0 + period1 + period2)
       return(0);
//----+ Insertion of variables with a floating point
   double Resalt0, Resalt1, Resalt2;
//----+ Insertion of integer variables and getting calculated bars
   int limit, MaxBar,bar, counted_bars = IndicatorCounted();
//---- checking for possible errors
   if(counted_bars < 0)
       return(-1);
//---- the last calculated bar must be recalculated 
   if(counted_bars > 0) 
       counted_bars--;
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   limit = Bars - counted_bars - 1; 
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   MaxBar = Bars - 1 - (period0 + period1 + period2); 
//---- initialization of zero 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = Bars - 1; bar >= MaxBar; bar--)
         {
           Ind_Buffer0[bar] = 0.0;
           Ind_Buffer1[bar] = 0.0;
           Ind_Buffer2[bar] = 0.0;
         }
     }
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt1 calculation based on the external 
       // variable period1
       Ind_Buffer1[bar] = Resalt1;
     }
//----+ THE SECOND CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt2 calculation 
       // based on the values of the buffer Ind_Buffer1[]  
       // and external variable period2
       Ind_Buffer2[bar] = Resalt2;
     }
//----+ THE MAIN CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt0 calculation 
       // based on the values of the buffer Ind_Buffer2[]  
       // and external variable0
       Ind_Buffer0[bar] = Resalt0;
     }
   return(0);
  }
//+------------------------------------------------------------------+

当然ながら、実際のインディケータに反映されるインディケータ値の数、計算に使用されるインディケータバッファ数、インディケータバッファ値計算のサイクル数は異なるでしょう。しかしこれは提示するスキームの意味を変えるものではありません。別のケースでは、それは完全に類似体です。

ここで、今回のコンテキストでは興味の対象でなく Expert Advisor に不要なエレメントをスキームから除外します。:

//+------------------------------------------------------------------+
//|                                               IndicatorPlan1.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
//---- INPUT PARAMETERS OF THE INDICATOR
extern int period0 = 15;
extern int period1 = 15;
extern int period2 = 15;
//---- indicator buffers
double Ind_Buffer0[];
double Ind_Buffer1[];
double Ind_Buffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- end of initialization
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
//---- Checking whether the bars number is enough for further calculation
   if(Bars < period0 + period1 + period2)
       return(0);
//----+ Insertion of variables with a floating point
   double Resalt0, Resalt1, Resalt2;
//----+ Insertion of integer variables and getting calculated bars
   int limit, MaxBar, bar, counted_bars = IndicatorCounted();
//---- checking for possible errors
   if(counted_bars < 0)
       return(-1);
//---- the last calculated bar must be recalculated 
   if(counted_bars > 0) 
       counted_bars--;
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   limit = Bars - counted_bars - 1; 
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   MaxBar = Bars - 1 - (period0 + period1 + period2); 
//---- initialization of zero 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = Bars - 1; bar >= MaxBar; bar--)
         {
           Ind_Buffer0[bar] = 0.0;
           Ind_Buffer1[bar] = 0.0;
           Ind_Buffer2[bar] = 0.0;
         }
     }
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt1 calculation  
       // based on the external variable period1
       Ind_Buffer1[bar]= Resalt1;
     }
//----+ THE SECOND CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt2 calculation 
       // based on the values of the buffer Ind_Buffer1[]  
       // and external variable period2
       Ind_Buffer2[bar] = Resalt2;
     }
//----+ THE MAIN CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt0 
       // based on the values of the buffer Ind_Buffer2[]  
       // and external variable period0
       Ind_Buffer0[bar] = Resalt0;
     }
   return(0);
  }
//+------------------------------------------------------------------+

残念なエラーがなければ、このコードは簡単に Expert Advisor コードに入れることができたでしょう。

1. まず忘れてはならないことは、関数 IndicatorCounted() は Expert Advisors では動作しないということです。
2. また初期化ブロックではカスタム配列をインディケータ配列に変えることはできません。

インディケータコードを完全に保存するためには、最初に関数 IndicatorCounted() の類似体を作成し、Expert Advisor でインディケータバッファの類似隊をいくらかエミュレートする必要があります。残念ながら、標準的な関数によって EA でインディケータバッファを直接エミュレートすることはできません。これまでに Expert Advisor 向けの SetIndexBuffer() および IndicatorBuffers() の類似体はありません。そのためこの問題を解決するには別の方法が必要です。MQL4 にはそのためのオプションが十分あるのです。



Expert Advisor におけるインディケータバッファのエミュレーション


まずインディケータバッファの内で起こる手順を詳しく見ていきます。

1. インディケータバッファ変数に割り当てられる値は、インディケータがチャートにアタッチされており、ターミナルが動作していれば、サイクル間で失われることはありません。
2. チャート上でゼロバー(直近バー)が変更されると、インディケータバッファのエレメントはすべて移動sれます。
3. 新規バーが来ると、インディケータ内で変数の限界値が1から2に代わります。そしてバッファエレメントはすべて1移動します。すなわち、ゼロバーが1番目のバーとなり、1番目のバーが2番目となる、などです。
4. 当然インディケータバッファのディメンションも変化します。次のティックでバーに変化がなければ、バッファエレメントは元の場所のままです。

それではインディケータバッファのエミュレーションです。これには、次に挙げる MQL4 の標準関数を使用します。 ArraySize()、 ArrayResize()、ArraySetAsSeries() です。インディケータバッファのエミュレーションコードはひじょうにシンプルで、その処理の原理は記述可能です。ゼロバーが変化するとき、バッファ内のエレメント定義の直接的順序は復元され、関数 ArrayResize() によって新規バーからバッファに新しいセルが追加されます。その後、バッファ内エレメント定義の逆順が設定され、エミュレート済みのインディケータバッファ内の最初のセルの間に空のセルが出現します。


//---- INDICATOR BUFFERS EMULATION
  int NewSize = iBars(symbol, timeframe);
  //----  Checking the change of the zero bar
  if(ArraySize(Ind_Buffer0) < NewSize)
    {
      //---- Set the direct indexing direction in the array 
      ArraySetAsSeries(Ind_Buffer0, false);
      ArraySetAsSeries(Ind_Buffer1, false);
      ArraySetAsSeries(Ind_Buffer2, false);
      //---- Change the size of the emulated indicator buffers 
      ArrayResize(Ind_Buffer0, NewSize); 
      ArrayResize(Ind_Buffer1, NewSize); 
      ArrayResize(Ind_Buffer2, NewSize); 
      //---- Set the reverse indexing direction in the array 
      ArraySetAsSeries(Ind_Buffer0, true);
      ArraySetAsSeries(Ind_Buffer1, true);
      ArraySetAsSeries(Ind_Buffer2, true); 
    } 
//----


ところでmこのインディケータバッファのエミュレーション方法は、中間計算に対して8つのインディケータバッファが十分でなければ、インディケータでも使用可能です。この例は添付ファイル SMI.mq4 and SMI_New.mq4 にあります。




関数 IndicatorCounted() の代用


それでは関数 IndicatorCounted() のエミュレーション分析を行いましょう。この関数は前のインディケータ呼び出し後変わっていない現チャートの数量を返します。また別の言い方をすることもできます。この関数は前回ティックに関してクライアントターミナルで入手可能であった現チャートバー数を返します。値がまったく等しくなるように、結果のバー数量から1を引く必要があります。よってこの関数は、値が受信されたあと、事前決定関数バー-1の値で初期化される静的整数変数と簡単に置き換えることができます。その後、インディケータスキームは次の形式を持つようになります。

//+------------------------------------------------------------------+
//|                                            NewIndicatorPlan1.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
 
//---- INPUT INDICATOR PARAMETERS
extern int period0 = 15;
extern int period1 = 15;
extern int period2 = 15;
//---- indicator buffers
double Ind_Buffer0[];
double Ind_Buffer1[];
double Ind_Buffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- initialization end
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
//---- Checking whether the bars number is enough for further calculation
   if(Bars < period0 + period1 + period2)
       return(0);
//---- INDICATOR BUFFERS EMULATION
   if(ArraySize(Ind_Buffer0) < Bars)
     {
       ArraySetAsSeries(Ind_Buffer0, false);
       ArraySetAsSeries(Ind_Buffer1, false);
       ArraySetAsSeries(Ind_Buffer2, false);
       //----  
       ArrayResize(Ind_Buffer0, Bars); 
       ArrayResize(Ind_Buffer1, Bars); 
       ArrayResize(Ind_Buffer2, Bars); 
       //----
       ArraySetAsSeries(Ind_Buffer0, true);
       ArraySetAsSeries(Ind_Buffer1, true);
       ArraySetAsSeries(Ind_Buffer2, true); 
     } 
//----+ INSERTION OF A STATIC INTEGER MEMORY VARIABLE
   static int IndCounted;
//----+ Insertion of variables with a floating point
   double Resalt0, Resalt1, Resalt2;
//----+ Insertion of integer variables and getting calculated bars
   int limit, MaxBar, bar, counted_bars = IndCounted;
//---- checking for possible errors
   if(counted_bars < 0)
       return(-1);
//---- the last calculated bar must be recalculated 
   if(counted_bars > 0) 
       counted_bars--;
//----+ REMEMBERING THE AMOUNT OF ALL BARS OF THE CHART
   IndCounted = Bars - 1;
//---- defining the number of the oldest bar, 
//     starting from which new bars will be recalculated
   limit = Bars - counted_bars - 1; 
//---- defining the number of the oldest bar, 
//     starting from which new bars will be recalculated
   MaxBar = Bars - 1 - (period0 + period1 + period2); 
//---- initialization of zero 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = Bars - 1; bar >= 0; bar--)
         {
           Ind_Buffer0[bar] = 0.0;
           Ind_Buffer1[bar] = 0.0;
           Ind_Buffer2[bar] = 0.0;
         }
     }
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt1 calculation  
       // based on the external variable period1
       Ind_Buffer1[bar] = Resalt1;
     }
//----+ THE SECOND CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt2 calculation 
       // based on the values of the buffer Ind_Buffer1[] and external variable period2
       Ind_Buffer2[bar] = Resalt2;
     }
//----+ THE MAIN CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt0 calculation 
       // based on the values of the buffer Ind_Buffer2[] and external variable period0
       Ind_Buffer0[bar] = Resalt0;
     }
   return(0);
  }
//+------------------------------------------------------------------+

インディケータコードのさらなる変換とそのストラクチャの最終スキーム

このインディケータが現チャートで処理を行う Expert Advisor で一度だけ必要であるとすると、もちろん、インディケータコードをただ EA コードのパーツに変換することもできました。インディケータが2度使われるなら、2度目でインディケータ変数名をすべて変更し、コードを再び追加すればよいのです。ただこの場合、はExpert Advisor 複雑化します。

別のタイムフレームでのデータ処理タスクも簡単に遂行されます。タイプの時系列に対する Bars タイプの事前決定変数を置き換えます。

iBars(string symbol,  int timeframe);


NULL -文字列シンボル用;0 (時系列で)- int タイムフレーム用;Close[bar] - for

iClose(string symbol, int timeframe, bar);


などです。

ここからインディケータ行を分析します。

//---- checking for possible errors
if(counted_bars < 0)
    return(-1);
//---- the last calculated bar must be recalculated 
if(counted_bars > 0) 
    counted_bars--;


われわれのインディケータストラクチャ内の関数 IndicatorCounted() の置換については、インディケータcounted_bars はゼロより小さくなることは決してありません。よって Expert Advisor コード内の行


//---- checking for possible errors
if(counted_bars < 0)
    return(-1);


は省略可能です。次の2行

//---- the last calculated bar must be recalculated 
if(counted_bars > 0) 
    counted_bars--;


でも同様です。最初のバーの不要な再計算によって EA の動作速度を落とす場合、そのような確認は EA 処理にはまったく無駄なことなので、それらは削除します。それから EA への変換用最終コードは以下のようなものとなります。

//+------------------------------------------------------------------+
//|                                            NewIndicatorPlan2.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
 
//---- INPUT INDICATOR PARAMETERS
extern int period0 = 15;
extern int period1 = 15;
extern int period2 = 15;
//---- indicator buffers
double Ind_Buffer0[];
double Ind_Buffer1[];
double Ind_Buffer2[];
//---- DECLARING VARIABLES FOR CHOOSING A CHART
string symbol; int timeframe;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- CHOOSING A CHART FRO INDICATOR CALCULATION
   symbol = Symbol();//INITIALIZATION OF THE VARIABLE symbol;
   timeframe =240;//INITIALIZATION OF THE VARIABLE timeframe;
//---- end of initialization
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
// GETTING THE AMOUNT OF ALL BARS OF THE CHART
   int IBARS = iBars(symbol, timeframe);
//---- Checking whether the bars number is enough for further calculation
   if(IBARS < period0 + period1 + period2)
       return(0);
// INDICATOR BUFFERS EMULATION
   if(ArraySize(Ind_Buffer0) < IBARS)
     {
       ArraySetAsSeries(Ind_Buffer0, false);
       ArraySetAsSeries(Ind_Buffer1, false);
       ArraySetAsSeries(Ind_Buffer2, false);
       //----  
       ArrayResize(Ind_Buffer0, IBARS); 
       ArrayResize(Ind_Buffer1, IBARS); 
       ArrayResize(Ind_Buffer2, IBARS); 
       //----
       ArraySetAsSeries(Ind_Buffer0, true);
       ArraySetAsSeries(Ind_Buffer1, true);
       ArraySetAsSeries(Ind_Buffer2, true); 
     } 
// INSERTION OF A STATIC INTEGER MEMORY VARIABLE
   static int IndCounted;
//----+ Insertion of variables with a floating point
   double Resalt0, Resalt1, Resalt2;
//----+ Insertion of integer variables and GETTING ALREADY CALCULATED BARS
   int limit, MaxBar, bar, counted_bars = IndCounted;
//----+ REMEMBERING THE AMOUNT OF ALL BARS OF THE CHART
   IndCounted = IBARS - 1;
//---- defining the number of the oldest bar,   
//     starting from which new bars will be recalculated
   limit = IBARS - counted_bars - 1; 
//---- defining the number of the oldest bar, 
//     starting from which new bars will be recalculated
   MaxBar = IBARS - 1 - (period0 + period1 + period2); 
//---- initialization of zero 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = IBARS - 1; bar >= 0; bar--)
         {
           Ind_Buffer0[bar] = 0.0;
           Ind_Buffer1[bar] = 0.0;
           Ind_Buffer2[bar] = 0.0;
         }
     }
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt1 calculation based on the external 
       // variable period1
       Ind_Buffer1[bar] = Resalt1;
     }
//----+ THE SECOND CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt2 calculation  
       // based on the values of the buffer Ind_Buffer1[] and the external variable period2
       Ind_Buffer2[bar] = Resalt2;
     }
//----+ THE MAIN CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= 0; bar--)
     {
       // Here code of the variable Resalt0 calculation 
       // based on the values of the buffer Ind_Buffer2[] and the external variable period0
       Ind_Buffer0[bar] = Resalt0;
     }
   return(0);
  }
//+------------------------------------------------------------------+


ここであることに配慮する必要があります。ゼロバーを複数回再計算するとき、計算サイクルの最初でコードを初期状態(記事)に戻すための一部の変数値を記憶しているインディケータがあります。Expert Advisor では最後の2行を削除したあと、この想起が1番目のバーではなく、ゼロバーで起こります。通常そのようなインディケータには計算サイクルの最初に次のようなコードのフラグメントがあります。

// Saving the variables values
if(bar == 1)
    if(((limit == 1) && (time == Time[2])) || (limit > 1))
      {
        time = Time[2];
        // These variables are not interesting for us
        PRICE = price;
        TREND = trend;
        RESALT = Resalt;
      }
//+------------------------------------------------------------------+

このフラグメントは最初のバーではなくゼロバーで変数値を保存するために変更します。'1' はすべて '0'、'2' -'1'ずつ、で置き換えます。そしてコードが現チャートで処理をするのでなければ、時系列配列への参照も変更します

time = Time[1];


into

time = iTime(symbol, timeframe, 1);


結果、得るのが以下のフラグメントです。

// Saving variables values
if(bar == 0)
    if(((limit == 0) && (time == iTime(symbol, timeframe, 1))) || (limit > 0))
      {
        time = iTime(symbol, timeframe, 1);
        PRICE = price;
        TREND = trend;
        RESALT = Resalt;
      }
//+------------------------------------------------------------------+

インディケータコードには私が作成した XXXSeries() のような平滑化関数が入っています。そういった関数を持つフラグメントをEA コードで使用するには、その関数をそれらの EA 類似体と置き換えます。



おわりに


現時点では、提供しているこの形式でインディケータコードをコードに変換するアルゴリズムはまだまだ洗練されていないのは疑う余地がありませんが、本稿の目的はこの処理を微に入り細に入り説明することではありません。本稿の主要な考えは、インディケータの一般的見解を提示し、二次詳細で過負荷にすることなくこの上なくシンプルにコード変換の一般的考えを分析することです。われわれはこの目的を達成したと思います。次稿では、Expert Advisor の一般的ストラクチャとインディケータ関数のストラクチャスキームを分析します。

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

添付されたファイル |
IndicatorPlan1.mq4 (3.03 KB)
SMI.MQ4 (4.87 KB)
SMI_New.MQ4 (5.93 KB)
インディケータコードから Expert Advisor コードへの変換Expert Advisor およびインディケータ関数の一般的スキーム インディケータコードから Expert Advisor コードへの変換Expert Advisor およびインディケータ関数の一般的スキーム
本稿はインディケータコードを Expert Advisor コードへ変換し、カスタムインディケータの呼び出しなく、Expert Advisor 内で必要なインディケータ値を計算するためのプログラムコード全体を使って Expert Advisor を書く方法に特化して述べます。本稿は Expert Advisor 変更とカスタムインディケータを基にしたインディケータ関数構築の考えを提供します。対象とする読者はすでに MQL4 言語でのプログラム経験をお持ちの方です。
Forex トレーディングのイロハ Forex トレーディングのイロハ
金融市場を扱うということはまずトレード処理を意味します。ごく幼いころから、われわれは皆、何を売り、買うべきかということについて直観的考えを持っています。ですが Forex トレーディングは何か特別なものです。本稿ではいくつか用語の説明が必要な考えを取り上げます。またそういう語に対応する MQL 4 fの関数についても考察します。
Expert Advisorのオーダーメード - トレーダー向けマニュアル Expert Advisorのオーダーメード - トレーダー向けマニュアル
トレーダーが全員プログラマーというわけではありません。そしてプログラマーが全員優秀というわけではありません。自分のシステムを自動化する必要がある場合、何をすべきでしょうか?MQL4 を学ぶのに時間も欲求もなしで?
トリコロールインディケータとインディケータを書くことを最大限シンプル化するいくつかの機会 トリコロールインディケータとインディケータを書くことを最大限シンプル化するいくつかの機会
本稿では、ビジュアルトレーディングのためにインディケータの情報値を増やすことの意味についていくらか説明します。私はインディケータを構築するために別のタイムフレームからのデータを使用するトリコロールインディケータの実行を分析してし、記事"Effective Averaging Algorithms with Minimal Lag: Use in Indicators"で述べられているインディケータのライブラリについても詳しく説明します。