English Русский 中文 Español Deutsch Português
高速で再描画しない ZigZag の書き方

高速で再描画しない ZigZag の書き方

MetaTrader 4 | 22 4月 2016, 09:52
4 552 0
Candid
Candid

はじめに

zigzag チャートの可能なアルゴリズムすべての中で、私が『減速レベルのブレークスルーで切り替わる Zigzag』と名付けるあるクラスを区別します。このクラスは全体的にあるいは部分的に既存の ZigZag のほとんどを含みます。クラス名自体は、実は、アルゴリズムのテンプレートを表しています。そこからインディケータを作るには、減速レベルを検出する関数を追加するだけで十分です。そのような関数のアルゴリズムの多様性は、将来 ZigZag を書く人の想像で制限されるだけです。



一般的方法

まず、インディケータを書く一般的方法を作ってみます。すなわち、

-任意のインディケータ(任意の EA 同様)関数n start() はコールバアク関数、すなわち特定のイベントを処理するために呼ばれる関数、を代表します。すなわち、ティックを処理します。

-インディケータを書く対象は、原則として、1つあるいは複数の市場特性の計算です。計算に必要な補助的な量と共に、それらは所定のインディケータの主要な変数セットを形成します。特定時刻にそれら主要変数の一連の値としてインディケータの状態 を定義します。この定義を基に、以下を述べることができます。

  • 新規ティックにおける変数の新しい値を計算し、関数 start() はインディケータの新しい状態を計算します。
  • このため、実際、関数 start() はある状態から別の状態へのインディケータを移すオペレータです。

-これらの点では、インディケータを書く過程は、その状態(状態変数)を述べて一連の量を判断すること、また新規ティック到来時にインディケータを新しい状態に移すオペレータを書くことに対し、それ自体を減らします。状態変数の初期化はインディケータアルゴリズムの基本部分となります。このすべてがどのように行われるのか、特定タイプのZigZag を例に説明していきます。



どの ZigZags が問題になっているのでしょうか?

上で述べられているように、本稿では、減速レベルをブレークスルーする際の ZigZag 切り替えに興味を向けます。では、『減速レベル』とは何でしょうか?価格がその頂点から H ポイント分移動するとき、頂点が修正される ZigZag を書きたいと思っていると仮定します。頂点を修正する、とは ZigZag のセグメント方向を逆に切り替えることを意味します。最小値を修正し、今上昇セグメントにあります。不完全な上昇セグメントの価格時間最大値に対する変数 TempMax を取り入れます。価格が次のレベルをブレークスルーしたら、この最大値を修正し(そして方向を切り替え)ます。

SwitchLevel = TempMax - H ×Point

切り替え前に時間最大が更新される場合、SwitchLevel の新しい値を計算する必要があります。よって、SwitchLevel は時間最大に続き、それより H ポイント後ろにきます。

下降セグメントでも状況はまったく対称的です:SwitchLevel が時間最小(TempMin)に続き、同じ H ポイント分あとにきます。ただしここでは以下となります。

SwitchLevel = TempMin + H × Point

実際、作成しようとしている ZigZag に対する減速レベルを計算するアルゴリズムを説明したばかりです。明らかに、それが唯一の可能なアルゴリズムではありません。たとえば、減速レベルとなるチャンネルの上方/下方境界を考慮するなら、チャンネル計算の方法があるだけの数のZigZag また、よく考えると、私が知ってい ZigZag のる絶対多数は、完全にまたは部分的に検討中のクラスに含まれています。ですがすべてではありません。たとえば、ウィリアムズのf楽樽で計算される ZigZag はこの種類には含まれません。



ZigZag モデル

次に ZigZag 状態の変数を決定します。

まずは現行セグメントの方向です。対応する変数をUpZ と名付け、上昇セグメントについての値 に、 を下降セグメントに割り当てます。

明らかに、上記で紹介したリスト TempMax および TempMin を追加します。また、その時間座標も追加します。ただしここで、測定単位を定義するのにある程度の自由度を得ます。時間座標として、チャートの冒頭から始まるバー番号を使用します。すなわち、MT4 で受け取られるのと逆の採番システムを使うのです。これはどちらもコードをシンプルにし、実行率を上げます。よって、リストは変数 TempMaxBarTempMinBarで補充されます。

チャート上で ZigZag を描き、それをいくらか使用するという両方を計画します。よって最終的な修正済み ZigZag 頂点の座標:CurMaxCurMaxBarCurMinCurMinBar、をリストに追加します。

それがリスト用のものです。特定の ZigZag を個人的に書く人は、この ZigZag で行おうとしている事柄で自由にリストを補充できます。たとえば、先行頂点の座標:PreMax、PreMaxBar、PreMin、 PreMinBar、を追加するのが妥当であると判ることもありえます。または、先行頂点の提議済み番号の座標を、その場合は配列を用いて、追加する必要があるかもしれません。



遷移オペレータ

提案の方法では、ZigZag に対する遷移オペレータを書くことはかなり簡単なタスクです。関心ある ZigZag クラス定義をMQL4 に解釈するだけです。以下がその記述です。

