Problem z pętlą

O jezykach programowania w platformach i nie tylko.
tonicipriani
Bywalec
Bywalec
Posty: 5
Rejestracja: 23 lip 2009, 18:32

Problem z pętlą

Nieprzeczytany post autor: tonicipriani »

Witam,
napisałem prostego EA i nie działa podczas testów. Wygląda na to, że expert wchodzi w pętle i wtedy dane testowe przestają napływać. Warunkiem wyjścia z pętli jest odpowiednia zmiana ceny. Poniżej zamieszczam kod. Proszę bardziej doświadczonych o pomoc. Pzdr!

Kod:

Kod: Zaznacz cały


//+------------------------------------------------------------------+
//|                                                       SO v01.mq4 |
//|                                   Copyright 2010 Adrian Gasiński |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010 Adrian Gasiński"
#property link      ""
double maks=10000, min=0, cena_otwarcia;
int numer_zlecenia;


//---- input parameters
extern int       lot;
extern int       sl;

void Inicjator(){
   if(Hour()==7 && Minute()>54){
      maks=High[iHighest(NULL, PERIOD_H1, MODE_HIGH, 3, 0)]; //określenie jakie było maksimum dla 3 ostatnich swiec
      min=Low[iLowest(NULL, PERIOD_H1, MODE_LOW, 3, 0)]; //określenie jakie było minimum dla 3 ostatnich swiec
   }
}

void SprawdzDluga(){ //funkcja sprawdzajaca czy nie nalezy otworzyc dlugiej pozycji
    if (Ask>maks){
      cena_otwarcia=Ask;
      numer_zlecenia=OrderSend(Symbol(),OP_BUY,lot,Ask,20*Point,0,0,NULL,0,0,Blue);
      
    }
}

void SprawdzKrotka(){
   if (Bid<min){
      cena_otwarcia=Bid;
      numer_zlecenia=OrderSend(Symbol(),OP_SELL,lot,Bid,20*Point,0,0, NULL,0,0, Red);      
     
   }
}


void SprawdzCzyZamknac(){
   
   if(Bid>cena_otwarcia+sl*Point || Ask<cena_otwarcia-sl*Point){
      OrderClose(numer_zlecenia,lot,Ask,7*Point,Green);
   }
   
}

int init()
  {

   return(0);
  }

int deinit()
  {

   return(0);
  }

int start()
  {
   Inicjator();
   if(min-maks<40*Point){
      
      while(OrdersTotal()==0){
         SprawdzKrotka();
         SprawdzDluga();
      }
   
   }
   
   while(OrdersTotal()>0){
      SprawdzCzyZamknac();
   }
   
   return 0;
   
  }

LowcaG
Pasjonat
Pasjonat
Posty: 1068
Rejestracja: 05 paź 2007, 15:39

Nieprzeczytany post autor: LowcaG »

hm...no juz wpada na starcie w petle

masz

Kod: Zaznacz cały

      while(OrdersTotal()==0){ 
i liczysz, ze
SprawdzKrotka lub SprawdzDluga, otworzy jakas pozycje i wtedy wyskoczysz z petli...

Problemem jest to, ze Ask i Bid Ci sie nie zmienia podczas tej petli, i dlatego jezeli ktoras z tych funkcji nie otworzy od razu pozycji to juz ich nie otworzy i Ci sie zapetla...

masz pare rozwiazan
1. Mniej eleganckie i nie polecam...to uzyc RefreshRates w funkcjach otwierajacych, zeby Ci sie Ask i Bid zaktualizowalo.

2.) wywalic w ogole te while i dac if y.

tonicipriani
Bywalec
Bywalec
Posty: 5
Rejestracja: 23 lip 2009, 18:32

Nieprzeczytany post autor: tonicipriani »

Wielkie dzięki ;) Bardzo pomogłeś.

Użyłem pętli, ponieważ, nie wiem czy słusznie myślałem, że wówczas poślizgi będą mniejsze,

tonicipriani
Bywalec
Bywalec
Posty: 5
Rejestracja: 23 lip 2009, 18:32

Nieprzeczytany post autor: tonicipriani »

Jeszcze raz proszę o pomoc. Żeby było łatwiej to opiszę co EA ma robić. Otóż o 7:58 ma sprawdzać minimum i maksimum z ostatnich 3 świec(H1). Jeśli różnica jest mniejsza od 50 pipsów to, gdy cena wybija się z utworzonego przez minimum i maksimum korytarza otwiera pozycję(taki typowy breakout). Cały problem polega na tym, że wszystko ma się dziać raz dziennie. Aby tak było stworzyłem 2 zmienne: dzien, i iterator. Dzień jest inkrementowany, po każdym ustaleniu minimum i maksimum(wew. metody inicjator),na początku ma wartość 0. A iterator na początku ma wartość 1 później jest inkrementowany na 3 różne sposoby:
1. Gdy zostaje zamknięta pozycja(metoda SprawdzCzyZamknac)
2. Gdy różnica maks-min jest większa od 50 pipsów.
3. Gdy różnica jest mniejsza, ale nie do godz.3.00 żadna pozycja nie została tego dnia otwarta.

Idea jest taka, ze pozycje są otwierane tylko wtedy gdy iterator jest równy zmiennej dzień, która jest zwiększana raz dziennie o 7:58:00.

Wszystko działało, aż miło dopóki dane w testach były automatycznie pobierane. Jednak okres testu na który pozwalały był za krótki, więc wszedłem w Centrum Historii MetaTrader'a i pobrałem dostępne dane dla GBPUSD.

