ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Как се създава и тества forex система. Expert Advisors и бектестове на системи за автоматична търговия.
Потребителски аватар
saxsten
Мнения: 1365
Регистриран: 04 апр 2010, 23:16
9 получени
3 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от saxsten » 26 май 2018, 14:16

Mateev написа:
25 май 2018, 21:21
saxsten написа:
25 май 2018, 20:29
не бе димич това проблемче го реших и тук нарочно не пущам този ред от кода
това де то съм написал събира печалбата от как е пуснат експерта пък мен ми трябва да събира само печалбата от 1 ден назад
С две думи когато z= 0 или пък
ако TimeCurrent()-iTime(NULL,PERIOD_D1,0)= 0 ;
тоест когато се появил нов нулев бар...
Когато се появи нов дневен бар, първо трябва да го детектираш. След това трябва да си изясниш кой е бил предишния (последния) ден, в който си имал затворени сделки. Това е така защото има и почивни дни или пък е възможно експерта да си го пуснал няколко дена след последното му пускане. И чак когате се изяснят тези неща, чак тогава можеш да развъртиш цикъл за пресканиране на ордерите, които отговарят на това условие. Тези неща в никакъв случай не се правят с един единствен ред код.

Изясняването на ситуацията с появата на нов нулев бар става посредством запомняне на DateTime на предишния бар и сравняването с DateTime на нулевия бар. Това запомняне ако го правиш в глобална променлива ще работи само ако експерта е активен в полунощ при смяната на деня. Ами ако това не е така? Затова запомнянето на старото DateTime трябва да се направи в областа с глобални променливи не на експерта, а на самия MetaTrader. В тази глобална MetaTrader област стойностите на променливите "живеят" дори и тогава, когато MetaTrader се рестартира или дори когато не е активен дни наред. За опериране с такива променливи се използват функциите GlobalVariableSet() и GlobalVariableGet().

След това сравняваш старата и новата стойност на DateTime на нулевия бар, и ако са различни, детектираш факта, че вече имаме нов ден.

Следващата стъпка е да си изясниш през кой ден е бил затворен последният ти ордер (позиция). Това се прави посредством развъртане на цикъл през историческите ордери. И ако този ден наистина е бил предишния ден, пускаш си останалия код. Какво обаче ще правиш, ако този ден не е бил предишния, а някакъв много по-стар? Тука не ти знам логиката на стратегията, но ти трябва точно и ясно да разграничиш факта дали говорим за предишен ден или за много по-стар ден, и на базата на това да пуснеш различни кодове за обработка.

ПП: Наистина имам желание да ти помогна, защото виждам как се мъчиш, а имаш голям мерак да направиш нещо работещо. Специално на MQL4 съм започнал да програмирам още преди 10-12 години и до момента сигурно съм изписал над 1 милион реда код. Мога да ти помагам с такива казуси, които от време на време поставяш във форума, но не разбирам защо се противиш на това. Уж търсиш помощ, а после не я приемаш.
Матеев като гледам какви "кодове " драскаш тука с нищо не можеш да ми помогнеш
Как да ми помогнеш ,като още не си разбрал същността на задачата ,ами се отплескваш по появяването на нови барове и обяснение, кое как щяло да работи ....абе с две думи не ми помагай, защото нищо няма да ти роди главата и нещо още по лошо, който ти се върже на приказките , дълго ще страда от заблужденията ти :grin:
Форекса е оръжие за масово поразяване

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 26 май 2018, 14:37

Тъй като в тази тема няколко пъти се е говорило за това, че MetaTrader 4 не поддържа милисекунди, искам да покажа как аз разрешавам този проблем. Накратко - чета милисекундите директно от DLL-ите на Windows-а, и после ги съхранявам и обработвам в няколко различни мои структури за поддръжка на времето.

Базовата структура на Windows-а за поддръжка на времето с милисекунди е дълга 16 байта и като такава не е подходяща да се използва в големи масиви, защото ще се пилее много памет. За да си разреша този проблем аз си създадох 3 други различни структури, всяка от които е строго специализирана за дадено приложение и поддържа времето в по-малко на брой байтове.

В следващите постинги ще публикувам кода на следните структури:
SSystemTime - точно копие на Windws-ката структура с милисекунди в нея и с дължина 16 байта.
SMicroTime - поддържа времето с милисекунди в него, но само в 8 байта (използвам double променлива)
SRsmTime - поддържа времето с милисекунди в него, но само в 6 байта (използвам побитово кодиране).
SBarTime - времето се съхранява само в 4 байта с дискрета от 1 минута. Подходящо е за създаване на масиви от барове.

Комуникацията с Windows-а се извършва само от първата структура (SSystemTime), а всички останали структури я използват и доразвиват за собствените си нужди. Кода и на четирите структури е писан отдавна и през годините е доразвиван и усъвършенстван. Използвал съм го в една камара експерти, индикатори, библиотеки или скриптове, и трябва да ви кажа, че работи безпогрешно. Дори и да е имало в миналото някакви бъгове, те отдавна са открити и отстранени. Така че можете да му имате доверие на този код.

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 26 май 2018, 14:44

Структура SSystemTime
Това е 16-байтова структура за времето с дискрета 1 милисекунда. Структурата е точно копие на тази, която се намира в Kernel32.DLL. Има следната функционалност:
1. Чете времето с милисекунди от Kernel32.dll
2. Съхранява датата и време от 1 до 65535-та година
2. Функцията ToString работи в пълния диапазон от години (1..65535).
3. Комуникацията с datetime формат е ограничена в диапазона от 1970 до 3000 г. заради изискванията на MQL4
4. Изчисляването на броя на секундите между две времена е ограничено в диапазона от 01.01.1970 до 31.12.2105 г. заради изискванията на Windows-а.

Ето кода на структурата:

Код: Избери всички

//+------------------------------------------------------------------+
//|                                             StructSystemTime.mqh |
//|                                        Copyright 2017, Mateev SC |
//|                                            http://www.mateev.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Mateev SC"
#property link      "http://www.mateev.com"
#property version   "1.00"
#property strict

//====================================================================
// 16-байтова структура за времето с дискрета 1 милисекунда.
// Структурата може да съхранява години от 1 до 65535.
//====================================================================
// Грегорианския каледнар е въведен на 4 октомври 1582 г., така че по-старите дати в тази структура може и да не са верни.
// Съгласно Грегорианския каледнар правилата за определяне на високосните години са следните:
// 1. Всяка година, кратна на 4, е високосна
// 2. Всяка година, кратна на 100, но не и на 400, не е високосна
// 3. Всяка година, кратна на 400, е високосна (1600, 2000 и т. н.)
//
// Средната продължителност на 1 година според Грегорианския календар е 365.2425 дни
// или 365.2425 = 365 + 0.25 - 0.01 + 0.0025 = 365 + 1/4 - 1/100 + 1/400
//
// Реалната средна продължителност, измерена със съвременни методи, е 365.242374 дни.
// Това означава, че в Грегорианския календар се натрупва отрицателна грешка от
// -0.000126 дена на на година, или това прави по -10.8864 секунди на година.
// Това означава, че някъде около 3000-ната година трябва да се отнеме 1 ден от календара. :)
//
// Преди Грегориянаския календар е действал Юлианския календар, при който
// се е спазвало само правило номер 1 (всяка година, кратна на 4, е високосна).
// Тази функционалност засега няма да се реализира в тази структура.
//
// Според Windows-a, който поддържа същата структура, валидните години са от 1601 до 30837г.
// Функцията за изчисляване на броя на секундите обаче връща валидни стойности
// само в диапазона от 01.01.1970 до 31.12.2105.
//
// Според MQL4, валидните стойности на неговия datetime формат са от 1970 до 3000 г.
//====================================================================
// Съгласно всичко написано по-горе, във функционалноста на структурата са наложени следните ограничения:
// 1. Структурата съхранява данни от 1 до 65535 г.
// 2. Функцията ToString работи в пълния диапазон от години (1..65535).
// 3. Комуникацията с datetime формат е ограничена в диапазона от 1970 до 3000 г.
// 4. Изчисляването на броя на секундите между две времена е ограничено в диапазона от 01.01.1970 до 31.12.2105 г.
//====================================================================
// Деклариране на импортнатите функции от Kernel32.DLL

