MQL4 COURSE
By Coders' guru
www.forex-tsd.com
Twoj pierwszy EA
Czesc 2
--------------------
Witam w drugiej czesci lekcji o tworzeniu twojego pierwszego EA. Poprzednio zajmowalismy sie kreatorem oraz dodaniem naszego kodu, ktory dzisiaj, linijka po linijce rozpracujemy.
Uwaga: Pragne powtorzyc, ze nasz EA jest tylko do celow edukacyjnych i nie bedzie (lub jego celem nie jest) sluzyl zarabianiu.
Kod, ktory aktualnie mamy:
//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Coders Guru |
//| http://www.forex-tsd.com |
//+------------------------------------------------------------------+
#property copyright "Coders Guru"
#property link "http://www.forex-tsd.com"
//---- input parameters
extern double TakeProfit=250.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
int Crossed (double line1 , double line2)
{
static int last_direction = 0;
static int current_direction = 0;
if(line1>line2)current_direction = 1; //up
if(line1<line2)current_direction = 2; //down
if(current_direction != last_direction) //changed
{
last_direction = current_direction;
return (last_direction);
}
else
{
return (0);
}
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
int cnt, ticket, total;
double shortEma, longEma;
if(Bars<100)
{
Print("bars less than 100");
return(0);
}
if(TakeProfit<10)
{
Print("TakeProfit less than 10");
return(0); // check TakeProfit
}
shortEma = iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
longEma = iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);
int isCrossed = Crossed (shortEma,longEma);
total = OrdersTotal();
if(total < 1)
{
if(isCrossed == 1)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,
"My EA",12345,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened : ",OrderOpenPrice());
}
else Print("Error opening BUY order : ",GetLastError());
return(0);
}
if(isCrossed == 2)
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
Bid-TakeProfit*Point,"My EA",12345,0,Red);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order opened : ",OrderOpenPrice());
}
else Print("Error opening SELL order : ",GetLastError());
return(0);
}
return(0);
}
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
{
if(OrderType()==OP_BUY) // long position is opened
{
// should it be closed?
if(isCrossed == 2)
{
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet);
// close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>Point*TrailingStop)
{
if(OrderStopLoss()<Bid-Point*TrailingStop)
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-
Point*TrailingStop,OrderTakeProfit(),0,Green);
return(0);
}
}
}
}
else // go to short position
{
// should it be closed?
if(isCrossed == 1)
{
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
// close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0)
{
if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
{
if((OrderStopLoss()>(Ask+Point*TrailingStop)) ||
(OrderStopLoss()==0))
{
OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,
OrderTakeProfit(),0,Red);
return(0);
}
}
}
}
}
}
return(0);
}
//+------------------------------------------------------------------+
Koncepcja naszego EA:
Zanim zakopiemy sie w kodzie naszej strategii, musimy sobie wyjasnic, na czym ona polega. Kazdy Expert Advisor musi podejmowac decyzje, kiedy ma wejsc na rynek i kiedy z niego wyjsc. Od czego sa te dwie akcje uwarunkowane? Nasz EA jest jednym z prostszych, wiec i koncepcja jest rownie prosta.
Uzywamy dwoch wskaznikow EMA, 8 dniowego (krotka) i 13 dniowego (dluga).
Uwaga: Uzywanie tych srednich kroczacych czy innych rozwiazan w tej lekcji, nie jest przeze mnie rekomendowane, a sluza one jedynie celom naukowym.
Wejscie:
Nasz EA otworzy zlecenie, kiedy krotka srednia przetnie dluga, a ich kierunek zadecyduje o rodzaju zlecenia:
Jesli krotka EMA jest powyzej dlugiej, zostanie otwarta pozycja long (kupno)
Jesli krotka EMA jest ponizej dlugiej, zostanie otwarta pozycja short (sprzedaz)
Mozliwe bedzie otwarcie tylko jednej pozycji na raz.
Wyjscie:
Nasz EA zamknie zlecenie kupna, jesli krotka EMA przetnie dluga EMA i znajdzie sie ponizej.
Nasz EA zamknie zlecenie sprzedazy, jesli krotka EMA przetnie dluga EMA i znajdzie sie powyzej.
Zlecenia zostana rowniez zamkniete, gdy cena osiagnie odpowiednio poziomy TP lub SL.
Modyfikacja:
Oprócz wchodzenia (otwierania) i wychodzenia (zamykania) z rynku (pozycji) nasz EA ma mozliwosc modyfikowania otwartych pozycji na podstawie pomyslu 'Trailing Stop point' o ktorej wdrazaniu dowiemy sie nieco pozniej w tej lekcji.
Wrocmy do rozgryzania naszego kodu.
//---- input parameters
extern double TakeProfit=250.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
W powyzszych liniach zadeklarowalismy 3 zmienne zewnetrzne (moga byc zmieniane przez uzytkownika na poziomie okna wlasciwosci EA). Sa one typu double. Przypisalismy juz im wartosci i w prawdzie uzytkownik moze to zmienic, jednak zaleca sie pozostawienie ich takimi.
Musze sie tu zatrzymac na chwile, by powiedziec ci troche wiecej o tych wartosciach.
Stop loss:
To limit punktow, ktory w przypadku, gdy rynek zahcowuje sie przeciwnie do twoich przywidywan, zamknie twoje zlecenie, dzieki czemu twoje straty beda mniejsze.
Stop loss jest zawsze ustawiany ponizej ceny zakupu lub powyzej ceny sprzedazy.
Trailing stop:
Jest to rodzaj SL, ale granica straty jest ustawiana procentowo ponizej (dla dlugich pozycji) lub powyzej (dla krotkich pozycji) ceny na rynku.
Take profit:
Jest czyms na ksztalt SL, po osiagnieciu ustawionego tu limitu przez twoje zlecenie, zostaje ono zamkniete.
Sa tutaj jednak dwie roznice:
nie ma tutaj trailing point (cokolwiek to znaczy:))
Punkt do wyjscia musi byc ustawiony powyzej aktualnej ceny zamiast ponizej.
int Crossed (double line1 , double line2)
{
static int last_direction = 0;
static int current_direction = 0;
if(line1>line2)current_direction = 1; //up
if(line1<line2)current_direction = 2; //down
if(current_direction != last_direction) //changed
{
last_direction = current_direction;
return (last_direction);
}
else
{
return (0);
}
}
Jak juz ci mowilem, idea naszego EA jest wypatrywanie przeciecia sie dwoch srednich kroczacych - krotkiej i dlugiej. To ktora linia bedzie nad ktora, zadecyduje o rodzaju otwieranego przez nas zlecenia.
Stworzylismy w tym celu funkcje.
Funkcja Crossed zawiera dwie wartosci jako jej parametry i zwraca liczbe calkowita. Pierwsza zmienna 'obserwuje' linie krotkiej sredniej kroczacej, a druga linie dlugiej zmiennej kroczacej. Za kazdym razem gdy ja uruchomimy, funkcja zapisuje kierunek by zapamietac ich polozenie pomiedzy kolejnymi tickami.
Funkcja zwroci wartosc 0, jesli polozenie srednich kroczacych sie nie zmienilo od ostatniego uruchomienia funkcji
Funkcja zwroci wartosc 1, jesli polozenie srednich kroczacych zmienilo sie (linie przeciely sie nawzajem) i pierwsza linia jest powyzej drugiej
Funkcja zwroci wartosc 2, jesli polozenie srednich kroczacych zmienilo sie (linie przeciely sie nawzajem) i pierwsza linia jest ponizej drugiej
Uwaga: mozesz uzywac tej funkcji dla dowolnych dwoch linii
Zobaczmy, jak to napisalismy
int Crossed (double line1 , double line2)
Powyzsza deklaracja funkcji oznacza, ze chcemy stworzyc funkcje o nazwie Crossed, ktora zawiera dwa parametry typu double (liczby rzeczywiste), a cala funkcja zwraca nam wartosc integer (liczby calkowite).
Zeby jej uzyc, musisz ja wczesniej zadeklarowac. Nie ma znaczenia w ktorym miejscu, ja usytuowalem ja powyzej start(), ale ty mozesz umiescic ja gdzie chcesz.
static int last_direction = 0;
static int current_direction = 0;
Zadeklarowalismy tutaj dwie stale typu integer, by zapamietac obecny i poprzedni kierunek dwoch linii. Bedziemy uzywac tych dwoch wartosci (sa typu static, wiec zachowuja swoje wartosci pomiedzy kolejnymi wywolaniami) by sprawdzic, czy polozenie dwoch linii sie zmienilo.
Ustawilismy ich wartosci na zero, poniewaz nie chcemy, by zadzialaly przy pierwszym wywolaniu funkcji (jesli bysmy tego nie zrobili, EA otworzyl by zlecenie, zaraz po uruchomieniu platformy).
if(current_direction != last_direction) //changed
W tej linijce porownujemy dwie wartosci, by sprawdzic czy nie zaszly zmiany od czasu ostatniego wywolania funkcji. Jesli zmienna current_direction nie jest rowna (!=) zmiennej last_direction, oznacza, ze linie przeciely sie.
last_direction = current_direction;
return (last_direction);
W tym przypadku (last_direction nie jest rowna current_direction) musimy usunac wartosc ze zmiennej last_direction, przez przypisanie jej wartosci z current_direction.
Nastepnie zwracamy wartosc last_direction. Wartosc zwracana wyniesie 1 jesli pierwsza linia bedzie powyzej drugiej lub 2 w gdy linia pierwsza jest ponizej drugiej.
else
{
return (0);
}
W przeciwnym razie (last direction jest rowna current_direction) nie zaszly zmiany w polozeniu linii i otrzymujemy wartosc 0.
Nasz program bedzie wywolywal ta funkcje w czesci start() i uzyje zwracanych wartosci o podjecia odpowiedniej decyzji.
W nastepnym czesci naszych lekcji dowiemy sie jak wywolac nasza funkcje i dowiemy sie o poleceniach sluzacych do przeprowadzana transakcji.
Jestem otwarty na wszelkie pytanai i sugestie.
Do zobaczenia
Coders' Guru
01-12-2005
tlumaczyl Matteo