// First, process the case of an up-segment
    if (UpZ) {
// Check whether the current maximum has changed
      if (High[pos]>TempMax) {
// If yes, then correct the corresponding variables
        TempMax = High[pos];
        TempMaxBar = Bars-pos;  // Here switching to direct numbering
      } else {
// If not, then check whether the slowing level has been broken through
        if (Low[pos]<SwitchLevel()) {
// If yes, then fix the maximum
          CurMax = TempMax;
          CurMaxBar = TempMaxBar;
// And draw a peak
          ZZ[Bars-CurMaxBar]=CurMax;  // Here switching to reverse numbering
// Correct the corresponding variables
          UpZ = false;
          TempMin = Low[pos];
          TempMinBar = Bars-pos;  // Here switching to direct numbering
        }
      }
    }  else {
// Now processing the case of down-segment
// Check whether the current minimum has changed
      if (Low[pos]<TempMin) {
// If yes, then correct the corresponding variables
        TempMin = Low[pos];
        TempMinBar = Bars-pos;  // Here switching to direct numbering
      } else {
// If not, then check whether the slowing level has been broken through
        if (High[pos]>SwitchLevel()) {
// If yes, then fix the minimum
          CurMin = TempMin;
          CurMinBar = TempMinBar;
// And draw a peak
          ZZ[Bars-CurMinBar]=CurMin;  // Here switching to reverse numbering
// Correct the corresponding variables
          UpZ = true;
          TempMax = High[pos];
          TempMaxBar = Bars-pos;  // Here switching to direct numbering
       }
      }
    }

遷移オペレータは準備できました。これでいつでもインディケータの状態変数を参照することができます。

そのようなオペレータは、ZigZag を描くエラーとして認識されるという特殊な性質があります。以下のフラグメントをもっと細かく考察します。

      if (High[pos]>TempMax) {
// If yes, then correct the corresponding variables
        TempMax = High[pos];
        TempMaxBar = Bars-pos;  // Here switching to direct numbering
      } else {
// If not, then check whether the slowing level has been broken through
        if (Low[pos]<SwitchLevel()) {
// If yes, then fix the maximum
          CurMax = TempMax;
          CurMaxBar = TempMaxBar;

if - elseのペアを使用すること は、 TempMax を持つバーの安値 が考慮されることを意味します。この価格が次の修正済み最小値を下回ると判る状況は ZigZag を描くエラーとして認識される可能性があります。それはほんとうにエラーなのでしょか?

履歴上の作業とリアルタイムの作業を考慮することは、同じことです。私はこれはエラーではないという意見です。実際、タイムフレーム内部では、履歴上で以前に何が起こったか、バーの最大値または最小値を知ることは決してありません。ここで if - else の構造を使用することは、意識的な決断をすることを意味します。われわれは勢いを好みます。それは、上昇セグメントについて最小値を、下降セグメントについては最大値を犠牲にすることを意味します。タイムフレームが小さいほど、このジレンマが発生する頻度が低くなる、というのは理にかなっています。

別のフラグメントにはコメントが必要です。

// Correct the corresponding variables
          UpZ = false;
          TempMin = Low[pos];
          TempMinBar = Bars-pos;  // Here switching to direct numbering
        }
      }

ここでは実際、時間最小の確認を開始するポイントは、セグメント間での切り替えタイミングに対して設定されます。提供されている例ではそれは正当ですが、一般的にはそれをしてはいけません。修正された最大値から現在のポジション(すなわち、切り替えの瞬間まで)まで最小間隔に対して一時的な最小値を設定するのがより妥当だと思われます。そのコードは以下のように書かれます。

   // Correct the corresponding variables
          UpZ = false;
          TempMinBar = CurMaxBar+1;
          TempExtPos = Bars - TempMinBar;  // Here switching to reverse numbering
          TempMin = Low[TempExtPos];
          for (i=TempExtPos-1;i>=pos;i--) {
            if (Low[i]<TempMin) {
              TempMin = Low[i];
              TempMinBar = Bars-i;  // Here switching to direct numbering
            }
          }

ここで、最小値が修正されたバーの安値は検討から再び外れます。

これら2件の注意事項も下降セグメントの処理に関連しています。



インディケータ

それを動作させるには、インディケータの完成が残っているだけです。init()deinit()にコメントを付ける必要はありません。すべてひじょうに明確で標準的なものです。ただし、関数 start() については重要な判断をします。われわれは完了したバーのみ処理します。この主な理由は、それによりシンプルで簡潔なコード構造を実現できるためです。

それについてはもう一つ重要な配慮があります。トレーディングシステムにおいて本格的な作業をすることは履歴上で統計を収集することです。この統計は、リアルタイムで取得される特性が完全に履歴で取得されるものと対応している場合にのみ有効(正しい)です。実ティックの履歴は持ちません。よって、完了バーのみリアルタイムで処理することで、それを完全に達成することができるのです。ディレイを削減するためにできる最大のことは、M1 まで小さなタイムフレームに行くことです。