#import "kernel32.dll"
void GetLocalTime (ushort &time[]); // Връща локалното време (GMT+2) с точност 1 милисекунда
void GetSystemTime(ushort &time[]); // Връща текущото UTC време (Coordinated Universal Time)
//void RtlTimeToSecondsSince1970(ulong &time[], ulong &seconds); // Връща броя на секундите от 01.01.1970 до 31.12.2105
#import

//====================================================================
// 16-байтова структура за времето с дискрета 1 милисекунда
// Структурата е точно копие на тази, която се намира в Kernel32.DLL

struct SSystemTime // 16-байтова структура за времето с дискрета 1 милисекунда
  {
  ushort year; // Година (виж ограниченията в коментара най-отгоре)
  ushort mon;  // Месец (1..12)
  ushort dow;  // Ден от седмицата от 0-Неделя до 6-Събота 
  ushort day;  // Ден от месеца (1..31)
  ushort hour; // Час (0..23)
  ushort min;  // Минута (0..59)
  ushort sec;  // Секунда (0..59)
  ushort msc;  // Милисекунда (0.999)
  
  SSystemTime(){Clear();} // Default конструктор
 
  // Методи за инициализация на цялата структура SRsmTime
  void Clear();          // Нулира структурата 
  void ReadLocalTime (); // Чете от Kernel32.DLL текущото GMT+2 локално време с точност 1 милисекунда
  void ReadSystemTime(); // Чете от Kernel32.DLL текущото UTC локално време (Coordinated Universal Time)
  
  // Методи за инициализация на части от структурата, след проверка за валидност
  bool SetYear (ushort value); // Проверява валидноста и инициализира годината 
  bool SetMonth(ushort value); // Проверява валидноста и инициализира месеца
  bool SetDay  (ushort value); // Проверява валидноста и инициализира деня 
  void CheckDays(); // Проверява валидноста на датата и ако трябва, прави корекции. Изчислява и деня от седмицата.
    
  bool SetHour    (ushort value); // Проверява валидноста и инициализира часовете 
  bool SetMinute  (ushort value); // Проверява валидноста и инициализира минутите
  bool SetSecond  (ushort value); // Проверява валидноста и инициализира секундите         
  bool SetMSeconds(ushort value); // Проверява валидноста и инициализира милисекундите
    
  // Преобразува цялата структура в различни други Time формати
  datetime    ToDateTime(); // Връща времето в datetime формат (8 байта), при което се губят милисекундите
  MqlDateTime ToMqlTime (); // Връща времето в MqlDateTime формат, при което се губят милисекундите
  
  // Методи за връщане на различни части от структурата или на някаква изчисляема информация
  ushort DaysInMonth() {return(DaysInMonth(mon));} // Връща броя на дните в месеца от структурата
  ushort DayOfYear();  // Връща деня от годината (1..366)
  
  string NameMonth9() {return(NameMonth9(mon));} // Връща дългото име на месеца в структурата
  string NameMonth2() {return(NameMonth2(mon));} // Връща късото име на месеца в структурата
  string NameDay9  () {return(NameDay9  (dow));} // Връща дългото име на деня от седмицата
  string NameDay3  () {return(NameDay3  (dow));} // Връща дългото име на деня от седмицата
  
  // DateTime методи (функции), които не зависят от данните в тази структура
  ushort DaysInMonth(ushort num); // Връща броя на дните в месеца month
  string NameMonth9 (ushort num); // Връща дългото име на месеца
  string NameMonth2 (ushort num); // Връща късото име на месеца  
  string NameDay9   (ushort num); // Връща дългото име на деня от седмицата
  string NameDay3   (ushort num); // Връща късото име на деня от седмицата
  
  // Връща времето като стринг в един от следните формати:
  // За датата (първата десетична цифра):
  //   0 - няма дата
  //   1 - YYYY.MM.DD  
  //   2 - DD.MM.YYYY
  // За времето (втората десетична цифра):
  //   0 - няма време
  //   1 - HH:MM:SS.mmm
  //   2 - HH:MM:SS
  //   3 - HH:MM
  //   4 - HH
  //   5 - MM:SS.mmm
  //   6 - MM:SS
  //   7 - MM
  //   8 - SS.mmm
  //   9 - SS
  //  10 - mmm
  // За в бъдеще ако дотрябва някой друг формат, то той се добавя на празните позиции
  string ToString(int dateFormat=1, int timeFormat=1); // Връща стринг с формат, указан в променливите dateFormat и timeFormat

  // Методи за запис и четене от файл
  bool Save(const int handle); // Записва структурата във файл
  bool Load(const int handle); // Чете структурата от файл     
  };

//====================================================================
// Нулира SKernelTime

SSystemTime::Clear() 
  {
    ZeroMemory(this);
    mon  = 1; // Месец (1..12)
    day  = 1; // Ден от месеца (1..31)
  }  

//====================================================================
// Чете от Kernel32.DLL текущото GMT+2 локално време с точност 1 милисекунда  
  
void SSystemTime::ReadLocalTime()
  {
    ushort time[8]; GetLocalTime(time); // Чете времето от Kernel32.DLL
    
    year = time[0]; // Година (виж ограниченията в коментара най-отгоре)
    mon  = time[1]; // Месец (1..12)
    dow  = time[2]; // Ден от седмицата от 0-Неделя до 6-Събота 
    day  = time[3]; // Ден от месеца (1..31)
    hour = time[4]; // Час (0..23)
    min  = time[5]; // Минута (0..59)
    sec  = time[6]; // Секунда (0..59)
    msc  = time[7]; // Милисекунда (0.999) 
  }
  
//====================================================================
// Чете от Kernel32.DLL текущото UTC локално време с точност 1 милисекунда  
  
void SSystemTime::ReadSystemTime()
  {
    ushort time[8]; GetSystemTime(time); // Чете времето от Kernel32.DLL
    
    year = time[0]; // Година (виж ограниченията в коментара най-отгоре)
    mon  = time[1]; // Месец (1..12)
    dow  = time[2]; // Ден от седмицата от 0-Неделя до 6-Събота 
    day  = time[3]; // Ден от месеца (1..31)
    hour = time[4]; // Час (0..23)
    min  = time[5]; // Минута (0..59)
    sec  = time[6]; // Секунда (0..59)
    msc  = time[7]; // Милисекунда (0.999)
  }

//====================================================================
// Проверява валидноста на датата и ако трябва, прави корекции. Изчислява деня от седмицата. 
 
void SSystemTime::CheckDays()
  { 
    ushort dm = DaysInMonth();
    if(day>dm) day=dm;
    dow = (ushort)TimeDayOfWeek(this.ToDateTime()); //Изчислява деня от седмицата
  }  

//====================================================================
// Проверява валидноста и инициализира годината
  
bool SSystemTime::SetYear(ushort value)
  {
    if (value < 1970) return(false);
    year = value;
    CheckDays();
    return(true);
  }

//====================================================================
// Проверява валидноста и инициализира месеца
  
bool SSystemTime::SetMonth(ushort value)
  {
    if (value <  1) return(false);
    if (value > 12) return(false);
    mon = value;
    CheckDays();
    return(true);
  }    

//====================================================================
// Проверява валидноста и инициализира деня
  
bool SSystemTime::SetDay(ushort value)
  {
    if (value <  1) return(false);
    if (value > 31) return(false);
    day = value;
    CheckDays();
    return(true);
  }

//====================================================================
// Проверява валидноста и инициализира часа
  
bool SSystemTime::SetHour(ushort value)
  {
    if (value > 23) return(false);
    hour = value;
    return(true);
  }  

//====================================================================
// Проверява валидноста и инициализира минутата
  
bool SSystemTime::SetMinute(ushort value)
  {
    if (value > 59) return(false);
    min = value;
    return(true);
  }  
    
//====================================================================
// Проверява валидноста и инициализира секундата
  
bool SSystemTime::SetSecond(ushort value)
  {
    if (value > 59) return(false);
    sec = value;
    return(true);
  }  
    
