View difference between Paste ID: vpxeAGpj and 5j7EjYEp
SHOW: | | - or go back to the newest paste.
1-
// hyrKagiZag.mq4
1+
// hyrKagiZag.mq5 ( MT5半自動移植版 by Claude )
2-
//  Copyright 2026 hyrolean
2+
// Copyright 2026 hyrolean
3-
//===========================================================================
3+
// Converted from URL:: https://pastebin.com/5j7EjYEp
4-
//----- properties -----
4+
//=======================================================================
5
// ----- properties -----
6-
#property link "https://pastebin.com/5j7EjYEp"
6+
7-
#property version "1.12"
7+
#property link      "https://pastebin.com/vpxeAGpj"
8-
#property strict
8+
#property version   "1.13"
9
10
  // version 1.13
11
  //  - fixed atrArray direction to match Series price arrays (ArraySetAsSeries true)
12-
  
12+
13
  // version 1.12
14
  //  - added ArraySetAsSeries() codes to OnCalculate()
15
16
  // version 1.11
17
  //  - bugfix on updating new extremum values among previous-current timelines
18
19
  // version 1.10
20-
#property indicator_buffers 1
20+
21
22
23-
//----- parameters -----
23+
24-
input double ShiftPrice = 100 ;      // Shift price in points
24+
#property indicator_buffers 3
25-
input bool ATRMultiplying = true ;   // ATR shift price multiplying enabled
25+
#property indicator_plots   1
26-
input double ATRMultiplier = 0.025 ; // ATR shift price multiplier
26+
#property indicator_type1   DRAW_SECTION
27-
input int ATRPeriod = 14 ;           // ATR period
27+
28
#property indicator_width1  1
29-
//----- buffers -----
29+
30
// ----- parameters -----
31
input double ShiftPrice   = 100;    // Shift price in points
32
input bool   ATRMultiplying = true; // ATR shift price multiplying enabled
33
input double ATRMultiplier  = 0.025;// ATR shift price multiplier
34-
//----- global -----
34+
input int    ATRPeriod      = 14;   // ATR period
35-
int ExtLevel=3;
35+
36
// ----- buffers -----
37-
//---------------------------------------------------------------------------
37+
38
double ExtHighBuffer[];
39
double ExtLowBuffer[];
40-
   // number of indicator buffers
40+
41-
   IndicatorBuffers(3); // Kagizag, High, Low
41+
// ----- global -----
42-
   // setup the drawing style of primary buffer as section
42+
int ExtLevel = 3;
43-
   SetIndexStyle(0,DRAW_SECTION);
43+
int atrHandle = INVALID_HANDLE;
44-
   // setup buffers
44+
45-
   SetIndexBuffer(0,ExtKagizagBuffer);
45+
//-----------------------------------------------------------------------
46-
   SetIndexBuffer(1,ExtHighBuffer);
46+
47-
   SetIndexBuffer(2,ExtLowBuffer);
47+
48-
   SetIndexEmptyValue(0,0.0);
48+
    // number of indicator buffers
49-
   // setup the indicator short name
49+
    IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
50-
   if(ATRMultiplying) {
50+
51-
     IndicatorShortName("KagiZag("+string(ShiftPrice)+","
51+
    // setup buffers
52-
       +string(ATRMultiplier)+","+string(ATRPeriod)+")");
52+
    SetIndexBuffer(0, ExtKagizagBuffer, INDICATOR_DATA);
53-
   }else {
53+
    SetIndexBuffer(1, ExtHighBuffer,    INDICATOR_CALCULATIONS);
54-
     IndicatorShortName("KagiZag("+string(ShiftPrice)+")");
54+
    SetIndexBuffer(2, ExtLowBuffer,     INDICATOR_CALCULATIONS);
55-
   }
55+
    ArraySetAsSeries(ExtKagizagBuffer, true);
56
    ArraySetAsSeries(ExtHighBuffer, true);
57-
   return(INIT_SUCCEEDED);
57+
    ArraySetAsSeries(ExtLowBuffer, true);
58
59-
//---------------------------------------------------------------------------
59+
    // draw style
60
    PlotIndexSetInteger(0, PLOT_DRAW_TYPE,  DRAW_SECTION);
61
    PlotIndexSetDouble (0, PLOT_EMPTY_VALUE, 0.0);
62
    PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, 0);
