Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 2181

 
Aleksei Stepanenko #:
Думаю так: создать двумерный массив 5х366. Перед началом прогона загружать из файла всё имеющиеся колонки. В момент прогона заполнить нужный столбец из пяти. По окончании выгрузить весь массив целиком заменив предыдущий файл. Но такое писать не пять минут. Не обещаю, что смогу быстро сделать. Сами тоже попробуйте писать.

Спасибо большое . Как я понял моя задача для Вас,  профессионала самого  высокого уровня - является новой с решением которой Вы похоже раньше не сталкивались.
Я даже немного загордился тем что смог просто сформулировать такую задачу... Конечно я буду пытаться решить эту задачу сам. Если получится - дам Вам знать. Но мои шансы решить ее быстрее чем Вы близки к нулю.... как мне кажется. Я хоть и давно на этом форуме но уровень моего владения языком просто несопоставим с Вашим уровнем.

И еше.... на одномерном массиве я только тренируюсь. И планирую писать в файл двухмерные массивы. И поэтому мне нужно что бы в файле с конечным результатом ячейки со значениями располагались рядом  друг с другом , как на рисунке внизу.

Спасибо.

 
ANDREY #:

Понял. Спасибо за ценную информацию. Объясните мне пожалуйста такой момент 

Если я не ошибаюсь управление  в выделенную строку попадает на каждом тике. Для чего на каждом тике делать 365 итераций. Например, на  тике N в первую (0) ячейку массива записалось значение. А 355 ячеек - пустые, без значений. Для чего нужно по пустым ячейкам массива прогонять заголовок цикла с последующими итерациями? Почему нельзя вообще обойтись без цикла и в функции  FileWrite(eHandle,DoubleToString(My[i][1],Digits)); вместо   [i][ всегда ставить  [b] Я убирал цикл и делал так как я здесь написал. Почему то в этом случае в файл ничего не писалось.... 

Спасибо

А почему массив объявлен на 366 записей? Может было сказано, но я пропустил…

Потом, зачем всё это писать в процессе, если в нужный момент можно мгновенно получить в массив данные баров или отдельно указанную цену баров

ArrayCopySeries - Операции с массивами - Справочник MQL4
ArrayCopySeries - Операции с массивами - Справочник MQL4
  • docs.mql4.com
ArrayCopySeries - Операции с массивами - Справочник MQL4
 
Alexey Viktorov #:

А почему массив объявлен на 366 записей? Может было сказано, но я пропустил…

Потом, зачем всё это писать в процессе, если в нужный момент можно мгновенно получить в массив данные баров или отдельно указанную цену баров

366 - произвольная цифра... количество дней в году. По факту количество заполненных элементов равно количеству торговых дней Форекса. То есть 252 кажется.
В процессе потому что я хотел научиться при оптимизации  сохранять значение нужной переменной и видеть значение этой переменной в динамике ,после окончания оптимизации  . Поэтому я оптимизировал день недели, а в динамике хотел видеть сохраненное значение цены. Этот код не для торговли, а для научения меня сохранять значение нужной переменной в процессе оптимизации и чтения этих значений моими глазами и умами после оптимизации с несколькими прогонами. Ведь в ходе и после оптимизации программа не создает лог файл в который я мог бы запринтовать нужную мне информацию как при тестировании без оптимизации.
В результате , я научился в процессе оптимизации  сохранять в 5 файлов значение цены. Но мне непонятно зачем на каждом тике делать даже 250 итераций, если массив не заполняется весь и сразу. Или управление в функцию void OnTick() передается не на каждом тике, а только после полного окончания очередного прогона, когда массив заполнен полностью значениями цены?

Спасибо

 
ANDREY #:

366 - произвольная цифра... количество дней в году. По факту количество заполненных элементов равно количеству торговых дней Форекса. То есть 252 кажется.
В процессе потому что я хотел научиться при оптимизации  сохранять значение нужной переменной и видеть значение этой переменной в динамике ,после окончания оптимизации  . Поэтому я оптимизировал день недели, а в динамике хотел видеть сохраненное значение цены. Этот код не для торговли, а для научения меня сохранять значение нужной переменной в процессе оптимизации и чтения этих значений моими глазами и умами после оптимизации с несколькими прогонами. Ведь в ходе и после оптимизации программа не создает лог файл в который я мог бы запринтовать нужную мне информацию как при тестировании без оптимизации.
В результате , я научился в процессе оптимизации  сохранять в 5 файлов значение цены. Но мне непонятно зачем на каждом тике делать даже 250 итераций, если массив не заполняется весь и сразу. Или управление в функцию void OnTick() передается не на каждом тике, а только после полного окончания очередного прогона, когда массив заполнен полностью значениями цены?

Спасибо

Тогда нужен динамический массив и при каждом новом значении увеличивать размер массива и цикл тогда будет по размеру массива.

Или ещё лучше, от массива отказаться вообще. Есть новые данные, открывается файл, дописывается одна строка в конец файла и файл закрывается.

 
Alexey Viktorov #:

Тогда нужен динамический массив и при каждом новом значении увеличивать размер массива и цикл тогда будет по размеру массива.

Или ещё лучше, от массива отказаться вообще. Есть новые данные, открывается файл, дописывается одна строка в конец файла и файл закрывается.

Именно так я и пытался сделать

void OnTick()
{
//ArrayInitialize(My,0); &&DayOfWeek()==G 
if(Bid==iOpen(NULL ,PERIOD_D1,0)&&B!=Day()&&DayOfWeek()==G)
{
OrderSend(Symbol(),OP_SELL,0.1,Bid, 3,Ask+150*Point,Ask-70*Point,"310",5);
B=Day();
b++;
My[b]=Bid;
}
}   
double OnTester()
   {
   string eName="My_"+(string)G+".csv";
   if(FileIsExist(eName)) FileDelete(eName); 
   int eHandle=FileOpen(eName,FILE_CSV|FILE_WRITE|FILE_SHARE_WRITE|FILE_READ,";");
   if(eHandle!=INVALID_HANDLE)
      {FileWrite(eHandle,DoubleToString(My[b],Digits));}
      FileClose(eHandle);
      return(0);
   }

Я убрал из OnTester() цикл . Но результат меня не устраивает. Программа создает так же 5 файлов , но в каждый из них записывает не по 250 значений цены , а по 1 значению в ячейку А1. Это наводит меня на мысль что управление попадает в   OnTester() не на каждом тике а только один раз в конце прогона и в А1 попадает последнее из 250 значение цены .
Я до сих пор точно не понимаю как часто управление попадает в  OnTester() на каждом тике, или один раз в конце каждого прогона оптимизатора. Если управление попадает в  OnTester() на каждом тике, тогда и массив не нужен...как мне кажется.

 
ANDREY #:

Именно так я и пытался сделать

Я убрал из OnTester() цикл . Но результат меня не устраивает. Программа создает так же 5 файлов , но в каждый из них записывает не по 250 значений цены , а по 1 значению в ячейку А1. Это наводит меня на мысль что управление попадает в   OnTester() не на каждом тике а только один раз в конце прогона и в А1 попадает последнее из 250 значение цены .
Я до сих пор точно не понимаю как часто управление попадает в  OnTester() на каждом тике, или один раз в конце каждого прогона оптимизатора. Если управление попадает в  OnTester() на каждом тике, тогда и массив не нужен...как мне кажется.

Упростите задачу до 3 значений и разберитесь. На 250 значениях легко запутаться.)

 
Valeriy Yastremskiy #:

