初心者の方からの質問 MQL5 MT5 MetaTrader 5 - ページ 578

 
Artyom Trishkin:

DataCandlesは構造体である。ヒストリーからローソク足を書き込む配列はarray[]です。そこで、そのインデックスをチャート上のローソク足のインデックスと一致させるために、時系列として作成する必要があるのです。つまり、array[]の0番目のセルが、現在の日付に最も近いローソク足に対応することになります。

すなわち、1.ローソク足を配列array[]にコピーし、2.それを時系列にし、そこから値を構造体に読み込むのです。

あなたは、配列[]なしで行うことができます - ちょうど構造体にチャートから直接データを書き込むが、私は5との互換性のためにこれを提案 - それは唯一の高[i]、低[i]と他のデータを使用してインジケータで直接コピーすることができますが、スクリプトまたはエキスパートアドバイザーで、我々は最初の配列に必要な履歴間隔をコピーする必要があります、これは私がやったこと。

bool series=ArrayIsSeries(array)。
アラート(シリーズ)。
ArraySetAsSeries(array, true)。
bool series=ArrayIsSeries(array)。

アラート(シリーズ)。

このように?

両方のアラートはまだfalseを返します

 
Andrey Koldorkin:
bool series=ArrayIsSeries(array)。
アラート(シリーズ)。
ArraySetAsSeries(array, true)。
bool series=ArrayIsSeries(array)。

アラート(シリーズ)。

このように?

両方のアラートはまだfalseを返します

というわけで、これは「エラー、バグ、質問」に報告すべきバグです。

このスクリプトは、ローソク足がコピーされた時刻を、array[]の0番目と最後のセルに表示します。

//+------------------------------------------------------------------+
//|                                                     TestCopy.mq4 |
//|              Copyright 2016, Artem A. Trishkin, Skype artmedia70 |
//|                       https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Artem A. Trishkin, Skype artmedia70"
#property link      "https://login.mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict
#property script_show_inputs

enum enumYN
  {
   enYes=1, // Да
   enNo=0,  // Нет
  };

//--- input parameters
input int Search_Period=10;   // Количество копируемых свечей
int searchPeriod=(Search_Period<1)?1:Search_Period;
input int Delta=2;            // Количество пунктов допуска
int delta=(Delta<0)?0:Delta;
input enumYN AsSeries=enYes;  // Массив array как таймсерия
MqlRates array[];             // Массив структур для копирования Open, High, Low, Close, Time
  