63-
                const double &open[],
63+
64-
                const double &high[],
64+
    // indicator short name
65-
                const double &low[],
65+
66-
                const double &close[],
66+
        IndicatorSetString(INDICATOR_SHORTNAME,
67-
                const long& tick_volume[],
67+
            "KagiZag(" + string(ShiftPrice) + "," +
68-
                const long& volume[],
68+
            string(ATRMultiplier) + "," + string(ATRPeriod) + ")");
69-
                const int& spread[])
69+
    } else {
70
        IndicatorSetString(INDICATOR_SHORTNAME,
71-
  int i, pos, opos=-1, numExt, extMode=0 ;
71+
            "KagiZag(" + string(ShiftPrice) + ")");
72-
  double curLow=0.0, curHigh=0.0 ;
72+
73-
  double deltaLow=0.0, deltaHigh=0.0 ;
73+
74-
  double shift = ShiftPrice*Point ;
74+
    // ATR handle
75-
  ArraySetAsSeries(high,true);
75+
76-
  ArraySetAsSeries(low,true);
76+
        atrHandle = iATR(_Symbol, PERIOD_CURRENT, ATRPeriod);
77-
  ArraySetAsSeries(open,true);
77+
        if(atrHandle == INVALID_HANDLE) {
78-
  if(prev_calculated==0) { // 初期状態
78+
            Print("Failed to create ATR handle");
79-
    InitializeAll();
79+
            return(INIT_FAILED);
80-
    pos = rates_total ;
80+
81-
  }else {
81+
82-
    // 近傍の有効頂点数(ExtLevelまでの)を数える
82+
83-
    for(i=numExt=0;numExt<ExtLevel&&i<rates_total;i++) {
83+
    return(INIT_SUCCEEDED);
84-
      if(ExtKagizagBuffer[i]!=0.0)
84+
85-
        numExt++;
85+
86
//-----------------------------------------------------------------------
87-
    if(!numExt) {
87+
void OnDeinit(const int reason)
88-
      // 頂点ナシ(初期状態)
88+
89-
      InitializeAll();
89+
    if(atrHandle != INVALID_HANDLE)
90-
      pos = rates_total ;
90+
        IndicatorRelease(atrHandle);
91-
    }else {
91+
92-
      // 頂点がみつかった
92+
93-
      pos = i-1 ;
93+
//-----------------------------------------------------------------------
94-
      if(ExtLowBuffer[pos]!=0.0) { // 頂点は、谷に位置する
94+
95-
        curLow = ExtLowBuffer[pos] ;
95+
96-
        extMode = 1 ; // 山を見つけるモード
96+
97-
      }else { // 頂点は、山に位置する
97+
                const double   &open[],
98-
        curHigh = ExtHighBuffer[pos] ;
98+
                const double   &high[],
99-
        extMode = -1 ; // 谷を見つけるモード
99+
                const double   &low[],
100-
      }
100+
                const double   &close[],
101-
      // 頂点再列挙の事前処理として近傍の頂点データを抹消しておく
101+
                const long     &tick_volume[],
102-
      for(i=pos-1;i>=0;i--) {
102+
                const long     &volume[],
103-
        ExtKagizagBuffer[i]=0.0;
103+
                const int      &spread[])
104-
        ExtLowBuffer[i]=0.0;
104+
105-
        ExtHighBuffer[i]=0.0;
105+
    int    i, pos, opos = -1, numExt, extMode = 0;
106-
      }
106+
    double curLow = 0.0, curHigh = 0.0;
107
    double deltaLow = 0.0, deltaHigh = 0.0;
108
    double shift = ShiftPrice * _Point;
109-
  // メイン処理
109+
110-
  for(i=pos-1;i>=0;i--) {
110+
    ArraySetAsSeries(high,true);
111
    ArraySetAsSeries(low,true);
112-
      if(rates_total-i<ATRPeriod) continue;
112+
    ArraySetAsSeries(open,true);
113-
      shift = ShiftPrice * iATR(NULL,0,ATRPeriod,i) * ATRMultiplier ;
113+
114
    if(prev_calculated == 0) {
115-
    switch(extMode) { // 頂点検出モード(山と谷のどちらのピークであるか)
115+
        // 初回計算
116-
    case 0: // どちらのモードでもない(初期状態)
116+
        InitializeAll();
117-
      deltaHigh = high[i]-open[pos-1] ;
117+
        pos = rates_total;
118-
      deltaLow = open[pos-1]-low[i] ;
118+
    } else {
119-
      if(deltaHigh>=deltaLow) { // 上昇気味
119+
        // 直近の極値(ExtLevel個)を探して再計算開始位置を決定
120-
        if(deltaHigh>=shift) { // 初期価格から上にシフト
120+
        for(i = numExt = 0; numExt < ExtLevel && i < rates_total; i++) {
121-
          curLow = open[pos-1] ;
121+
            if(ExtKagizagBuffer[i] != 0.0)
122-
          ExtKagizagBuffer[pos-1]=curLow;
122+
                numExt++;
123-
          ExtLowBuffer[pos-1]=curLow;
123+
124-
          curHigh = high[i] ;
124+
        if(!numExt) {
125-
          pos = i ;
125+
            // 極値が見つからない(初回相当)
126-
          ExtKagizagBuffer[pos] = curHigh ;
126+
            InitializeAll();
127-
          ExtHighBuffer[pos] = curHigh ;
127+
            pos = rates_total;
128-
          extMode = -1 ; // 谷を見つけるモードに移行
128+
        } else {
129
            // 極値が見つかった
130-
      }else { // 下降気味
130+
            pos = i - 1;
131-
        if(deltaLow>=shift) { // 初期価格から下にシフト
131+
            if(ExtLowBuffer[pos]!= 0.0) {
132-
          curHigh = open[pos-1] ;
132+
                // 直近極値は安値
133-
          ExtKagizagBuffer[pos-1]=curHigh;
133+
                curLow  = ExtLowBuffer[pos];
134-
          ExtHighBuffer[pos-1]=curHigh;
134+
                extMode = 1; // 安値を追いかけるモード
135-
          curLow = low[i] ;
135+
            } else {
136-
          pos = i ;
136+
                // 直近極値は高値
137-
          ExtKagizagBuffer[pos] = curLow ;
137+
                curHigh  = ExtHighBuffer[pos];
138-
          ExtLowBuffer[pos] = curLow ;
138+
                extMode  = -1; // 高値を追いかけるモード
139-
          extMode = 1 ; // 山を見つけるモードに移行
139+
            }
140
            // 直前の確定済み極値より新しいバッファデータをリセット
141-
      }
141+
            for(i = pos - 1; i >= 0; i--) {
142-
      break;
142+
                ExtKagizagBuffer[i] = 0.0;
143-
    case 1: // 山を見つけるモード ( 谷側に価格が進行中 )
143+
                ExtLowBuffer[i]     = 0.0;
144-
      deltaHigh = high[i] - curLow ;
144+
                ExtHighBuffer[i]    = 0.0;
145-
      deltaLow = curLow - low[i] ;
145+
            }
146-
      if(deltaHigh>deltaLow) { // 上昇気味
146+
147-
        if(deltaHigh>=shift) { // 谷底から上にシフト
147+
148-
          curHigh = high[i] ;
148+
149-
          opos = pos ;
149+
    double atrArray[];
150-
          pos = i ;
150+
151-
          ExtKagizagBuffer[pos] = curHigh ;
151+
        if(CopyBuffer(atrHandle, 0, 0, pos, atrArray) <= 0)
152-
          ExtHighBuffer[pos] = curHigh ;
152+
            return(0);
153-
          extMode = -1 ; // 谷を見つけるモードに移行
153+
        ArraySetAsSeries(atrArray, true); // high/low/openと方向を揃える(index 0=最新)
154-
          break;
154+
155
156-
      }
156+
    // メインループ
157-
      if(deltaLow>=0) { // 最安値更新
157+
    for(i = pos - 1; i >= 0; i--) {
158-
        curLow = low[i] ;
158+
        if(ATRMultiplying) {
159-
        if(opos>=0) { // ひとつ前のポジション(山)が有効
159+
            if(rates_total - i < ATRPeriod) continue;
160-
          int ih = iHighest(NULL,0,MODE_HIGH,opos-pos,pos) ;
160+
            shift = ShiftPrice * atrArray[i] * ATRMultiplier;
161-
          if(curHigh<=high[ih]) { // 現在からひとつ前までの最高値が前の山より高い
161+
162-
            // ひとつ前のポジション(山)を更新
162+
163-
            curHigh=high[ih];
163+
        switch(extMode) {
164-
            ExtKagizagBuffer[opos] = 0.0 ;
164+
        case 0: // 初回(まだどちらのモードでもない)
165-
            ExtHighBuffer[opos]=0.0;
165+
            deltaHigh = high[i] - open[pos - 1];
166-
            opos=ih;
166+
            deltaLow  = open[pos - 1] - low[i];
167-
            ExtKagizagBuffer[ih]=curHigh;
167+
            if(deltaHigh >= deltaLow) { // 上方向優先
168-
            ExtHighBuffer[ih]=curHigh;
168+
                if(deltaHigh >= shift) {
169-
          }
169+
                    curLow  = open[pos - 1];
170
                    ExtKagizagBuffer[pos - 1] = curLow;
171-
        if(opos!=pos) ExtKagizagBuffer[pos]=0.0;
171+
                    ExtLowBuffer[pos - 1]     = curLow;
172-
        ExtLowBuffer[pos]=0.0;
172+
                    curHigh = high[i];
173-
        pos=i;
173+
                    pos     = i;
174-
        ExtKagizagBuffer[pos]=curLow;
174+
                    ExtKagizagBuffer[pos] = curHigh;
175-
        ExtLowBuffer[pos]=curLow;
175+
                    ExtHighBuffer[pos]    = curHigh;
176-
      }
176+
                    extMode = -1; // 高値を追いかけるモードへ
177-
      break;
177+
                }
178-
    case -1: // 谷を見つけるモード ( 山側に価格が進行中 )
178+
            } else { // 下方向優先
179-
      deltaHigh = high[i] - curHigh ;
179+
                if(deltaLow >= shift) {
180-
      deltaLow = curHigh - low[i] ;
180+
                    curHigh = open[pos - 1];
181-
      if(deltaLow>deltaHigh) { // 下降気味
181+
                    ExtKagizagBuffer[pos - 1] = curHigh;
182-
        if(deltaLow>=shift) { // 山頂から下にシフト
182+
                    ExtHighBuffer[pos - 1]    = curHigh;
183-
          curLow = low[i] ;
183+
                    curLow = low[i];
184-
          opos = pos ;
184+
                    pos    = i;
185-
          pos = i ;
185+
                    ExtKagizagBuffer[pos] = curLow;
186-
          ExtKagizagBuffer[pos] = curLow ;
186+
                    ExtLowBuffer[pos]     = curLow;
187-
          ExtLowBuffer[pos] = curLow ;
187+
                    extMode = 1; // 安値を追いかけるモードへ
188-
          extMode = 1 ; // 山を見つけるモードに移行
188+
                }
189-
          break;
189+
            }
190
            break;
191-
      }
191+
192-
      if(deltaHigh>=0) { // 最高値更新
192+
        case 1: // 安値を追いかけるモード(高値への転換待ち)
193-
        curHigh = high[i] ;
193+
            deltaHigh = high[i] - curLow;
194-
        if(opos>=0) { // ひとつ前のポジション(谷)が有効
194+
            deltaLow  = curLow  - low[i];
195-
          int il = iLowest(NULL,0,MODE_LOW,opos-pos,pos) ;
195+
            if(deltaHigh > deltaLow) { // 上方向
196-
          if(curLow>=low[il]) { // 現在からひとつ前までの最安値が前の谷より低い
196+
                if(deltaHigh >= shift) { // 高値側へ転換
197-
            // ひとつ前のポジション(谷)を更新
197+
                    curHigh = high[i];
198-
            curLow=low[il];
198+
                    opos    = pos;
199-
            ExtKagizagBuffer[opos] = 0.0 ;
199+
                    pos     = i;
200-
            ExtLowBuffer[opos]=0.0;
200+
                    ExtKagizagBuffer[pos] = curHigh;
201-
            opos=il;
201+
                    ExtHighBuffer[pos]    = curHigh;
202-
            ExtKagizagBuffer[il]=curLow;
202+
                    extMode = -1; // 高値を追いかけるモードへ
203-
            ExtLowBuffer[il]=curLow;
203+
                    break;
204-
          }
204+
                }
205
            }
206-
        if(opos!=pos) ExtKagizagBuffer[pos]=0.0;
206+
            if(deltaLow >= 0) { // 安値更新
207-
        ExtHighBuffer[pos]=0.0;
207+
                curLow = low[i];
208-
        pos=i;
208+
                if(opos >= 0) { // 直前の高値ピーク(高値)を更新確認
209-
        ExtKagizagBuffer[pos]=curHigh;
209+
                    int ih = IndexOfHighest(high, pos, opos);
210-
        ExtHighBuffer[pos]=curHigh;
210+
                    if(curHigh <= high[ih]) {
211-
      }
211+
                        // 更新前の直前ピーク(高値)より現在の高値側が高い
212-
      break;
212+
                        curHigh = high[ih];
213
                        ExtKagizagBuffer[opos] = 0.0;
214
                        ExtHighBuffer[opos]    = 0.0;
215-
  return(rates_total);
215+
                        opos = ih;
216
                        ExtKagizagBuffer[ih] = curHigh;
217-
//---------------------------------------------------------------------------
217+
                        ExtHighBuffer[ih]    = curHigh;
218
                    }
219
                }
220-
   ArrayInitialize(ExtKagizagBuffer,0.0);
220+
                if(opos != pos) ExtKagizagBuffer[pos] = 0.0;
221-
   ArrayInitialize(ExtHighBuffer,0.0);
221+
                ExtLowBuffer[pos] = 0.0;
222-
   ArrayInitialize(ExtLowBuffer,0.0);
222+
                pos = i;
223
                ExtKagizagBuffer[pos] = curLow;
224-
//---------------------------------------------------------------------------
224+
                ExtLowBuffer[pos]     = curLow;
225
            }
226
            break;
227
228
        case -1: // 高値を追いかけるモード(安値への転換待ち)
229
            deltaHigh = high[i] - curHigh;
230
            deltaLow  = curHigh - low[i];
231
            if(deltaLow > deltaHigh) { // 下方向
232
                if(deltaLow >= shift) { // 安値側へ転換
233
                    curLow = low[i];
234
                    opos   = pos;
235
                    pos    = i;
236
                    ExtKagizagBuffer[pos] = curLow;
237
                    ExtLowBuffer[pos]     = curLow;
238
                    extMode = 1; // 安値を追いかけるモードへ
239
                    break;
240
                }
241
            }
242
            if(deltaHigh >= 0) { // 高値更新
243
                curHigh = high[i];
244
                if(opos >= 0) { // 直前の安値ピーク(安値)を更新確認
245
                    int il = IndexOfLowest(low, pos, opos);
246
                    if(curLow >= low[il]) {
247
                        // 更新前の直前ピーク(安値)より現在の安値側が低い
248
                        curLow = low[il];
249
                        ExtKagizagBuffer[opos] = 0.0;
250
                        ExtLowBuffer[opos]     = 0.0;
251
                        opos = il;
252
                        ExtKagizagBuffer[il] = curLow;
253
                        ExtLowBuffer[il]     = curLow;
254
                    }
255
                }
256
                if(opos != pos) ExtKagizagBuffer[pos] = 0.0;
257
                ExtHighBuffer[pos] = 0.0;
258
                pos = i;
259
                ExtKagizagBuffer[pos] = curHigh;
260
                ExtHighBuffer[pos]    = curHigh;
261
            }
262
            break;
263
        }
264
    }
265
266
    return(rates_total);
267
}
268
269
//-----------------------------------------------------------------------
270
void InitializeAll()
271
{
272
    ArrayInitialize(ExtKagizagBuffer, 0.0);
273
    ArrayInitialize(ExtHighBuffer,    0.0);
274
    ArrayInitialize(ExtLowBuffer,     0.0);
275
}
276
//-----------------------------------------------------------------------
277
int IndexOfLowest(const double &array[],const int si,const int ei)
278
{
279
  double v = array[si];
280
  int r=si;
281
  for(int i=si+1;i<=ei;i++) {
282
    if(v>array[i]) { r=i ; v = array[i]; }
283
  }
284
  return r ;
285
}
286
//-----------------------------------------------------------------------
287
int IndexOfHighest(const double &array[],const int si,const int ei)
288
{
289
  double v = array[si];
290
  int r=si;
291
  for(int i=si+1;i<=ei;i++) {
292
    if(v<array[i]) { r=i ; v = array[i]; }
293
  }
294
  return r ;
295
}
296
//-----------------------------------------------------------------------
297