Упростите задачу до 3 значений и разберитесь. На 250 значениях легко запутаться.)

Спасибо за ценный совет. Сделал как Вы сказали. Убрал цикл из OnTester() , но массив оставил , и еще уменьшил тестируемый период до 1 месяца. В результате установил точно, что в каждый из 5 файлов попадает только в А1 только значение последней цены, то есть последней ячейки массива. То есть , цены последнего в месяце понедельника, последнего вторника... последней пятницы. Получается, что за один прогон массив заполняется полностью и только в конце прогона в OnTester() попадает только последнее значение b , то есть значение только последней заполненной ячейки массива. А я раньше думал, что в  OnTester() управление попадает на каждом тике.... в моем случае при оптимизации. Если бы управление попадало туда на каждом тике , а значит и на начале каждой дневной свечи, то , как мне кажется , в файл на каждой новой дневной свече должна была бы записываться ее цена в каждую следующую ячейку колонки  А (1,2,3,4......30)

Правда возможен еще вариант при котором функция FileWrite() почему то на каждом открытии дневной свечи  пишет значение цены всегда в одну и ту же ячейку A1. Тогда я что то недопонимаю в этой функции.

Интересно... а какие изменения нужно внести в код что бы управление в  OnTester() попадало  на открытии  каждой дневной свечи... если оно попадает туда только один раз в конце прогона? Или какие изменения нужно внести в код, что бы  FileWrite() заполняла все ячейки, если управление в  OnTester()  попадает на  открытии каждой дневной свечи ?