//====================================================================
// Проверява валидноста и инициализира милисекундата
  
bool SSystemTime::SetMSeconds(ushort value)
  {
    if (value > 999) return(false);
    msc = value;
    return(true);
  }      
//====================================================================
// Връща броя на дните в месеца month

ushort SSystemTime::DaysInMonth(ushort num)
  {
    switch(num)
      {
        case  1: return(31); // Януари
        case  2: {           // Февруари
                   ushort leapYear = year;
                   if (year%100==0) leapYear/=100;
                   return((leapYear%4==0)? 29 : 28);        
                 }
        case  3: return(31); // Март
        case  4: return(30); // Април       
        case  5: return(31); // Май
        case  6: return(30); // Юни       
        case  7: return(31); // Юли
        case  8: return(31); // Август
        case  9: return(30); // Септември
        case 10: return(31); // Октомври
        case 11: return(30); // Ноември       
        case 12: return(31); // Декември
      }
   return(0);  
  }
  
//====================================================================   
// Връща деня от годината (1..366)

ushort SSystemTime::DayOfYear()
  {
    ushort days = 0;
    for (ushort i=1; i<mon; i++) days = days + DaysInMonth(i);
    return(days + day); 
  }  
  
//====================================================================
// Връща времето в MqlDateTime формат, при което се губят милисекундите

MqlDateTime SSystemTime::ToMqlTime()
  {
    MqlDateTime ret;
    ret.year        = year;
    ret.mon         = mon;
    ret.day         = day;
    ret.hour        = hour;
    ret.min         = min;
    ret.sec         = sec;
    ret.day_of_week = dow;
    ret.day_of_year = this.DayOfYear();
    return (ret);
  } 
  
//====================================================================
// Връща времето в datetime формат, при което се губят милисекундите

datetime SSystemTime::ToDateTime()
  {
    if (year < 1970) return(   0); // Минимална година в datetime формата
    if (year > 3000) return(3000); // Максимална година в datetime формата
    
    MqlDateTime MqlTime = this.ToMqlTime();
    return(StructToTime(MqlTime));
  }

//====================================================================
// Връща дългото име на месеца month
  
string SSystemTime::NameMonth9 (ushort num)
  {
   switch(num)
     {
      case  1: return("January");
      case  2: return("February");
      case  3: return("March");
      case  4: return("April");
      case  5: return("May");
      case  6: return("June");
      case  7: return("July");
      case  8: return("August");
      case  9: return("September");
      case 10: return("October");
      case 11: return("November");
      case 12: return("December");
     }
   return("Bad month");  
  }  

//====================================================================
// Връща късото име на месеца month 
  
string SSystemTime::NameMonth2 (ushort num)
  {
   switch(num)
     {
      case  1: return("Jan");
      case  2: return("Feb");
      case  3: return("Mar");
      case  4: return("Apr");
      case  5: return("May");
      case  6: return("Jun");
      case  7: return("Jul");
      case  8: return("Aug");
      case  9: return("Sep");
      case 10: return("Oct");
      case 11: return("Nov");
      case 12: return("Dec");
     }
   return("Bad month");  
  } 

//==================================================================== 
// Връща дългото име на деня от седмицата
  
string SSystemTime::NameDay9(ushort num)
  {
   switch(num)
     {
      case 0: return("Sunday");
      case 1: return("Monday");
      case 2: return("Tuesday");
      case 3: return("Wednesday");
      case 4: return("Thursday");
      case 5: return("Friday");
      case 6: return("Saturday");
     }
   return("Bad day of week");  
  }      

//==================================================================== 
// Връща късото име на деня от седмицата
  
string SSystemTime::NameDay3(ushort num)
  {
   switch(num)
     {
      case 0: return("Su");
      case 1: return("Mo");
      case 2: return("Tu");
      case 3: return("We");
      case 4: return("Th");
      case 5: return("Fr");
      case 6: return("Sa");
     }
   return("Bad day of week");  
  } 
  
//====================================================================  
// Връща времето като стринг в един от следните формати:
// За датата (първата десетична цифра):
//   0 - няма дата
//   1 - YYYY.MM.DD  
//   2 - DD.MM.YYYY
// За времето (втората десетична цифра):
//   0 - няма време
//   1 - HH:MM:SS.mmm
//   2 - HH:MM:SS
//   3 - HH:MM
//   4 - HH
//   5 - MM:SS.mmm
//   6 - MM:SS
//   7 - MM
//   8 - SS.mmm
//   9 - SS
//  10 - mmm
// За в бъдеще ако дотрябва някой друг формат, то той се добавя на празните позиции

string SSystemTime::ToString(int dateFormat=1, int timeFormat=1)
  { 
    // Делимитери
    string T = "."; // Точка
    string D = ":"; // Двуеточие
    
    // Преобразуване на датата в стринг
    string date = "";
    if (dateFormat>0)
      {
        string YYYY = IntegerToString(year,4,'0');
        string MM   = IntegerToString(mon ,2,'0');
        string DD   = IntegerToString(day ,2,'0');
        
        switch (dateFormat)
          {
            case  1: date = YYYY + T + MM + T + DD; break;
            case  2: date = DD + T + MM + T + YYYY; break;
          }
      }
    
    // Преобразуване на времето в стринг
    string time = "";
    if (timeFormat>0)
      {
        string HH  = IntegerToString(hour,2,'0');
        string MM  = IntegerToString(min ,2,'0'); 
        string SS  = IntegerToString(sec ,2,'0');
        string mmm = IntegerToString(msc ,3,'0');
        
        switch (timeFormat)
          {
            case  1: time = HH + D + MM + D + SS + T + mmm; break;
            case  2: time = HH + D + MM + D + SS;           break;
            case  3: time = HH + D + MM;                    break;
            case  4: time = HH;                             break;
            case  5: time = MM + D + SS + T + mmm; break;
            case  6: time = MM + D + SS;           break;
            case  7: time = MM;                    break;
            case  8: time = SS + T + mmm; break;
            case  9: time = SS;           break;
            case 10: time = mmm; break;
          }
      }
      
    if (dateFormat==0) return(time); // Няма дата. Връща само времето.
    if (timeFormat==0) return(date); // Няма време. Връща само датата    
    return(date + " " + time);       // Има ги и двете. Връща ги с добавен интервал между тях като разделител.
  } 
 
//====================================================================
// Записва структурата във файл
 
bool SSystemTime::Save(const int handle)
  {
    if(handle==INVALID_HANDLE) return(false);
    else return(FileWriteStruct(handle,this,sizeof(SSystemTime))==sizeof(SSystemTime));
  } 

//====================================================================
// Чете структурата от файл

bool SSystemTime::Load(const int handle)
  {
    if(handle==INVALID_HANDLE) return(false);
    else return(FileReadStruct(handle,this,sizeof(SSystemTime))==sizeof(SSystemTime));
  }  


Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 26 май 2018, 15:01

Структура SMicroTime
Структурата има функционаност за поддръжка на времето с точност 1-2 микросекунди във формат double (8 байта). Цялата част на числото отговаря на MQL datetime формата (брой секунди от 1970г. до 3000г.). Дробната част на числото съдържа дробната част на секундата с точност поне 5.5 разряда. За да работи правилно се нуждае от кода на структурата SSystemTime, който трябва да се добави в началото с #include.

Структурата е подходяща за повсеместно използване в кода вместо datetime. Трябва обаче да се има предвид факта, че секундите и милисекундите се съхраняват като дробна част от деня, с всички последици, които произтичат от това при сравнение на две времена.

Ето кода на структурата:

Код: Избери всички

//+------------------------------------------------------------------+
//|                                                   SMicroTime.mqh |
//|                                        Copyright 2017, Mateev SC |
//|                                            http://www.mateev.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Mateev SC"
#property link      "http://www.mateev.com"
#property version   "1.00"
#property strict

#include "StructSystemTime.mqh" // 16-байтова структура за времето с дискрета 1 милисекунда

//=======================================================================================
// Функционаност за поддръжка на времето с точност 1-2 микросекунди във формат double (8 байта).
// Цялата част на числото отговаря на MQL datetime формат (брой секунди от 1970г. до 3000г.)
// Дробната част на числото съдържа дробната част на секундата с точност поне 5.5 разряда
// Ниво 1 от структурите за време, защото ползва структура от ниво 0 (SSystemTime)
//=======================================================================================