struct DataCandle             // Структура для хранения всех совпадений
  {
   int number_matched;           // Количество совпадений
   MqlRates reference_candle;    // Данные эталонной свечи
   MqlRates matched_candles[];   // Массив свечей, совпадающих с эталонной по нужному критерию 
  };
  DataCandle dataCandle[];    // Массив структур данных свечей и их совпадений
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int copy_bars=(int)fmin(Search_Period,Bars(Symbol(),Period()));   // количество копируемых свечей
   int copied=CopyRates(Symbol(),PERIOD_CURRENT,1,copy_bars,array);  // копируем данные
   if(copied>0) {                                                    // если скопировали
      ArraySetAsSeries(array,AsSeries);                              // задаём массив как таймсерию или нет
      ArrayResize(dataCandle,copied);                                // задаём размер структуры равным числу скопированных данных
      ZeroMemory(dataCandle);                                        // Обнуляем данные в структуре
      //--- основной цикл по "эталонным" свечам в массиве array. Их параметры будем искать в доп. цикле
      for(int i=0; i<copy_bars-1; i++) {                             // цикл по скопированным данным от начала до "на один меньше размера массива"
         dataCandle[i].reference_candle.high=array[i].high;          // ищем этот high
         dataCandle[i].reference_candle.low=array[i].low;            // запомнили low для сравнения
         dataCandle[i].reference_candle.time=array[i].time;          // запомнили time для вывода в журнал
         //--- поиск совпадений с эталонной свечой, индексируемой индексом основного цикла i
         int size=0;                                                 // размер массива совпадающих свечей
         ArrayResize(dataCandle[i].matched_candles,size);            // Размер массива совпадений в ноль
         dataCandle[i].number_matched=size;                          // Инициализируем количество совпадений нулём
         //--- теперь ищем совпадения по high свечей в цикле j с high эталонной свечи с индексом i
         for(int j=0; j<copy_bars; j++) {                            // в цикле от i+1 до copy_bars
            if(j==i) continue;                                       // пропустим свечу "саму себя"
            //--- если совпадают high эталонной свечи (i) и свечи с индексом j (с допуском на величину Point)
            if(NormalizeDouble(delta*Point()-fabs(array[i].high-array[j].high),Digits())>=0) {
               size++;                                               
               ArrayResize(dataCandle[i].matched_candles,size);            // увеличим размер массива совпадающих свечей
               dataCandle[i].number_matched=size;                          // запишем количество совпадений
               dataCandle[i].matched_candles[size-1].high=array[j].high;   // запишем в массив high совпадающей свечи
               dataCandle[i].matched_candles[size-1].low=array[j].low;     // запишем в массив low совпадающей свечи
               dataCandle[i].matched_candles[size-1].time=array[j].time;   // запишем в массив время совпадающей свечи
               //Print("Время свечи ",i," :",TimeToString(dataCandle[i].reference_candle.time=array[i].time),", high=",DoubleToString(dataCandle[i].reference_candle.high=array[i].high,Digits()),". Совпадение со свечой ",TimeToString(dataCandle[i].matched_candles[size-1].time=array[j].time),", её high ",DoubleToString(dataCandle[i].matched_candles[size-1].high=array[j].high,Digits()),". Совпадений: ",(string)dataCandle[i].number_matched);
               }
            }
         }
      }

   //--- Посмотрим чего понаписали в массивы
   Alert("Array is series: ",ArrayIsSeries(array),
         "\ntime array[0]: ",TimeToString(array[0].time,TIME_DATE|TIME_MINUTES),
         "\ntime array[",string(searchPeriod-1),"]: ",TimeToString(array[ArraySize(array)-1].time,TIME_DATE|TIME_MINUTES));
   for(int i=0; i<ArraySize(dataCandle)-1; i++) {
      string refs_txt="";
      string matched_txt="";
      refs_txt="Свеча "+IntegerToString(i,2,'0')+": время "+TimeToString(dataCandle[i].reference_candle.time)+", high: "+DoubleToString(dataCandle[i].reference_candle.high,Digits())+" имеет совпадений: "+(string)dataCandle[i].number_matched+" шт. ";
      if(dataCandle[i].number_matched>0) {
         for(int j=0; j<ArraySize(dataCandle[i].matched_candles); j++) {
            matched_txt="Совпадение "+IntegerToString(j+1)+": "+TimeToString(dataCandle[i].matched_candles[j].time)+", high: "+DoubleToString(dataCandle[i].matched_candles[j].high,Digits());
            }
         }
      Print(refs_txt,matched_txt);
      }
  }
//+------------------------------------------------------------------+
 
Artyom Trishkin:

ですから、これは「エラー、バグ、質問」に報告されるべきバグです。

このスクリプトは、ローソク足がコピーされた時刻を、array[]の0番目と最後のセルに表示します。

これを出力する。

配列が直列である:false

time array[0]: 2016.05.12 21:00

時間配列[9]:2016.05.12 12:00

 
Andrey Koldorkin:

こう出てきます。

配列が直列である:false

time array[0]: 2016.05.12 21:00

時間配列[9]:2016.05.12 12:00

スクリプトの開始時に時系列としてArray arrayを「Yes」と選択すると、常にfalseであるが時刻は正しい。

Array is series: false
time array[0]: 2016.05.12 21:00
time array[9]: 2016.05.12 12:00

いいえ」を選択した場合。