その他基本的な特性は関数 IndicatorCounted() を使わないことです。そうする主な理由は、使用されているコードは別の重要なアクションを必要とすることです。それは、インディケータの状態変数の初期化です。これは関数n init() では行えません。というのも、直接の採番には履歴を吸い上げるときインディケータを再計算する必要があり、そのため、状態変数を再初期化する必要があるためです。関数 init() は履歴吸い上げのときは起動されません。

よって、もう一つ『標準』関数 Reset() を追加する必要があります。最終的には、IndicatorCounted() を使用したいという思いは、このタイプのインディケータに必要な再計算チェックを妨げるとして役に立ちません。このチェックは以下のように実装されます。

int start() {
//  Work with completed bars only
  if (Bars == PreBars) return(0);  
//  Check whether there are enough bars on the chart
  if (Bars < MinBars) {
    Alert(": Not enough bars on the chart");
    return(0);
  }  
//  If the history was not pumped, make calculations for the bar just completed
  if (Bars-PreBars == 1 && BarTime==Time[1]) StartPos = 1;
//  Otherwise, count the number of bars specified in function Reset() 
  else StartPos = Reset();
// Modify check variables
  PreBars = Bars;  
  BarTime=Time[0];
// Cycle on history
  for (pos=StartPos;pos>0;pos--) {

関数 Reset() は以下のように表記されます。

int Reset() {
  if (MinBars == 0) MinBars = Bars-1;
  StartPos = MinBars;
  PreBars = 0;
  BarTime = 0;
  dH = H*Point;
  UpZ = true;
  TempMaxBar = Bars-StartPos;
  TempMinBar = Bars-StartPos;
  TempMax = High[StartPos];
  TempMin = Low[StartPos];
  StartPos++;
  return(StartPos);
}

ここで、追加の変数 dH に特に注意を払います。それに対しては、価格スケールに変換されたZigZag 切り替え閾値(H)を割り当てます。ある疑問が生じるでしょう。:なぜ UpZ = で、ではないのか? 答えは簡単です。:セグメントの小さい数字のあと、インディケータは、独立した初期値UpZ の同じグラフとなるのです。

最終的に、減速レベルの計算は以下のようになります。

double SwitchLevel() {
  double SwLvl;
  if (UpZ) SwLvl = TempMax - dH;
  else SwLvl = TempMin + dH;
  return(SwLvl);
}

ここではすべて明白です。



おわりに

ZigZag を書くテンプレート ZZTemplate は本稿に添付があります。必要なことは、関数 SwitchLevel() に必要なコードを追加することだけです。テンプレートをここで例として使用されている ZigZag に変えるには、以下の行とそこにつけられているコメントを見つけるだけです。

//extern int H = 33;

//double dH;

//  dH = H*Point;

//  if (UpZ) SwLvl = TempMax - dH;
//  else SwLvl = TempMin + dH;

ZigZag スピートに関する最後の注意事項です。テンプレートとは一般性を意味します。また、われわれはできる限り透明なストラクチャを取得したいと思っています。私は、もっとも具体的な実装は追加でその動作の最適化を強化することだと思います。

一般的な推奨事項は以下です。:可能であれば、if オペレータに処理を設定する。最適化の例として(しかし理想的なモデルではありません)本稿で使用されているの代替実装である添付のインディケータ HZZ をご覧ください。問題を単純化することで、関数 SwitchLevel() といくつかの状態変数を使用しないでおくことができます。小さなボーナスとして、ファイルに ZigZag 頂点を書くHZZ と、ZigZag の統計的特性を『オンザフライ』で行うチェックを追加しました。

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

添付されたファイル |
HZZ.mq4 (4.22 KB)
ZZTemplate.mq4 (5.67 KB)
怠慢は、進歩またはグラフィックスとインタラクティブに作業する方法への刺激 怠慢は、進歩またはグラフィックスとインタラクティブに作業する方法への刺激
トレンドライン、フィボナッチレベル、チャートにマニュアルで入れられたアイコンとインタラクティブに動作するインターフェース用インディケータ。それにより、フィボナッチレベルのゾーンを色付きで描画し、価格がトレンドラインを交差する瞬間を表示し、『価格レベル』オブジェクトを管理することができます。
MQL4 によるHTML チュートリアル MQL4 によるHTML チュートリアル
HTML は今や広く普及している文書タイプです。MetaTrader 4 クライアントターミナルによって、ステートメント、検証レポート、最適化レポートを .htm ファイルとして保存することが可能です。MQL4 プログラムではそのようなファイルから情報を得ることが必要な場合があります。本稿では、HTML からタグ構成や内容を取得する方法のバリエーションの一つを説明します。
コメントによってコード内エラーを判断する方法 コメントによってコード内エラーを判断する方法
本稿では、コメントを基に MQL4 コード内のエラーを検索する方法について説明します。この方法は、ほどほどに大きなコード内のエラーによって生じるコンパイル中に問題が発生する場合に便利であることが判ります。