struct SMicroTime // 8 байта структура за дата и време с дискрета 1 секунда в цялата част и микросекунди в дробната част 
  {
    double MicroTime; // В 1 double се съхранява цялата информация за структурата  
    
    SMicroTime() {Clear();}; // Default конструктор    

    // Методи за инициализация на цялата структура SMicroTime
    void Clear(); // Нулира структурата 
    void Set(datetime dt) {MicroTime=double(dt);} // Инициализира MicroTime от datetime и нулира мили и микро-секундите
    bool Set(SSystemTime &value); // Записва SSystemTime в структурата   
    
    // Инициализация само на дробната част на структурата (микросекундите), без да се променя цялата част
    void SetMkSeconds(uint mks){MicroTime=double(uint(MicroTime))+double(mks)/1000000;} 
    
    // Преобразува цялата структура в различни други Time формати
    datetime    ToDateTime(void) const { return(datetime(MicroTime)); } // Връща датата и времето в datetime формат
    MqlDateTime ToMqlTime (void); // Връща времето в MqlDateTime формат
    
    // Връща различни периоди от време от комплексното SMicroTime    
    ushort   GetYear     (void) const { return(ushort(TimeYear     (datetime(MicroTime)))); }
    ushort   GetMonth    (void) const { return(ushort(TimeMonth    (datetime(MicroTime)))); }
    ushort   GetDay      (void) const { return(ushort(TimeDay      (datetime(MicroTime)))); }
    ushort   GetHour     (void) const { return(ushort(TimeHour     (datetime(MicroTime)))); }
    ushort   GetMinute   (void) const { return(ushort(TimeMinute   (datetime(MicroTime)))); }
    ushort   GetSecond   (void) const { return(ushort(TimeSeconds  (datetime(MicroTime)))); }
    ushort   GetDayOfWeek(void) const { return(ushort(TimeDayOfWeek(datetime(MicroTime)))); }
    ushort   GetDayOfYear(void) const { return(ushort(TimeDayOfYear(datetime(MicroTime)))); } 
    uint     GetMkSeconds(void); // Връща микросекундите от последната секунда (0..999999)      
    ushort   GetMSecond  (void) { return(ushort(GetMkSeconds()/1000)); } // Връща милисекундите от последната секунда      (0..999)
    ushort   GetMkSecond (void) { return(ushort(GetMkSeconds()%1000)); } // Връща микросекундите от последната милисекунда (0..999)
    
    // Връща времето като стринг в един от следните формати:
    //  0 - YYYY.MM.DD HH:MM:SS.uuuuuu
    //  1 - YYYY.MM.DD HH:MM:SS.mmm
    //  2 - YYYY.MM.DD HH:MM:SS
    //  3 - YYYY.MM.DD HH:MM
    //  4 - YYYY.MM.DD 
    //  5 - DD.MM.YYYY HH:MM:SS.uuuuuu
    //  6 - DD.MM.YYYY HH:MM:SS.mmm
    //  7 - DD.MM.YYYY HH:MM:SS
    //  8 - DD.MM.YYYY HH:MM
    //  9 - DD.MM.YYYY    
    // 10 - HH:MM:SS.uuuuuu                
    // 11 - HH:MM:SS.mmm
    // 12 - HH:MM:SS
    // 13 - HH:MM    
    // За в бъдеще ако дотрябва някой друг формат, то той се добавя най-отзад със следващия индекс
    string ToString(int format); 

    bool Save(const int handle); // Записва структурата във файл
    bool Load(const int handle); // Чете структурата от файл    
  };
  
//====================================================================
// Нулира структурата

void SMicroTime::Clear()
  {
    ZeroMemory(this);
  }
  
//==================================================================== 
// Записва SSystemTime в структурата  
   
bool SMicroTime::Set(SSystemTime &value)
  {
    datetime DT = value.ToDateTime();
    this.MicroTime = double(DT);
    this.SetMkSeconds(uint(value.msc)*1000);
    return(true);
  } 
  
//====================================================================
// Връща микросекундите от последната секунда (0..999999)
// Точноста е 1 дискрета при малките години и 2 дискрети при големите

uint SMicroTime::GetMkSeconds(void)
  {
    int mks = (int)MathRound((MicroTime-datetime(MicroTime))*1000000);
    if (mks <      0) mks =      0;
    if (mks > 999999) mks = 999999;
    return(uint(mks));
  }
  
//====================================================================
// Връща времето в MqlDateTime, при което се губят милисекундите

MqlDateTime SMicroTime::ToMqlTime()
  {
    MqlDateTime ret;
    ret.year = GetYear  ();
    ret.mon  = GetMonth ();
    ret.day  = GetDay   ();
    ret.hour = GetHour  ();
    ret.min  = GetMinute();
    ret.sec  = GetSecond();
    ret.day_of_week = GetDayOfWeek();
    ret.day_of_year = GetDayOfYear();
    return (ret);
  }  

//====================================================================
// Връща времето като стринг в един от следните формати:
//  0 - YYYY.MM.DD HH:MM:SS.uuuuuu
//  1 - YYYY.MM.DD HH:MM:SS.mmm
//  2 - YYYY.MM.DD HH:MM:SS
//  3 - YYYY.MM.DD HH:MM
//  4 - YYYY.MM.DD 
//  5 - DD.MM.YYYY HH:MM:SS.uuuuuu
//  6 - DD.MM.YYYY HH:MM:SS.mmm
//  7 - DD.MM.YYYY HH:MM:SS
//  8 - DD.MM.YYYY HH:MM
//  9 - DD.MM.YYYY    
// 10 - HH:MM:SS.uuuuuu                
// 11 - HH:MM:SS.mmm
// 12 - HH:MM:SS
// 13 - HH:MM   
// За в бъдеще ако дотрябва някой друг формат, то той се добавя най-отзад със следващия индекс

string SMicroTime::ToString(int format)
  { 
    string year = IntegerToString(GetYear     (),4,'0');
    string month= IntegerToString(GetMonth    (),2,'0');
    string day  = IntegerToString(GetDay      (),2,'0');
    string hour = IntegerToString(GetHour     (),2,'0');
    string min  = IntegerToString(GetMinute   (),2,'0'); 
    string sec  = IntegerToString(GetSecond   (),2,'0');
    string ms   = IntegerToString(GetMSecond  (),3,'0');
    string mks  = IntegerToString(GetMkSeconds(),6,'0'); 

    
    string T = "."; // Точка
    string D = ":"; // Двуеточие
    string S = " "; // Space 
    
    switch (format)
      {
        case  0: return(year+T+month+T+day+S+hour+D+min+D+sec+T+mks); break;
        case  1: return(year+T+month+T+day+S+hour+D+min+D+sec+T+ms);  break;
        case  2: return(year+T+month+T+day+S+hour+D+min+D+sec);       break;
        case  3: return(year+T+month+T+day+S+hour+D+min);             break;
        case  4: return(year+T+month+T+day);                          break;
        case  5: return(day+T+month+T+year+S+hour+D+min+D+sec+T+mks); break;
        case  6: return(day+T+month+T+year+S+hour+D+min+D+sec+T+ms);  break;
        case  7: return(day+T+month+T+year+S+hour+D+min+D+sec);       break;
        case  8: return(day+T+month+T+year+S+hour+D+min);             break;
        case  9: return(day+T+month+T+year);                          break;
        case 10: return(hour+D+min+D+sec+T+mks);                      break;
        case 11: return(hour+D+min+D+sec+T+ms);                       break;
        case 12: return(hour+D+min+D+sec);                            break;
        case 13: return(hour+D+min);                                  break;
        default: return(year+T+month+T+day+S+hour+D+min+D+sec+T+mks);
      }
  }
  
//====================================================================
// Записва структурата във файл
 
bool SMicroTime::Save(const int handle)
  {
    if(handle==INVALID_HANDLE) return(false);
    else return(FileWriteStruct(handle,this,sizeof(SMicroTime))==sizeof(SMicroTime));
  } 