Tu zaczęły się problemy. Ponieważ teraz Inicjator() jest wykonywany, nie raz dziennie, a 6 razy dziennie. Domyślam się, że chodzi o dokładność danych i nie pomaga tu warunek if(Hour()==7 && Minute()==58 && Seconds()==0), ponieważ na dokładnych danych w ciągu jednej sekundy EA jest w stanie wykonać się 6 razy (?!).

Proszę o pomoc. Macie jakieś pomysły jak to można rozwiązać?

Dodano po 37 sekundach:

Kod: Zaznacz cały

//+------------------------------------------------------------------+
//|                                                       SO v01.mq4 |
//|                                   Copyright 2010 Adrian Gasiński |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010 Adrian Gasiński"
#property link      ""
double maks=10000, min=0, cena_otwarcia;
int numer_zlecenia, dzien=0, iterator=1;
bool dluga;


//---- input parameters
extern int       lot;
extern int       sl;

void Inicjator(){
   
      RefreshRates();
      maks=High[iHighest(NULL, PERIOD_H1, MODE_HIGH, 3, 0)]; //określenie jakie było maksimum dla 3 ostatnich swiec
      min=Low[iLowest(NULL, PERIOD_H1, MODE_LOW, 3, 0)]; //określenie jakie było minimum dla 3 ostatnich swiec
      dzien++;
      Alert("Inicjator wykonany dzien = ");
      Alert(dzien);
   
}

void SprawdzDluga(){ //funkcja sprawdzajaca czy nie nalezy otworzyc dlugiej pozycji
    if (Ask>maks){
      cena_otwarcia=Ask;
      numer_zlecenia=OrderSend(Symbol(),OP_BUY,lot,Ask,20*Point,0,0,NULL,0,0,Blue);    
      dluga=true;      
    }
}

void SprawdzKrotka(){
   if (Bid<min){
      cena_otwarcia=Bid;
      numer_zlecenia=OrderSend(Symbol(),OP_SELL,lot,Bid,20*Point,0,0, NULL,0,0, Red);   
      dluga=false;   
  }
}


void SprawdzCzyZamknac(){
   
      if(Ask>cena_otwarcia+sl*Point || Ask<cena_otwarcia-sl*Point){ 
         if(dluga==false){
         OrderClose(numer_zlecenia,lot,Ask,20*Point,Green);
         }
         if(dluga){
         OrderClose(numer_zlecenia,lot,Bid,20*Point,Green);
         }
         if(OrdersTotal()==0){
         iterator++;
         Alert("Iterator zwiększony przy zamknięciu: iterator");
         Alert(iterator);
         }
         
      }
    
   
}

int init()
  {
   
   return(0);
  }

int deinit()
  {
   
   return(0);
  }

int start()
  {
      if(OrdersTotal()==0){
         if(Hour()==7 && Minute()==58 && Seconds()==0){   
            Inicjator();
            
         }   
      
            if(maks-min<50*Point){
      
               if(iterator==dzien){
                  SprawdzKrotka();
                  SprawdzDluga();
               }
            }
            if(maks-min>50*Point){//w takim wypadku musimy zwiększyć iterator ponieważ nie ma pozycji po ktorej zamknięciu on się zwiększy
               if(iterator==dzien){
                  iterator++;
                  Alert("Iterator zwiększony, ponieważ nie ma handlu(r>50) iterator = ^");
                  Alert(iterator);
               }
            }
         
          if(Hour()==03 && Minute()==00 && Seconds()==00  && iterator==dzien){
               if(maks-min<50){
                  iterator++;
                  Alert("Iterator zwiększony, r<50,ale nie było otwartej pozycji");
                  Alert(iterator);
               }
       
          }
      } 
       
   if(OrdersTotal()>0){
      SprawdzCzyZamknac();
   }
   
   return(0);
   
  }

green7
Maniak
Maniak
Posty: 2060
Rejestracja: 16 sty 2008, 18:44

Nieprzeczytany post autor: green7 »

Tu zaczęły się problemy. Ponieważ teraz Inicjator() jest wykonywany, nie raz dziennie, a 6 razy dziennie. Domyślam się, że chodzi o dokładność danych i nie pomaga tu warunek if(Hour()==7 && Minute()==58 && Seconds()==0), ponieważ na dokładnych danych w ciągu jednej sekundy EA jest w stanie wykonać się 6 razy (?!).
6 razy bo zapewne testujesz na tickach. I wtedy dostaniesz w ciągu minuty tyle ticków ile wynosi volumen w tej minucie. Nie wiem jak "zachowa się" wtedy czas i co emuluje mt4. Ale całkiem możliwe, że zawsze seconds będzie 0 dla wszystkich ticków w minucie (łatwo sprawdzić w testerze).
No i problem też łatwo rozwiązać - np. dodaj flagę, która będzie ustawiana jeśli już wywołałeś funkcję, a dopiero zmiana minuty albo godziny czy też dnia ją wyzeruje.
Green
Obrazek
Obrazek

Kowalski
Uczestnik
Uczestnik
Posty: 3
Rejestracja: 28 sty 2011, 13:07

Nieprzeczytany post autor: Kowalski »

ja mam wątpliwości co do

Kod: Zaznacz cały

void SprawdzKrotka(){
   if (Bid<min){
      cena_otwarcia=Bid;
      numer_zlecenia=OrderSend(Symbol(),OP_SELL,lot,Bid,20*Point,0,0, NULL,0,0, Red);   
      dluga=false;   
  }
} 
to chyba nie powinno być użyte jako else w tym miejscu?? chyba że się mylę

ODPOWIEDZ