#property strict
int b=-1,B=-1;
extern int G=0;
double My[31];


void OnTick()
{
//ArrayInitialize(My,0); &&DayOfWeek()==G 
if(Bid==iOpen(NULL ,PERIOD_D1,0)&&B!=Day()&&DayOfWeek()==G)
{
OrderSend(Symbol(),OP_SELL,0.1,Bid, 3,Ask+150*Point,Ask-70*Point,"310",5);
B=Day();
b++;
My[b]=Bid;
}
}   
double OnTester()
   {
   string eName="My_"+(string)G+".csv";
   if(FileIsExist(eName)) FileDelete(eName); 
   int eHandle=FileOpen(eName,FILE_CSV|FILE_WRITE,";");
   if(eHandle!=INVALID_HANDLE)
      {FileWrite(eHandle,My[b]);}
      FileClose(eHandle);
      return(0);
   }
 
ANDREY #:

Именно так я и пытался сделать

Я убрал из OnTester() цикл . Но результат меня не устраивает. Программа создает так же 5 файлов , но в каждый из них записывает не по 250 значений цены , а по 1 значению в ячейку А1. Это наводит меня на мысль что управление попадает в   OnTester() не на каждом тике а только один раз в конце прогона и в А1 попадает последнее из 250 значение цены .
Я до сих пор точно не понимаю как часто управление попадает в  OnTester() на каждом тике, или один раз в конце каждого прогона оптимизатора. Если управление попадает в  OnTester() на каждом тике, тогда и массив не нужен...как мне кажется.

Когда файл открывается указатель находится в начале файла. Соответственно записывается новое значение поверх старого. Для записи значения в следующую строку надо файловый указатель переместить в коней файла.

bool  FileSeek(
   int                  file_handle,     // handle файла
   long                 offset,          // в байтах
   ENUM_FILE_POSITION   origin           // позиция для отсчета
   );

SEEK_SET

Начало файла

SEEK_CUR

Текущая позиция файлового указателя

SEEK_END

Конец файла


То-есть на 0 байт от конца файла.

 
Alexey Viktorov #:

Когда файл открывается указатель находится в начале файла. Соответственно записывается новое значение поверх старого. Для записи значения в следующую строку надо файловый указатель переместить в коней файла.

SEEK_SET

Начало файла

SEEK_CUR

Текущая позиция файлового указателя

SEEK_END

Конец файла


То-есть на 0 байт от конца файла.

Кроме того, если перед открытием файл каждый раз удалять, то конец файла почему-то совпадает с началом ))

То же самое, если открывать только с флагом FILE_WRITE, без FILE_READ.

 
ANDREY #:

Спасибо за ценный совет. Сделал как Вы сказали. Убрал цикл из OnTester() , но массив оставил , и еще уменьшил тестируемый период до 1 месяца. В результате установил точно, что в каждый из 5 файлов попадает только в А1 только значение последней цены, то есть последней ячейки массива. То есть , цены последнего в месяце понедельника, последнего вторника... последней пятницы. Получается, что за один прогон массив заполняется полностью и только в конце прогона в OnTester() попадает только последнее значение b , то есть значение только последней заполненной ячейки массива. А я раньше думал, что в  OnTester() управление попадает на каждом тике.... в моем случае при оптимизации. Если бы управление попадало туда на каждом тике , а значит и на начале каждой дневной свечи, то , как мне кажется , в файл на каждой новой дневной свече должна была бы записываться ее цена в каждую следующую ячейку колонки  А (1,2,3,4......30)

Правда возможен еще вариант при котором функция FileWrite() почему то на каждом открытии дневной свечи  пишет значение цены всегда в одну и ту же ячейку A1. Тогда я что то недопонимаю в этой функции.

Интересно... а какие изменения нужно внести в код что бы управление в  OnTester() попадало  на открытии  каждой дневной свечи... если оно попадает туда только один раз в конце прогона? Или какие изменения нужно внести в код, что бы  FileWrite() заполняла все ячейки, если управление в  OnTester()  попадает на  открытии каждой дневной свечи ?

Когда-же научитесь читать документацию?

Событие Tester генерируется по окончании тестирования эксперта на исторических данных.

Функция вызывается непосредственно перед вызовом функции OnDeinit()


Функции обработки событий - Функции - Основы языка - Справочник MQL4
Функции обработки событий - Функции - Основы языка - Справочник MQL4
  • docs.mql4.com
Функции обработки событий - Функции - Основы языка - Справочник MQL4