//====================================================================
// Чете структурата от файл

bool SMicroTime::Load(const int handle)
  {
    if(handle==INVALID_HANDLE) return(false);
    else return(FileReadStruct(handle,this,sizeof(SMicroTime))==sizeof(SMicroTime));
  }

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 26 май 2018, 15:19

Структура SRsmTime
Това е 6-байтова структура за времето с дискрета от 1 милисекунда. Годините са от 0 до 4095. В структурата е използвано побитово кодиране, така че дори и милисекундите са записани точно такива, каквито са в действителност. Тази структура предоставя възможно най-компактното кодиране на времето заедно с милисекундите, така че тя е най-подходяща да се използва в големи масиви, в които има и време. Аз масово я използвам в масивите от тикове, които създавам и поддържам в един или друг клас. За да работи структурата правилно се нуждае от кода на структурата SSystemTime, който трябва да се добави в началото с #include.

Ето кода на структурата:

Код: Избери всички

//+------------------------------------------------------------------+
//|                                                StructRsmTime.mqh |
//|                                        Copyright 2016, Mateev SC |
//|                                            http://www.mateev.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Mateev SC"
#property link      "http://www.mateev.com"
#property version   "1.00"
#property strict

#include "StructSystemTime.mqh" // 16-байтова структура за времето с дискрета 1 милисекунда

//====================================================================
// 6-байтова структура за времето с дискрета 1 милисекунда
// Годините са от 0 до 4095
// Ниво 1 от структурите за време, защото ползва структура от ниво 0 (SSystemTime)
//====================================================================

struct SRsmTime // 6 байтова структура за времето на тика с дискрета 1 милисекунда
  {
  ushort YearMonth;  // 12 бита за годината (0 до 4095) и 4 бита за месеца (1-12)
  ushort DayHourMin; // 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59)
  ushort SecondsMs;  // 6 бита за секундите (0-59) и 10 бита за милисекундите (0-999)
  
  SRsmTime() {Clear();}; // Default конструктор
  
  // Методи за инициализация на цялата структура SRsmTime
  void Clear(); // Нулира структурата  
  bool Set(datetime     value); // Записва datetime в структурата и нулира милисекундите  
  bool Set(SSystemTime &value); // Записва SSystemTime в структурата (губят се микросекундите)
  bool Set(MqlDateTime &value); // Записва MqlDateTime в структурата и нулира милисекундите  
    
  // Методи за инициализация само на част от структурата SRsmTime
  bool SetYear   (ushort value); // Записва годината в структурата 
  bool SetMonth  (ushort value); // Записва месеца в структурата
  bool SetDay    (ushort value); // Записва деня в структурата 
  bool SetHour   (ushort value); // Записва часа в структурата   
  bool SetMinute (ushort value); // Записва минутата в структурата
  bool SetSecond (ushort value); // Записва секундата в структурата
  bool SetMSecond(ushort value); // Записва милисекундата в структурата
  
  // Преобразува цялата структура в различни други Time формати
  datetime    ToDateTime (); // Връща времето в datetime    формат, при което се губят милисекундите
  SSystemTime ToSystemTime(); // Връща времето в SMicroTime  формат (микросекундите са нулирани)
  MqlDateTime ToMqlTime  (); // Връща времето в MqlDateTime формат, при което се губят милисекундите
  string      ToString(int D, int T) {return(this.ToSystemTime().ToString(D,T));} // Връща стринг с формат, указан в SSystemTime
      
  // Връща различни периоди от време от комплексното SRsmTime
  ushort GetYear   () {return( YearMonth  >> 4);}           // Връща годината
  ushort GetMonth  () {return( YearMonth  &  0x000F);}      // Връща месеца от годината
  ushort GetDay    () {return( DayHourMin >> 11);}          // Връща деня от годината
  ushort GetHour   () {return((DayHourMin >> 6) & 0x001F);} // Връща часа
  ushort GetMinute () {return( DayHourMin &  0x003F);}      // Връща минутата
  ushort GetSecond () {return( SecondsMs  >> 10);}          // Връща секундата
  ushort GetMSecond() {return( SecondsMs  &  0x03FF);}      // Връща милисекундата 

  // Методи за запис и четене от файл
  bool Save(const int handle); // Записва структурата във файл
  bool Load(const int handle); // Чете структурата от файл     
  };
  
//====================================================================
// Нулира структурата

void SRsmTime::Clear()
  {
    ZeroMemory(this);
    SetMonth(1);
    SetDay(1);
  }  

//====================================================================
// Връща времето в MqlDateTime, при което се губят милисекундите

MqlDateTime SRsmTime::ToMqlTime()
  {
    MqlDateTime ret;
    ret.year = GetYear  ();
    ret.mon  = GetMonth ();
    ret.day  = GetDay   ();
    ret.hour = GetHour  ();
    ret.min  = GetMinute();
    ret.sec  = GetSecond();
    ret.day_of_week = TimeDayOfWeek(StructToTime(ret));
    ret.day_of_year = TimeDayOfYear(StructToTime(ret));
    return (ret);
  } 

//====================================================================
// Връща времето в datetime формат, при което се губят милисекундите

datetime SRsmTime::ToDateTime()
  {
    MqlDateTime MqlTime = this.ToMqlTime();
    return(StructToTime(MqlTime));
  }

//====================================================================  
// Записва годината в структурата.
// 12 бита за годината (0 до 4095) и 4 бита за месеца (1-12).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SRsmTime::SetYear(ushort value)
  {
    if (value > 4095) return(false);
    YearMonth = (YearMonth & 0x000F) | (value << 4);
    return (true);
  }

//====================================================================  
// Записва месеца в структурата.
// 12 бита за годината (0 до 4095) и 4 бита за месеца (1-12).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SRsmTime::SetMonth(ushort value)
  {
    if (value < 1 ) return(false);
    if (value > 12) return(false);
    YearMonth = (YearMonth & 0xFFF0) | value;
    return (true);
  }

//====================================================================  
// Записва деня в структурата.
// 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SRsmTime::SetDay(ushort value)
  {
    if (value < 1 ) return(false);
    if (value > 31) return(false);
    DayHourMin = (DayHourMin & 0x07FF) | (value << 11);
    return (true);
  } 

//====================================================================  
// Записва часа в структурата.
// 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SRsmTime::SetHour(ushort value)
  {
    if (value > 23) return(false);
    DayHourMin = (DayHourMin & 0xF83F) | (value << 6);
    return (true);
  }

//====================================================================  
// Записва минутата в структурата.
// 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SRsmTime::SetMinute(ushort value)
  {
    if (value > 59) return(false);
    DayHourMin = (DayHourMin & 0xFFC0) | value;
    return (true);
  }

//====================================================================  
// Записва секундата в структурата.
// 6 бита за секундите (0-59) и 10 бита за милисекундите (0-999)
// Връща true, ако стойноста е валидна и е записана коректно.

bool SRsmTime::SetSecond(ushort value)
  {
    if (value > 59) return(false);
    SecondsMs = (SecondsMs & 0x03FF) | (value << 10);
    return (true);
  }
            
//====================================================================  
// Записва милисекундата в структурата.
// 6 бита за секундите (0-59) и 10 бита за милисекундите (0-999)
// Връща true, ако стойноста е валидна и е записана коректно.

bool SRsmTime::SetMSecond(ushort value)
  {
    if (value > 999) return(false);
    SecondsMs = (SecondsMs & 0xFC00) | value;
    return (true);
  }

//====================================================================
// Записва datetime в структурата и нулира милисекундите
  
bool SRsmTime::Set(datetime value)
 {
   if (!this.SetYear  ((ushort)TimeYear   (value))) return(false);
   if (!this.SetMonth ((ushort)TimeMonth  (value))) return(false);
   if (!this.SetDay   ((ushort)TimeDay    (value))) return(false);
   if (!this.SetHour  ((ushort)TimeHour   (value))) return(false);
   if (!this.SetMinute((ushort)TimeMinute (value))) return(false);
   if (!this.SetSecond((ushort)TimeSeconds(value))) return(false);
   return(SetMSecond(0)); // Нулира милисекундата
 } 
  
//====================================================================
// Записва MqlDateTime в структурата и нулира милисекундите
  
bool SRsmTime::Set(MqlDateTime &value)
 {
   if (!this.SetYear   (ushort(value.year))) return(false);
   if (!this.SetMonth  (ushort(value.mon ))) return(false);
   if (!this.SetDay    (ushort(value.day ))) return(false);
   if (!this.SetHour   (ushort(value.hour))) return(false);
   if (!this.SetMinute (ushort(value.min ))) return(false);
   if (!this.SetSecond (ushort(value.sec ))) return(false);
   if (!this.SetMSecond(0)) return(false); 
   return(true); 
 }
 
//====================================================================
// Записва SSystemTime в структурата
  
bool SRsmTime::Set(SSystemTime &value)
 {
   if (!this.SetYear   (value.year)) return(false);
   if (!this.SetMonth  (value.mon )) return(false);
   if (!this.SetDay    (value.day )) return(false);
   if (!this.SetHour   (value.hour)) return(false);
   if (!this.SetMinute (value.min )) return(false);
   if (!this.SetSecond (value.sec )) return(false);
   if (!this.SetMSecond(value.msc )) return(false);   
   return(true); 
 }   

//====================================================================
// Връща времето в SSystemTime формат (микросекундите са нулирани)

SSystemTime SRsmTime::ToSystemTime()
  {
    SSystemTime ret;
    ret.Clear();
    ret.SetYear    (this.GetYear());
    ret.SetMonth   (this.GetMonth());
    ret.SetDay     (this.GetDay());
    ret.SetHour    (this.GetHour());
    ret.SetMinute  (this.GetMinute());
    ret.SetSecond  (this.GetSecond());
    ret.SetMSeconds(this.GetMSecond());
    return (ret);
  }

//====================================================================
// Записва структурата във файл
 
bool SRsmTime::Save(const int handle)
  {
    if(handle==INVALID_HANDLE) return(false);
    else return(FileWriteStruct(handle,this,sizeof(SRsmTime))==sizeof(SRsmTime)); 
  } 

//====================================================================
// Чете структурата от файл

bool SRsmTime::Load(const int handle)
  {
    if(handle==INVALID_HANDLE) return(false);
    else return(FileReadStruct(handle,this,sizeof(SRsmTime))==sizeof(SRsmTime));
  }  


Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 26 май 2018, 15:23

Структура SBarTime
Това е 4-байтова структура за времето с дискрета от 1 минута. Годините са от 0 до 4095. В структурата е използвано побитово кодиране. Тази структура предоставя възможно най-компактното кодиране на времето с дискрета от 1 минута, така че тя е най-подходяща да се използва в големи масиви от барове, в които времето няма нужда да е по-точно от 1 минута. За да работи структурата правилно се нуждае от кода на структурата SSystemTime, който трябва да се добави в началото с #include.

Ето кода на структурата:

Код: Избери всички

//+------------------------------------------------------------------+
//|                                                StructBarTime.mqh |
//|                                        Copyright 2016, Mateev SC |
//|                                            http://www.mateev.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Mateev SC"
#property link      "http://www.mateev.com"
#property version   "1.00"
#property strict

#include "StructSystemTime.mqh" // 16-байтова структура за времето с дискрета 1 милисекунда

//====================================================================
// 4-байтова структура за времето на един бар с дискрета 1 минута.
// Годините са от 0 до 4095.
// Ниво 1 от структурите за време, защото ползва структура от ниво 0 (SSystemTime)
//====================================================================

struct SBarTime // 4 байтова структура за времето на 1 бар с дискрета 1 минута
  {
    ushort YearMonth;  // 12 бита за годината (0 до 4095) и 4 бита за месеца (1-12)
    ushort DayHourMin; // 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59)

    SBarTime() {Clear();}; // Default конструктор    
    
    // Методи за инициализация на цялата структура SBarTime
    void Clear(); // Нулира структурата
    bool Set(datetime     value); // Записва datetime в структурата   
    bool Set(SSystemTime &value); // Записва SMicroTime в структурата (губят се секундите и микросекундите)     
    bool Set(MqlDateTime &value); // Записва MqlDateTime в структурата
    
    // Методи за инициализация само на част от структурата SBarTime
    bool SetYear  (ushort value); // Записва само годината в структурата 
    bool SetMonth (ushort value); // Записва само месеца в структурата
    bool SetDay   (ushort value); // Записва само деня в структурата 
    bool SetHour  (ushort value); // Записва само часа в структурата   
    bool SetMinute(ushort value); // Записва само минутата в структурата
    
    // Преобразува цялата структура в различни други Time формати
    datetime    ToDateTime (); // Връща времето в datetime    формат
    MqlDateTime ToMqlTime  (); // Връща времето в MqlDateTime формат
    SSystemTime ToSystemTime(); // Връща времето в SMicroTime  формат
    string      ToString(int D, int T) {return(this.ToSystemTime().ToString(D,T));} // Връща стринг с формат, указан в SSystemTime
    
    // Връща различни периоди от време от комплексното SBarTime 
    ushort GetYear  () {return( YearMonth  >> 4);}           // Връща годината
    ushort GetMonth () {return( YearMonth  &  0x000F);}      // Връща месеца от годината
    ushort GetDay   () {return( DayHourMin >> 11);}          // Връща деня от годината
    ushort GetHour  () {return((DayHourMin >> 6) & 0x003F);} // Връща часа
    ushort GetMinute() {return( DayHourMin &  0x003F);}      // Връща минутата

    // Методи за запис и четене от файл
    bool Save(const int handle); // Записва структурата във файл
    bool Load(const int handle); // Чете структурата от файл     
  };
  
//====================================================================
// Нулира структурата

void SBarTime::Clear()
  {
    ZeroMemory(this);
    SetMonth(1);
    SetDay(1);
  }  

//====================================================================
// Връща времето в MqlDateTime, при което се губят милисекундите

MqlDateTime SBarTime::ToMqlTime()
  {
    MqlDateTime ret;
    ret.year = GetYear  ();
    ret.mon  = GetMonth ();
    ret.day  = GetDay   ();
    ret.hour = GetHour  ();
    ret.min  = GetMinute();
    ret.sec  = 0;
    ret.day_of_week = TimeDayOfWeek(StructToTime(ret));
    ret.day_of_year = TimeDayOfYear(StructToTime(ret));
    return (ret);
  } 

//====================================================================
// Връща времето в datetime формат, при което се губят милисекундите

datetime SBarTime::ToDateTime()
  {
    MqlDateTime MqlTime = this.ToMqlTime();
    return(StructToTime(MqlTime));
  }
  
//====================================================================
// Връща времето в SMicroTime  формат
  
SSystemTime SBarTime::ToSystemTime()
  {
    SSystemTime ret;
    ret.Clear();
    ret.SetYear  (this.GetYear());
    ret.SetMonth (this.GetMonth());
    ret.SetDay   (this.GetDay());
    ret.SetHour  (this.GetHour());
    ret.SetMinute(this.GetMinute());
    return (ret);
  }   

//====================================================================  
// Записва годината в структурата.
// 12 бита за годината (0 до 4095) и 4 бита за месеца (1-12).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SBarTime::SetYear(ushort value)
  {
    if (value > 4095) return(false);
    YearMonth = (YearMonth & 0x000F) | (value << 4);
    return (true);
  }

//====================================================================  
// Записва месеца в структурата.
// 12 бита за годината (0 до 4095) и 4 бита за месеца (1-12).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SBarTime::SetMonth(ushort value)
  {
    if (value < 1 ) return(false);
    if (value > 12) return(false);
    YearMonth = (YearMonth & 0xFFF0) | value;
    return (true);
  }

//====================================================================  
// Записва деня в структурата.
// 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SBarTime::SetDay(ushort value)
  {
    if (value < 1 ) return(false);
    if (value > 31) return(false);
    DayHourMin = (DayHourMin & 0x07FF) | (value << 11);
    return (true);
  } 

//====================================================================  
// Записва часа в структурата.
// 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SBarTime::SetHour(ushort value)
  {
    if (value > 23) return(false);
    DayHourMin = (DayHourMin & 0xF83F) | (value << 6);
    return (true);
  }

//====================================================================  
// Записва минутата в структурата.
// 5 бита за деня (1-31), 5 бита за часа (0-23) и 6 бита за минутата (0-59).
// Връща true, ако стойноста е валидна и е записана коректно.

bool SBarTime::SetMinute(ushort value)
  {
    if (value > 59) return(false);
    DayHourMin = (DayHourMin & 0xFFC0) | value;
    return (true);
  }

//====================================================================
// Записва datetime в структурата
  
bool SBarTime::Set(datetime value)
 {
   if (!SetYear  ((ushort)TimeYear  (value))) return(false);
   if (!SetMonth ((ushort)TimeMonth (value))) return(false);
   if (!SetDay   ((ushort)TimeDay   (value))) return(false);
   if (!SetHour  ((ushort)TimeHour  (value))) return(false);
   if (!SetMinute((ushort)TimeMinute(value))) return(false);
   return(true); 
 } 
 
//====================================================================
// Записва MqlDateTime в структурата и нулира милисекундите
  
bool SBarTime::Set(MqlDateTime &value)
 {
   if (!this.SetYear  ((ushort)value.year)) return(false);
   if (!this.SetMonth ((ushort)value.mon )) return(false);
   if (!this.SetDay   ((ushort)value.day )) return(false);
   if (!this.SetHour  ((ushort)value.hour)) return(false);
   if (!this.SetMinute((ushort)value.min )) return(false);
   return(true); 
 }
 
//====================================================================
// Записва SMicroTime в структурата (губят се микросекундите от SMicroTime)
  
bool SBarTime::Set(SSystemTime &value)
 {
   if (!this.SetYear  (value.year)) return(false);
   if (!this.SetMonth (value.mon )) return(false);
   if (!this.SetDay   (value.day )) return(false);
   if (!this.SetHour  (value.hour)) return(false);
   if (!this.SetMinute(value.min )) return(false);
   return(true); 
 } 

//====================================================================
// Записва структурата във файл
 
bool SBarTime::Save(const int handle)
  {
    if (handle==INVALID_HANDLE) return(false);
    else return(FileWriteStruct(handle,this,sizeof(SBarTime))==sizeof(SBarTime));
  } 

//====================================================================
// Чете структурата от файл

bool SBarTime::Load(const int handle)
  {
    if (handle==INVALID_HANDLE) return(false);
    else return(FileReadStruct(handle,this,sizeof(SBarTime))==sizeof(SBarTime));
  }  


Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 26 май 2018, 15:33

Всички публикувани от мене Time структури могат директно да комуникират и в двете посоки със структурите на MetaTrader 4 (datetime и MqlDateTime). Помежду си обаче моите структури комуникират само със SSystemTime, тъй като тя е най-универсална, и като такава може да се използва като опорна точка в комуникацията между всички останали Time структури без загуба на данни.

Различните структури имат различна функционалност, и ако нещо липсва в една от структурите, спокойно може тя да се преобразува в друга структура и да се ползва липсващата функционалност. Например преобразуването на датата и времето в различни стрингови формати го има само в SSystemTime и SMicroTime. Или пък получаването на късите и дългите имена на месеците и дните от седмицата го има само в структурата SSystemTime.

Забравих да кажа и най-важното. Тъй като структурата SSystemTime извиква функции на WIndows-а, то за да работи коректно, трябва специално да се разреши опцията Allow DLL imports в менюто Tools/Options/Expert Advisors на MetaTrader 4.

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 26 май 2018, 16:37

saxsten написа:
26 май 2018, 14:16
.....
Матеев като гледам какви "кодове " драскаш тука с нищо не можеш да ми помогнеш
Как да ми помогнеш ,като още не си разбрал същността на задачата ,ами се отплескваш по появяването на нови барове и обяснение, кое как щяло да работи ....абе с две думи не ми помагай, защото нищо няма да ти роди главата и нещо още по лошо, който ти се върже на приказките , дълго ще страда от заблужденията ти :grin:
Престани да подскачаш. Вече не си ми интересен. Всички вече видяха колко струваш като програмист ... :grin:
Куца ти не само синтакса на кода, но и логиката ти при създаване на алгоритми. Ако искаш повече да не се излагаш, спри да публикуваш кодове. А ако зададеш въпрос за нещо, което не го знаеш, тогава вече може някой и да ти отговори, ако не подскачаш толкова много. И си спихни самочувствието на програмист, защото вече доказа, че не си такъв. Та ти дори не можеш правилно да обясниш какво точно искаш да направиш. Използваш терминология и разсъждения на първокласник, а не на програмист.

Съжалявам, че всичко това ти го казвам в прав текст и не съм тактичен, но ти сам си го изпроси с отношението си към мене. Ясно осъзнавам, че злобееш когато някой знае и може повече от тебе, но доброто възпитание изисква да се подтиска тази злоба. Примири се в ролята си на ученик до момента, до който започнат да ти просветват някои неща от програмирането и финансовите пазари, защото иначе се излагаш в ролята си на учител, който ръси глупост след глупост в последните 10-15 твои постинга.

ПП: Ако спреш да се заяждаш с мене и да обиждаш, аз също обещавам да бъда тактичен. и да си трая или тактично да поправям грешките ти, без намеци колко си зле с материала. Алтернативата, ако продължаваш да ме обиждаш, е да започна да вадя един по един историческите ти постинги и да обяснявам за всеки един от тях къде грешиш и защо грешиш. Нищо лично, но все пак решението ти за бъдещите ни взаимоотнощения си е лично твое, а не мое. Аз не съм злобен и просто ще реагирам според ситуацията, предизвикана от тебе.

Потребителски аватар
knestin
Мнения: 176
Регистриран: 28 яну 2015, 14:33
4 получени
2 дадени
Контакти:

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от knestin » 27 май 2018, 19:32

Здравейте колеги трейдъри.
Искам да ви помоля за помощ за написване на следната програмка за МТ4 / за тестване и ЕА / :
1. В 14.00 Бг време откриваме sell EURUSD & buy EURUSD със SL= 30 и TP = 60 pipsa /по 4 знака/
2. В 14,00 Бг време откриваме sell AUDUSD & buy AUDUSD със SL = 25 и TP = 50 pipsa.

Всички сделки закриваме в 19.00 Бг време.

Така за всеки ден.

Благодаря.
Не можеш да решиш проблемите с мисленето, с което си ги създал !

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 28 май 2018, 05:24

А какво да прави експерта, ако по някаква причина (напр. интернет) времето стане 14:10, а позициите все още не са отворени? Тоест в целия диапазон от 14 до 17 часа да могат да се отварят позиции, или например само в първите 10 минути след 14 часа?

Същото важи и за закриването на позициите. Какво да правим, ако поради някаква причина времето стане 20 часа или дори 3 през нощта, а позициите все още не са затворени?

Когато се програмира, кода трябва правилно да отработва всички възможни ситуации, които могат да се случат, дори и да са с много малка вероятност за случване. И тъй като в конкретния случай цикъла на експерта е едно денонощие, то той трябва да я наясно какво да прави във всяка една секунда от това денонощие. Логиката на експерта трябва да се преобразува така:

1. От толкова до толкова часа ако няма отворени позиции направи това, а ако има направи онова.
2. От толкова до толкова часа ако няма отворени позиции направи това, а ако има направи онова.
3. От толкова до толкова часа ако няма отворени позиции направи това, а ако има направи онова.
...........
Списъка от от диапазони от-до трябва да покрива всичките 24 часа, защото не се знае кога ще спре тока например и на експерта ще му се наложи да тръгне от начало, без да има информация какво се е случвало до момента.

Потребителски аватар
knestin
Мнения: 176
Регистриран: 28 яну 2015, 14:33
4 получени
2 дадени
Контакти:

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от knestin » 28 май 2018, 09:23

Благодаря за отговора.
Напълно съм съгласен с направените бележки.
Моята молба е ако можеш да направиш код /програма/ която да изпълнява предложените изходни данни, за да мога да тествам алгоритъма за определени интервали от време и т.н.
Когато говорим за експерт в реално време и пари : положението е съвсем друго.
Но на първо време ако е възможно ще те помоля за код за тестване на алгоритъма.

Поздрави
Не можеш да решиш проблемите с мисленето, с което си ги създал !

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 28 май 2018, 09:26

Ще го напиша, но след няколко дена, защото в момента ми предстои една планова проверка на Развъдната асоциация и имам много работа по подготовката.

Иначе най-добре е да се обявят 3 времена (Т1, Т2 и Т3). Позиците се отварят в периода Т1-Т2, живеят в периода Т2-Т3 и се затварят в периода Т3-Т1. Разбира се ако всичко е наред, действията ще се извършват в началото на дадения период, но ако нещо се обърка, допустимо е да се извършват и по-късно в рамките на целия период. Когато правиш исторически тестове, тези периоди можеш да ги зададеш като параметри, за да видиш коя комбинация е най-добра.

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 28 май 2018, 10:04

knestin написа:
27 май 2018, 19:32
1. В 14.00 Бг време откриваме sell EURUSD & buy EURUSD със SL= 30 и TP = 60 pipsa /по 4 знака/
2. В 14,00 Бг време откриваме sell AUDUSD & buy AUDUSD със SL = 25 и TP = 50 pipsa.
Всички сделки закриваме в 19.00 Бг време.
Между другото така описаната от тебе стратегия ще има голями разходи за спред (по 2 на ден). Логически може да се преобразува така, щото да хаби средно по 1 спред на ден или дори по-малко, и пак да се запази базовата логика. Например за EURUSD ще изглежда така:
1. Гледаме каква е била цената в 10:00 часа и я запомняме. Нека да я кръстим P.
2. Започваме да следим текущата цена до XX часа (или в следващите ММ минути).
3. Ако текущата цена стане P-30 пипса, отваряме SELL позиция със SL=60 и TP=30 и забраняваме отваряне на други позиции до 19 часа.
4. Ако текущата цена стане P+30 пипса, отваряме BUY позиция със SL=60 и TP=30 и забраняваме отваряне на други позиции до 19 часа.
5. След 19:00 часа при пръв удобен случай затваряме текущата позиция, ако все още е активна, и спираме да следим цената до другата сутрин.

Този алгоритъм прави същото като твоя, но на ден отваря не по 2 сделки, а само по една, или дори въобще не отваря, ако цената е заспала. Като цяло ще постига по-добър резултат от твоя алгоритъм, защото ще има икономия на спред.
Последна промяна от Mateev на 28 май 2018, 10:21, променено общо 5 пъти.

Потребителски аватар
тъпото копеле
Мнения: 1219
Регистриран: 10 фев 2011, 09:55
12 получени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от тъпото копеле » 28 май 2018, 10:10

knestin написа:
27 май 2018, 19:32
1. В 14.00 Бг време откриваме sell EURUSD & buy EURUSD със SL= 30 и TP = 60 pipsa /по 4 знака/
Това е идентично на един ОСО ордер с отложени бай и сел стоп на 30 пипа от текущата, всеки със съответен стоп от 60 пипа. Разликата е, че в твоя вариант се плащат два спреда вместо един.
При тези параметри е логично стартегията да дава 67% печеливши сделки по 30 пипа и 33% губещи по 60, като губи устойчиво по един спред на сделка. В твоя вариант - по два.

Потребителски аватар
knestin
Мнения: 176
Регистриран: 28 яну 2015, 14:33
4 получени
2 дадени
Контакти:

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от knestin » 31 май 2018, 22:01

Здравей Mateev.
Дали намери време да погледнеш и напишеш кода /за алгоритъма/ за който писах по-горе. Може с buy & stop и TP или с ордери sellstop и buystop.

Благодаря
Не можеш да решиш проблемите с мисленето, с което си ги създал !

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 01 юни 2018, 08:07

Планирам да го напиша сега в почивните дни. По принцип не се наемам да пиша кодове по заявка на други хора, но в конкретния случай ще го направя като пример как се пише един експерт така, че да е заключен в клас. Затварянето на един експерт в клас позволява много на брой експерти лесно да се вградят в един единствен такъв и да работят в паралел без да си пречат. Навих се да напиша твоя код именно поради тази причина - ти искаш два различни експерта да работят по две различни валутни двойки, но въпреки това да се обединят в един единствен код. Това всъщност е интересното нещо, което ме накара да реша публично да го покажа как се прави.

Mateev
Мнения: 289
Регистриран: 02 окт 2017, 10:04
52 получени
41 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Mateev » 01 юни 2018, 08:33

Има и още един интересен проблем при писането на експерти, и той е как да накараме много експерти едновременно да работят по много графики в един и същи MetaTrader, и да не си пречат или по-скоро да не се състезават един с друг за така наречения Trading Context. За който не знае, в един и същи момент от време MetaTrader може да отработва една единствена сделка. Тоест нишката, която прави търговски операции, е една единствена в рамките на MetaTrader-а. При това положение ако един експерт я заеме тази нишка, на всички други експерти ще им върне грешка при опит да я използват.

Този проблем се решава най-елегантно като се напише специален експерт, който ще се занимава само с това - отваряне и затваряне на сделки, а всички други експерти в MetaTrader-а само ще го молят да прави това от тяхно име. Тези молби ще създават опашка от чакащи за обработка търговски операции, и изпълнението на заявките от тази опашка ще може да се приоритизира съгласно желанията на трейдера, а не съгласно чистата случайност при конкуриращи се в реално време експерти.

Този код също мисля да го напиша и да го пусна в публичното пространство, но това ще стане някой друг почивен ден. В този код всъщност ще се демонстрира как могат различни експерти в един и същи MetaTrader да си "приказват" помежду си и да си прехвърлят информация един на друг или да се договарят за някакви съвместни действия (в случая да си изберат един единствен шеф, който да търгува от тяхно име).

Този код разрешава още един проблем - защитата от случайно пускане на един и същи експерт върху повече от една графики. При тази ситуация експертите трябва да детектират, че има повече от едно тяхно копие, и след това да се договорят помежду си само едно от всичките копия да извършва търговски операции, а останалите да работят в Read Only режим.

Евгени Йонков
Мнения: 5
Регистриран: 17 авг 2015, 14:06
1 получени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от Евгени Йонков » 01 юни 2018, 19:44

Ето един експерт генериран от EA Lab по идеята на knestin - предполагам доста далеч от съвършенството ако се пусне в реално време по причини, които Матеев подробно обясни, но мисля че за бектест върши работа. Вторият експерт също трябва да се сложи в папката Experts на платформата за да работи основния.

(Knestin, бях ти писал на ЛС преди време за една предишна твоя идея, но не знам дали не прояви интерес или се трият личните съобщения ако не се отворят определено време, че и аз рядко влизам тук)


knestinEA.ex4
(11.04 KБ) Свален 4 пъти
TVI_EALab_3_5.ex4
(61.86 KБ) Свален 3 пъти
http://www.myfxbook.com/members/EYonkov

Потребителски аватар
saxsten
Мнения: 1365
Регистриран: 04 апр 2010, 23:16
9 получени
3 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от saxsten » 02 юни 2018, 14:06

Mateev » 01 юни 2018, 06:07 Планирам да го напиша...
Mateev » 01 юни 2018, 06:33...Този код също мисля да го напиша


Когато от умрял човек писмо получите тогава и от Матеев нещо полезно ще научите
Намерихте черква да се прекръстите
Луд човек, може ли кодове да пише?
Много ще ми е интересно да ги видя. :grin:
Форекса е оръжие за масово поразяване

Потребителски аватар
saxsten
Мнения: 1365
Регистриран: 04 апр 2010, 23:16
9 получени
3 дадени

Re: ЕА, скриптове, индикатори и т.н. с ОТВОРЕН КОД

Мнение от saxsten » 02 юни 2018, 14:28

Има брокери, които не вземат допълнителен спред при отварянето на насрещна позиция
Форекса е оръжие за масово поразяване

Отговори

Върни се в “FOREX СИГНАЛИ, СИСТЕМИ И СТРАТЕГИИ”

Кой е на линия

Потребители, разглеждащи този форум: Няма регистрирани потребители и 4 госта