Array is series: false
time array[0]: 2016.05.12 12:00
time array[9]: 2016.05.12 21:00

配列に書き込まれたローソク足の時間が逆になっています。つまり、ArraySetAsSeriess() は 正しく動作しますが、ArrayIsSeries() は動作せず、常にfalseを出力します。これは、上記のバグスレッドに既に書きました。

 
Andrey Koldorkin:

ああ、このプログラミング。森の奥へ進むほど...。

配列の向きを知る必要はないことを理解する。アルゴリズムは、繰り返しを探している。したがって、バーがどのような順番で処理されるかは気にしない。
 
Vasiliy Sokolov:
配列の向きを知る必要はないことを理解する。アルゴリズムは、繰り返しを探している。だから、バーの処理順序は問わない。
そうです。結局のところ、私はその後、どのローソク足が一致を形成し、現在の 価格に最も近いと価格を取る知っている必要があります低。
 
Andrey Koldorkin:
が必要です。なぜなら、どのローソク足が一致したかを調べ、現在の 価格に最も近いところから安値を取る必要があるからです。

そのための仕組みとして、キャンドルタイムがあり、それによって、必要な時間に最も近いキャンドルを見つけることができます。

また、ローソク足番号は出力する必要はありません。実際のバー番号とは一致しません。なぜなら、配列を埋めて、配列の中のインデックスは、チャート上ではなく、配列の中のローソク足の番号にのみ属しているからです。

 
Artyom Trishkin:

私はそれが何を与えるかをチェックしました - 常に偽ですが、時間は正しいです:スクリプトを実行するときに時系列の "はい "としてArray配列を選択した場合、その後。

いいえ」を選択した場合。

配列に書き込まれたローソク足の時間は逆になっており、ArraySetAsSeriess()は正しく動作しますが、ArrayIsSeries()は動作せず、常にfalseを出力します。これは既に上記のバグスレッドに書き込んであります。

コードを少し修正しました。

ArraySetAsSeries(array,true); //ここにtrueを入れるだけです。

を作成し、ローソク足の本数を追加してセルフチェックを行いました。

Alert("Array is series: ",ArrayIsSeries(array),

"⑯キャンドル" +IntegerToString(0,2,'0')+" 時間 array[0]: ",TimeToString(array[0].time,TIME_DATE|TIME_MINUTES)",

"ⅷ時間配列[", string(searchperiod-1),"]:",TimeToString(array[ArraySize(array)-1].time,TIME_DATE|TIME_MINUTES)");

次のように出力されます。

配列が直列である:false

キャンドル00時刻配列[0]:2016.05.12 22:00

キャンドル09時間配列[9]:2016.05.12 13:00

 
Artyom Trishkin:
これを行うには、構造内にキャンドルタイムがあり、それによって必要な任意の時間に最も近いキャンドルを見つけることができます。
まあ、すべて同じです。それは、1行のコードで方向が変わることが判明しています。しかし、私が何が起こっているのかを理解しようとしている間、少なくとも私の頭の中のローソク足とマシンは同じ順番になるでしょう ))
 
Andrey Koldorkin:

コードを少し変更しました。

ArraySetAsSeries(array,true); //ここにtrueを入れるだけです。

を作成し、ローソク足の本数を追加してセルフチェックを行いました。

Alert("Array is series: ",ArrayIsSeries(array),

"⑯キャンドル" +IntegerToString(0,2,'0')+" 時間 array[0]: ",TimeToString(array[0].time,TIME_DATE|TIME_MINUTES)",

"ⅷ時間配列[", string(searchperiod-1),"]:",TimeToString(array[ArraySize(array)-1].time,TIME_DATE|TIME_MINUTES)");

次のように出力されます。

配列が直列である:false

Candle 00 time array[0]: 2016.05.12 22:00

キャンドル09時間配列[9]:2016.05.12 13:00

mql4を使っていますか?その場合、構造体に書かれているその時間からローソク足の番号を調べます。iBarShift() を使用すると便利です。
理由: