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

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

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

Мнение от saxsten » 23 май 2018, 18:43

Mateev написа:
23 май 2018, 13:07
-----------------------------------
Матеев ти си напълно безнадежден случай
Това че не правиш разлика между тикова волативност и Price Volatility простено да ти е
Най-добре спри да се занимаваш с мен ,защото от теб нищо не може да се научи
А ако спреш да се занимаваш с форекс ,още по добре за форекса
......................
Тук няма ли игнор да те напъхам в него че да мирясаш :grin:
Форекса е оръжие за масово поразяване

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

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

Мнение от Mateev » 23 май 2018, 22:19

Първо трябва да се научиш, че се пише ВОЛАТИЛНОСТ, а не ВОЛАТИВНОСТ.
Второ волатилноста винаги представлява ПРОЦЕНТ НА ПРОМЯНАТА за единица време, а не БРОЙ НА НЕЩОТО за единица време.
Трето ако се използва думичката волатилност, без уточнение на какво, хората си представят ЦЕНИ, а не ТИКОВЕ, и ИЗМЕНЕНИЕ, а не БРОЙКА.
Под волатилен пазар се разбира ПАЗАР С БЪРЗО ДВИЖЕЩИ СЕ ЦЕНИ, а не голям брой сделки, направени на този пазар, или много на брой тикове, излъчени от някой брокер с нервен алгоритъм за формиране на цени.

Съжалявам че ти го казвам, но с всеки следващ постинг се излагаш все повече и повече, и пишеш все повече и повече простотии, които ЖИВЕЯТ САМО В ТВОЯТА ГЛАВА. Все повече започваш да ми приличваш на Ангел със сбърканата психика и надутото самочувствие, който половин година защитава тезата, че котлоните били някаква форма на климатици, а пазара бил "наклонен".

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

И преди да ми отговориш отново с някоя простотия, направи справка в интернет, защото наистина последните ти десетина постинга са много смешни, и всички го видяха това. Сега не знам как ще изтриеш срама и позора от себе си, но аз нямам никаква вина за това. Опитах се в началото тактично да ти напиша за какво става въпрос, а ти вместо да се засрамиш, започна с рогата напред да ръсиш глупост след гпупост. Осъзнай се човече .....

Потребителски аватар
p_dim
Мнения: 420
Регистриран: 12 фев 2013, 17:43
41 получени
53 дадени

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

Мнение от p_dim » 24 май 2018, 19:26

@saxsten,
то нали проблема беше, че не може да се хване кой е последния затворен ордер в историята, защото ако са затворени в една и съща секунда (да кажем с цикъл), няма как да се различи кой е последен. Това дето си писал последно, ще събира печалбата за деня или нещо такова. С нищо не решава проблема. Давам ти пример с GDAX, където времевата щампа на изпълнен ордер е даже в микросекунди, а не в милисекунди и изглежда примерно така:

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

2017-12-01T05:33:56.761199Z
(Последното 'Z' означава Zero GMT offset, т.е. че времето е по Гринуич по ISO 8601). Вече цепят секундата на 1 милион хората, а Метакуотци си я карат като по времето на Pentium 1 :grin:

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

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

Мнение от Mateev » 25 май 2018, 19:07

saxsten написа:
21 май 2018, 22:32
Ето какво стана с функцията

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

   int HOrder()  
    
   {  HProfit =0;k =0; y=0;HClose1=0; h =0;  ctn =0 ;  z =0 ;   if (z <100 ) ctn = 0  ; 
       int HTotal = OrdersHistoryTotal();      
           z=(TimeCurrent()-iTime(NULL,PERIOD_D1,0)) ;           
  //================================================            
       {for (i = 0; i < HTotal; i++) 
     {  if ( OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic )         
        HProfit = HProfit+OrderProfit(); HProfit = NormalizeDouble(HProfit,2);         }}   
    //================================================
        {for (i = 0; i < HTotal; i++) 
     {  if ( OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true&& OrderMagicNumber() == Magic )             
         ctn = ctn+1  ;       }} return(0);}
Брои всички закрити сделки както и печалбата по тях.
Параметъра z <= 86400 докато пристигне новият нулев бар iTime(NULL,PERIOD_D1,0)
Някой има ли идея как да спрем броенето когато се е появил новият бар и да съхраниме резултатите ,и да започнем да броим отново докато се появи следващият нулев бар
saxsten,
Ако спреш да се заяждаш, съм готов да ти помогна по-бързо да навлезеш в програмирането на MQL и по-лесно да пишеш оптимален код. По показаното от тебе до момента си личи, че си в много начален стадий от развитието си като програмист. Това не го казвам за да те обидя, а защото си има начини как да се пише код така, щото да става бързо и лесно, и да се допускат колкото се може по-малко грешки в него - синтактични и/или логически.

В показаната от тебе горна функция има няколко логически грешки, както и демонстрация на много лош стил за програмиране, който лесно ще те вкара в капан, когато започне да нараства сложноста на твоите проекти. Накратко ще ги изредя:
1. Пишеш функция, която да връща някаква int променлива, а всъщност винаги връщаш нула. Какъв е смисъла от това?
2. В горния код всъщност има не една, а две различни функции, които вместо да връщат резултата по правилния начин, директно работят с глобални променливи.
3. Горния код въпреки че уж е функция, всъщност бъзика стойностите на една камара глобални променливи. Това е много лош стил на програмиране.
4. Горната функция за да е универсална и за да може да се използва винаги и навсякъде трябва да приема параметри при стартирането си за използваните в нея mode, symbol и magic number.
5. Кода "if (z <100 ) ctn = 0 ;" е напълно излишен и нищо не прави, защото преди него както z, така и cnt вече са нулирани.
6. Кода "z=0;" също е излишен, защото след него винаги има присвояване на стойноста на z (z=(TimeCurrent()-iTime(NULL,PERIOD_D1,0)) ;).
7. Въобще това z не му е мястото в тази функция, защото касае времето на нулевия бар, а не ситуацията с ордерите.
8. Не им е мястово в тази функция и на променливите k, y, h и HClose1
9. В кода "if ( OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true ....." това "==true" е напълно излишно. И без него кода ще си работи по същия начин, защото ако OrderSelect вече е върнал true, няма смисъл пак да го сравняваме с true, за да получим отново true. То вече си е true.
10. Всеобщо прието е при програмиране локалните променливи да започват с малка буква, а глобалните - с голяма. Така човек по-лесно се ориентира при четене на кода. При тебе това не е спазено.
11. Подредбата на кода също така е направена по възможно най-лошия начин така, щото човек да се взира в него половин час, докато осъзнае какво всъщност си искал да напишеш. С такъв стил на програмиране се допускат много грешки и бъговете се откриват много трудно. Логическото проследяване на кода и контрола на сложноста също са почти невъзможни.

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

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

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

Мнение от Mateev » 25 май 2018, 19:46

Започваме с малко преподреждане на кода, за да си изясним какво всъщност си искал да напишеш:

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

int HOrder()  
  {
    HProfit=0; k=0; y=0;HClose1=0; h=0; ctn=0; z=0; if (z <100 ) ctn = 0; 
    int HTotal = OrdersHistoryTotal();      
    z=(TimeCurrent()-iTime(NULL,PERIOD_D1,0));           
    //================================================            
    {
      for (i = 0; i < HTotal; i++) 
        {
          if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)         
            HProfit = HProfit+OrderProfit();
            HProfit = NormalizeDouble(HProfit,2);
        }
    }   
    //================================================
    for (i = 0; i < HTotal; i++) 
     {
       if ( OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true&& OrderMagicNumber() == Magic )             
         ctn = ctn+1;
     }
  } 
  return(0);
  }
Веднага откриваме, че броя на отварящите и затварящите големи скоби не е еднакъв, и компилатора генерира десетки грешки. Освен това си слагал скоби дори и там, където не е необходимо. Изчистваме проблема със скобите и получаваме това:

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

int HOrder()  
  {
    HProfit=0; k=0; y=0;HClose1=0; h=0; ctn=0; z=0; if (z <100 ) ctn = 0; 
    int HTotal = OrdersHistoryTotal();      
    z=(TimeCurrent()-iTime(NULL,PERIOD_D1,0));           
    //================================================            
    for (i = 0; i < HTotal; i++) 
      {
        if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)         
          HProfit = HProfit + OrderProfit();
          HProfit = NormalizeDouble(HProfit,2);
      }
    //================================================
    for (i = 0; i < HTotal; i++) 
     {
       if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)             
         ctn = ctn+1;
     }
  return(0);
  }

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

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

Мнение от saxsten » 25 май 2018, 20:06

Матеев ,колко пъти да ти казвам да не се занимаваш с мен и пази боже да ми помагаш
Матеев ти олигофрен ли си що ли
Форекса е оръжие за масово поразяване

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

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

Мнение от Mateev » 25 май 2018, 20:06

Изхвърляме ненужните глобални променливи и декларираме останалите, които уж са нужни. Също така изхвърляме ненужния if, който проверява дали z<100. Получи се този код, който вече се компилира без грешка:

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

int i,ctn, Magic;
double HProfit;
datetime z;

int HOrder()  
  {
    HProfit=0; ctn=0; z=0; 
    int HTotal = OrdersHistoryTotal();      
    z=(TimeCurrent()-iTime(NULL,PERIOD_D1,0));           
    //================================================            
    for (i = 0; i < HTotal; i++) 
      {
        if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)         
          HProfit = HProfit + OrderProfit();
          HProfit = NormalizeDouble(HProfit,2);
      }
    //================================================
    for (i = 0; i < HTotal; i++) 
     {
       if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)             
         ctn = ctn+1;
     }
    return(0);
  }
Изхвърляме сметките за z, защото въобще не им е мястото в тази функция. Също така брояча i от глобален го правим на локален, защото така е редно. При това го правим не локален в рамките на функцията, а локален само в рамките на цикъла. Така е редно да се прави. Получаваме следния код:

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

int HOrder()  
  {
    HProfit=0; ctn=0; 
    
    int HTotal = OrdersHistoryTotal();      
    for (int i = 0; i < HTotal; i++) 
      {
        if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)         
          HProfit = HProfit + OrderProfit();
          HProfit = NormalizeDouble(HProfit,2);
      }
    //================================================
    for (int i = 0; i < HTotal; i++) 
     {
       if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)             
         ctn = ctn+1;
     }
    return(0);
  }

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

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

Мнение от saxsten » 25 май 2018, 20:15

Mateev написа:
25 май 2018, 20:06
Изхвърляме ненужните глобални променливи и декларираме останалите, които уж са нужни. Също така изхвърляме ненужния if, който проверява дали z<100. Получи се този код, който вече се компилира без грешка:

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

int i,ctn, Magic;
double HProfit;
datetime z;

int HOrder()  
  {
    HProfit=0; ctn=0; z=0; 
    int HTotal = OrdersHistoryTotal();      
    z=(TimeCurrent()-iTime(NULL,PERIOD_D1,0));           
    //================================================            
    for (i = 0; i < HTotal; i++) 
      {
        if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)         
          HProfit = HProfit + OrderProfit();
          HProfit = NormalizeDouble(HProfit,2);
      }
    //================================================
    for (i = 0; i < HTotal; i++) 
     {
       if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)             
         ctn = ctn+1;
     }
    return(0);
  }
Изхвърляме сметките за z, защото въобще не им е мястото в тази функция. Също така брояча i от глобален го правим на локален, защото така е редно. При това го правим не локален в рамките на функцията, а локален само в рамките на цикъла. Така е редно да се прави. Получаваме следния код:

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

int HOrder()  
  {
    HProfit=0; ctn=0; 
    
    int HTotal = OrdersHistoryTotal();      
    for (int i = 0; i < HTotal; i++) 
      {
        if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)         
          HProfit = HProfit + OrderProfit();
          HProfit = NormalizeDouble(HProfit,2);
      }
    //================================================
    for (int i = 0; i < HTotal; i++) 
     {
       if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic)             
         ctn = ctn+1;
     }
    return(0);
  }
Матеев ,колко пъти да ти казвам да не се занимаваш с мен и пази боже да ми помагаш
Матеев ти олигофрен ли си що ли
Форекса е оръжие за масово поразяване

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

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

Мнение от Mateev » 25 май 2018, 20:24

Това, което го пиша, е полезно не само за тебе, но и за другите хора, които четат темата. Нагледно давам пример как се оптимизира някакъв код и как се изчистват грешките от него.

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

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

int ctn, Magic;
double HProfit;

int HOrder()  
  {
    HProfit=0; ctn=0; 
    
    int HTotal = OrdersHistoryTotal();      
    for (int i = 0; i < HTotal; i++) 
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) && OrderMagicNumber() == Magic)         
        HProfit = HProfit + OrderProfit();
    HProfit = NormalizeDouble(HProfit,2);
    //================================================
    for (int i = 0; i < HTotal; i++) 
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) && OrderMagicNumber() == Magic)             
         ctn = ctn+1;
    return(0);
  }

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

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

Мнение от saxsten » 25 май 2018, 20:29

p_dim написа:
24 май 2018, 19:26
@saxsten,
то нали проблема беше, че не може да се хване кой е последния затворен ордер в историята, защото ако са затворени в една и съща секунда (да кажем с цикъл), няма как да се различи кой е последен. Това дето си писал последно, ще събира печалбата за деня или нещо такова. С нищо не решава проблема. Давам ти пример с GDAX, където времевата щампа на изпълнен ордер е даже в микросекунди, а не в милисекунди и изглежда примерно така:

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

2017-12-01T05:33:56.761199Z
(Последното 'Z' означава Zero GMT offset, т.е. че времето е по Гринуич по ISO 8601). Вече цепят секундата на 1 милион хората, а Метакуотци си я карат като по времето на Pentium 1 :grin:
не бе димич това проблемче го реших и тук нарочно не пущам този ред от кода
това де то съм написал събира печалбата от как е пуснат експерта пък мен ми трябва да събира само печалбата от 1 ден назад
С две думи когато z= 0 или пък
ако TimeCurrent()-iTime(NULL,PERIOD_D1,0)= 0 ;
тоест когато се появил нов нулев бар


Променливите HProfit =0;HClose1=0; ctn =0 ; z =0 ; if (z <100 ) ctn = 0 ; се дефинират извън тялото на тази функция така че не и мисли

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

 int HOrder()   
    
   {[u]  HProfit =0;HClose1=0;   ctn =0 ;  z =0 ;   if (z <100 ) ctn = 0  ;[/u] 
       int HTotal = OrdersHistoryTotal();      
           z=(TimeCurrent()-iTime(NULL,PERIOD_D1,0)) ;           
  //================================================            
       {for (i = 0; i < HTotal; i++) 
     {  if ( OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true && OrderMagicNumber() == Magic )         
        HProfit = HProfit+OrderProfit(); HProfit = NormalizeDouble(HProfit,2);         }}   
    //================================================
        {for (i = 0; i < HTotal; i++) 
     {  if ( OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) == true&& OrderMagicNumber() == Magic )             
         ctn = ctn+1  ;       }} return(0);}
А бе аз кажи речи съм си решил проблема пък и нещо Матеев се втурнал да ми "помага" че пази Боже :x
Последна промяна от saxsten на 25 май 2018, 20:38, променено общо 1 път.
Форекса е оръжие за масово поразяване

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

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

Мнение от Mateev » 25 май 2018, 20:38

Все още не сме оправили безсмисления факт, че функцията винаги връща нула. Няма смисъл и да го оправяме, защото функцията всъщност трябва да се раздели на 2 функции, и всяка една от тях да връща това, за което е създадена. Ето какво се получи след разделянето на две функции:

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

int Magic;

//================================================ 
// Връща сумата от печалба/загуба на всички затворени позиции
double ClosedPositionsPL()  
  {
    double hProfit=0;    
    int hTotal = OrdersHistoryTotal();      
    for (int i = 0; i < hTotal; i++) 
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) && OrderMagicNumber() == Magic)         
        hProfit += OrderProfit();
    return(NormalizeDouble(hProfit,2));
  }    
  
//================================================  
// Връща броя на затворените позиции
int ClosedPositionsCount() 
  { 
    int cnt=0; 
    int hTotal = OrdersHistoryTotal();   
    for (int i = 0; i < hTotal; i++) 
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) && OrderMagicNumber() == Magic)             
        cnt++;
    return(cnt);
  }

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

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

Мнение от saxsten » 25 май 2018, 20:44

Mateev написа:
25 май 2018, 20:38
Все още не сме оправили безсмисления факт, че функцията винаги връща нула. Няма смисъл и да го оправяме, защото функцията всъщност трябва да се раздели на 2 функции, и всяка една от тях да връща това, за което е създадена. Ето какво се получи след разделянето на две функции:

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

int Magic;

//================================================ 
// Връща сумата от печалба/загуба на всички затворени позиции
double ClosedPositionsPL()  
  {
    double hProfit=0;    
    int hTotal = OrdersHistoryTotal();      
    for (int i = 0; i < hTotal; i++) 
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) && OrderMagicNumber() == Magic)         
        hProfit += OrderProfit();
    return(NormalizeDouble(hProfit,2));
  }    
  
//================================================  
// Връща броя на затворените позиции
int ClosedPositionsCount() 
  { 
    int cnt=0; 
    int hTotal = OrdersHistoryTotal();   
    for (int i = 0; i < hTotal; i++) 
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY) && OrderMagicNumber() == Magic)             
        cnt++;
    return(cnt);
  }
Матеев ти тука топлата вода ли ще откриваш
спри се да ми "помагаш" бре :twisted: само за беля ходиш наоколо 8-)
Форекса е оръжие за масово поразяване

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

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

Мнение от Mateev » 25 май 2018, 20:51

saxsten написа:
25 май 2018, 20:29
А бе аз кажи речи съм си решил проблема пък и нещо Матеев се втурнал да ми "помага" че пази Боже :x
Ти като че ли не четеш какво съм написал. Твоя код бъка от грешки и безсмислици, и разбира се не се компилира. Предлагам следващия път преди да пуснеш някакъв код, поне го провери дали се компилира....
Последна промяна от Mateev на 25 май 2018, 21:31, променено общо 1 път.

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

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

Мнение от 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 милион реда код. Мога да ти помагам с такива казуси, които от време на време поставяш във форума, но не разбирам защо се противиш на това. Уж търсиш помощ, а после не я приемаш.

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

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

Мнение от Mateev » 25 май 2018, 22:21

Набързо написах една функция, която ако се стартира на всеки тик, ще детектира появата на нов бар по който и да е символ в който и да е негов TimeFrame (период). Старата стойност на времето на последния бар, през който е работил експерта, се запомня в пространството за глобални променливи на MetaTrader и се съхранява там за период до 4 седмици дори и когато MetaTrader е изключен.

Функцията работи стабилно, надеждно и вярно при всички възможни гафове, които могат да се случат по време на експлоатацията:
- Reconect на MetaTrader-a (временно прекъсване на интернет връзката)
- Restart на експерта (спиране за неопределено време и повторно пускане)
- Restart на компютъра (спиране за период до 4 седмици и повторно пускане)
- Смяна на експерта с по-нова негова версия.
- При смяна на бара връща True само при първото си извикване, и False на всяко следващо извикване в рамките на бара
- Функцията работи безпогрешно както в режим RealTime, така и по време на исторически тестове със Strategy Tester-a

Формирането на стринговото име на променливата се прави така, щото да не се сблъскват променливи дори и тогава, когато функцията се извиква от различни експерти по различни символи в различен TimeFrane на съответната графика. Ето кода, който се получи:

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

//================================================ 
// Връща True, ако е детектиран нов бар за даден символ и период.
// Старата стойност на DateTime на нулевия бар се съхранява за
// 4 седмици в глобалното пространство за променливи на самия MetaTrader

bool IsNewBar(string symbol, ENUM_TIMEFRAMES period)  
  {
    string   globalName = symbol + " Last Bar " + IntegerToString(period) + " Time";
    datetime oldBarTime = (datetime)GlobalVariableGet(globalName);
    datetime newBarTime = iTime(symbol, period,0);
    bool     isNewBar   = newBarTime != oldBarTime;
    if (isNewBar) GlobalVariableSet(globalName, newBarTime); 
    return(isNewBar);
  }
ПП: Функцията няма да работи правилно, ако на няколко графики има няколко различни експерта върху един и същи символ и един и същи период. За да се модифицира да работи и при такива условия, трябва като параметър да се предаде и числото Magic, което след това да се преобразува като стринг и да участва във формирането на името на променливата. Ето например как изглежда тази модифицирана версия:

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

//================================================ 
// Връща True, ако е детектиран нов бар за даден символ и период.
// Старата стойност на DateTime на нулевия бар се съхранява за
// 4 седмици в глобалното пространство за променливи на самия MetaTrader

bool IsNewBar(int magic=0, string symbol=NULL, ENUM_TIMEFRAMES period=PERIOD_CURRENT)  
  {
    string   globalName = symbol + " Last Bar " + IntegerToString(period) + " Time and Magic " + IntegerToString(magic);
    datetime oldBarTime = (datetime)GlobalVariableGet(globalName);
    datetime newBarTime = iTime(symbol, period,0);
    bool     isNewBar   = newBarTime != oldBarTime;
    if (isNewBar) GlobalVariableSet(globalName, newBarTime); 
    return(isNewBar);
  } 
В тази модифицирана версия добавих и стойности на параметрите по подразбиране, за да може функцията да се извиква и без параметри или с по-малко на брой параметри. Ако се извика без параметри, ще работи върху текущия символ по текущия TimeFrame и с Magic=0. Имайте предвид, че числото Magic се използва само за това да се получи различно име на променлива в глобалното пространство и съвсем не е задължително в него да се вписва истинския Magic Number. Достатъчно е само да е различно, ако два различни експерта работят на един и същи символ в един и същи TimeFrame.

Потребителски аватар
p_dim
Мнения: 420
Регистриран: 12 фев 2013, 17:43
41 получени
53 дадени

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

Мнение от p_dim » 26 май 2018, 00:55

@Mateev,
:good: Само е добре да уточня, че функцията ще работи добре в OnTick(), но не и в OnTimer(). Причината мисля, че е ясна: ако се загуби връзка със сървъра, OnTick() просто ще спи и няма да се задейства нищо от написаното в кода. Не е така обаче, ако функцията се изпълнява в OnTimer(). Изпълнението на функцията пак трябва да разпознае дали е започнал нов бар или не, без значение че не може да се предприемат някакви търговски действия, защото е пропаднала връзката със сървъра. Това може да стане обаче само за МТ5, където има една нова глезотия TimeTradeServer() и я няма в МТ4. Това животинче ще изчисли какво е времето на сървъра, на база текущото време в нашия комп, т.е. без да е нужна връзка със сървъра. Така може да изчислим дали сме в нов бар или не, без връзка със сървъра. Давам примерен код, като използвам кода на Матеев и пак да повторя, че е за МТ5 със забележка, че не съм го пробвал, но изглежда, че така трябва да е:

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

#define TIMER_MSC 100
#define  Magic 112233

int OnInit()
{
   if (!EventSetMillisecondTimer(TIMER_MSC) { Print("Греда с таймера...!"); return(INIT_FAILED);
   return(INIT_SUCCEEDED);
}

//---------------------------------------------------------------------

void OnDeinit(const int reason) { EventKillTimer(); }

//---------------------------------------------------------------------

void OnTimer()
{
   if (IsNewBar(Magic,_Symbol,PERIOD_M10)) // Ако има нов бар в М10
   {............}
   else
   {............} 
}

//---------------------------------------------------------------------

bool IsNewBar(int magic=0, string symbol=NULL, ENUM_TIMEFRAMES period=PERIOD_CURRENT)  
{
    string   globalName = symbol + " Last Bar " + IntegerToString(period) + " Time and Magic " + IntegerToString(magic);
    datetime oldBarTime = (datetime)GlobalVariableGet(globalName);
    datetime serverTime = TimeTradeServer();
    datetime newBarTime =  datetime(serverTime - (serverTime%(60* (int)period))); 
    bool     isNewBar   = newBarTime != oldBarTime;
    if (isNewBar) GlobalVariableSet(globalName, newBarTime); 
    return(isNewBar);
} 


Потребителски аватар
p_dim
Мнения: 420
Регистриран: 12 фев 2013, 17:43
41 получени
53 дадени

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

Мнение от p_dim » 26 май 2018, 11:59

Реших да проверя все пак какво съм писал снощи на 2+ бири, че да не подведа неволно някой колега. Е, изял съм някоя и друга скобичка, но кода си бачка. Ама какво виждам: неволно хващам поредната Метакуотска бъгавщина! Не съм го казвал, ама пак повтарям: това MQL-а си е куцо та дрънка... 8-) Подавам на функцията PEROD_CURRENT и очаквам да се подаде за изпълнение текущия ТаймФрейм от графиката където е закачен експерта, а ми изплюва грешка zero_divide! Абе мое ли Експерта да е инициализиран, а константата PERIOD_CURRENT още да не е и да връща нула? Кога ще ги оправят най-накрая тия срамотии? Те така...
В момента пазара е затворен (събота е), но нищо не пречи на пробата. Подавам на функцията PERIOD_M5 и закачам бота на М1 (то е без значение на кой фрейм ще се закачи). С таймера ще проверява дали имаме нов бар в М5. Резултат: всичко си бачка според очакванията. Разбира се за реално използване, функцията трябва да се върже с SymbolInfoSessionQuote() за да се извиква само когато сме в работно време за инструмента и да не отчита "нов бар" през почивните дни или в неработно време на борсата където се търгува. Така няма да сбърка и коректно ще отброи, че има нови барове от последното извикване, дори да е имало загуба на връзката със сървъра. С първия вариант в OnTick(), след възстановяване на връзката не е ясно колко бара са прескочени, а това може да е важно за стратегията.

IsNewBar.png
IsNewBar.png (31.67 KБ) Видяна 253 пъти

Ето го тествания код, с оправени скоби, в тяло на Експерт:

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

//+------------------------------------------------------------------+
//|                                                ProbaTimerMsc.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#define TIMER_MSC 100
#define  Magic 112233

int OnInit()
{
   if (!EventSetMillisecondTimer(TIMER_MSC)) { Print("Греда с таймера...!"); return(INIT_FAILED); }
   return(INIT_SUCCEEDED);
}

//---------------------------------------------------------------------

void OnDeinit(const int reason) { EventKillTimer(); }

//---------------------------------------------------------------------

void OnTimer()
{
   if (IsNewBar(Magic,_Symbol,PERIOD_M5)) // Ако има нов бар в М5
   { Print("Започва нов бар..."); }
 
}

//---------------------------------------------------------------------

bool IsNewBar(int magic=0, string symbol=NULL, ENUM_TIMEFRAMES period=PERIOD_CURRENT)  
{
    string   globalName = symbol + " Last Bar " + IntegerToString(period) + " Time and Magic " + IntegerToString(magic);
    datetime oldBarTime = (datetime)GlobalVariableGet(globalName);
    datetime serverTime = TimeTradeServer();
    datetime newBarTime =  datetime(serverTime - (serverTime%(60* (int)period))); 
    bool     isNewBar   = newBarTime != oldBarTime;
    if (isNewBar) GlobalVariableSet(globalName, newBarTime); 
    return(isNewBar);
} 

//+------------------------------------------------------------------+

Потребителски аватар
p_dim
Мнения: 420
Регистриран: 12 фев 2013, 17:43
41 получени
53 дадени

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

Мнение от p_dim » 26 май 2018, 12:53

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

PERIOD_CURRENT.png
PERIOD_CURRENT.png (25.29 KБ) Видяна 245 пъти
Функцията ще трябва да се извиква с Period() за параметър, тя връща enum-а на текущия фрейм. :-? При Метакуотци всичко е "думам ти дъще, сещай се снахо..." :lol:

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

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

Мнение от Mateev » 26 май 2018, 13:02

Съгласен съм с корекцията, но ти вече предлагаш съвсем друга функция, която да върши съвсем друга работа. Моята функция детектира наличието на нов бар тогава, когато той НАИСТИНА СЕ ПОЯВИ. Твоята функция детектира ДАЛИ Е НАСТЪПИЛО ВРЕМЕТО за нов бар, независимо от това дали той се е появил или не. Така че според мене двете функции трябва да имат различни имена и в зависимост от логиката да се ползва или едната, или другата. Предлагам следното по отношение на имената на двете функции:

IsNewBar - Моята функция, която проверява дали наистина е дошъл нов бар.
IsTimeForNewBar - Твоята функция, която проверява дали е настъпило времето за нов бар, независимо дали той е дошъл или не.

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

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

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

string   globalName = "Function IsNewBar " + symbol + " Last Bar " + IntegerToString(period) + " Time and Magic " + IntegerToString(magic);
а при твоята функция трябва да изглежда така:

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

string   globalName = "Function IsTimeForNewBar " + symbol + " Last Bar " + IntegerToString(period) + " Time and Magic " + IntegerToString(magic);

Потребителски аватар
p_dim
Мнения: 420
Регистриран: 12 фев 2013, 17:43
41 получени
53 дадени

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

Мнение от p_dim » 26 май 2018, 14:03

Точно така, аз нищо не съм "коригирал", само дадох решение в различен аспект :good:

Отговори

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

Кой е на линия

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