MQL4 könyv    Egy szokásos program létrehozása  Kereskedelmi függvények

Kereskedelmi függvények

Egy szokásos Expert Advisor sok kereskedelmi függvényt tartalmaz. Két kategóriába sorolhatjuk őket- vezérlő függvényekre és végrehajtó függvényekre. A legtöbb esetben csak egy vezérlő függvényt és különféle végrehajtó függvényeket használnak egy EA-ban.

Egy szokásos EA-ban a kereskedő stratégiát két függvényben valósítják meg - egy kereskedési ismertetőjeleket meghatározó függvényben és a kereskedést megvalósító függvényben. A kereskedői stratégia a program többi részére nem lehet hatással. A kereskedést végrehajtó és a kereskedési ismertetőjeleket szolgáltató függvényeket össze kell hangolni egymással az átadott paraméterek értékei alapján.

Mindegyik kereskedelmi függvény meghatározott feladatokat láthat el. A kereskedési stratégia alapján a kereskedelmi függvény a következő feladatokat láthatja el az EA-ban:

  • kinyit egy előre beállított típusú megbízását;
  • bezár egy előre beállított típusú megbízását;
  • részlegesen bezár egy előre beállított típusú megbízást;
  • bezár minden előre beállított típusú megbízását;
  • bezár két ellentétes, előre beállított volumenű megbízást;
  • bezár minden piaci megbízást;
  • módosítja az előre beállított típusú megbízás stop szintjét;
  • elhelyezi az előre beállított típusú függőben levő megbízást;
  • törli az előre beállított típusú függőben levő megbízást;
  • töröl minden előre beállított típusú függőben levő megbízást;
  • minden függőben levő megbízás törlése;
  • az előre beállított típusú függőben levő megbízás módosítása.

Egy általános kereskedelemi kód egy szokásos Expert Advisorban a következőkből áll: A (stratégia alapján) létrehozott kereskedési ismertetőjelek megjelenésekor a kereskedelmet megvalósító függvény (szintén a stratégia alapján) hívja a kereskedési kérést ténylegesen kialakító függvényeket.

Trade() felhasználói vezérlő függvény

int Trade( int Trad_Oper )

Ez az az alapvető függvény, ami megvalósítja a kereskedési stratégiát.

A Trad_Oper paraméter a következő értékeket veheti fel a kereskedési ismertetőjeleknek megfelelően:
10 – jelzés a Buy megbízás nyitása feltételeinek meglétéről;
20 – jelzés a Sell megbízás nyitása feltételeinek meglétéről;
11 – jelzés a Buy megbízás zárása feltételeinek meglétéről;
21 – jelzés a Sell megbízás zárása feltételeinek meglétéről;
0 – nincsenek rendelkezésre álló fontos ismertetőjelek;
-1 – nem az EURUSD szimbólumot használjuk.

A függvény végrehajtása a következő kereskedelmi függvényeket igényli:

  • Close_All() – a függvény bezár minden előre beállított típusú megbízást;
  • Open_Ord() – a függvény kinyit egy előre beállított típusú megbízást;
  • Tral_Stop() – a függvény módosítja az előre beállított típusú megbízás StopLoss értékét;
  • Lot() – a függvény meghatározza az új megbízás lot összegét.
A Trade() kereskedelmet vezérlő függvény a  Trade.mqh incklude fájlban megvalósítva:
//------------------------------------------------------------------------
// Trade.mqh
// The code should be used for educational purpose only.
//------------------------------------------------------------------------
// Trade function.
//------------------------------------------------------------------- 1 --
int Trade(int Trad_Oper) // User-defined function
 {
 // Trad_Oper - trade operation type:
 // 10 - opening Buy 
 // 20 - opening Sell 
 // 11 - closing Buy
 // 21 - closing Sell
 // 0 - no important criteria available
 // -1 - another symbol is used
 switch(Trad_Oper)
 {
 //------------------------------------------------------------- 2 --
 case 10: // Trading criterion = Buy
 Close_All(1); // Close all Sell
 if (Lot()==false) // Not enough money for min.
 return; // Exit the user-defined function
 Open_Ord(0); // Open Buy
 return; // Having traded, leave
 //---------------------------------------------------------- 3 --
 case 11: // Trading criterion = closing Buy
 Close_All(0); // Close all Buy
 return; // Having traded, leave
 //---------------------------------------------------------- 4 --
 case 20: // Trading criterion = Sell
 Close_All(0); // Close all Buy
 if (Lot()==false)
 return; // Exit the user-defined function
 Open_Ord(1); // Open Sell 
 return; // Having traded, leave
 //---------------------------------------------------------- 5 --
 case 21: // Trading criterion = closing Sell
 Close_All(1); // Close all Sell
 return; // Having traded, leave
 //---------------------------------------------------------- 6 --
 case 0: // Retaining opened positions
 Tral_Stop(0); // Trailing stop Buy
 Tral_Stop(1); // Trailing stop Sell
 return; // Having traded, leave
 //---------------------------------------------------------- 7 --
 }
 }
//------------------------------------------------------------------- 8 --

A Trade() kereskedelemvezérlő függvényt az usualexpert.mq4 Expert Advisor start()különleges függvényéből hívjuk. Az Criterion() kereskedési ismertetőjeleket meghatározó függvény visszatérési értéke lesz a Trade() függvény átadott paramétere.

A Trade() függvény 1-2 blokkjában ismertetjük a kereskedési ismertetőjelek paramétereinek a jelentését, amelyeket a kereskedési stratégia megvalósítása során alkalmazunk. A függvényben a ’swich’ operátort használjuk arra (2-7 blokk), hogy kiválassza a kereskedési ismertetőjelek által meghatározott függvénycsoportot, amellyel az ismertetőjeleknek megfelelő módon kereskedhetünk. Az EA a kereskedési stratégia szerint megbízásokat zár be és nyit ki. A függőben levő megbízásokat nem használja ez a stratégia.

 A kereskedési ismertetőjeleket  meghatározó függvény részben leírtuk azt, hogy a kereskedési ismertetőjeleknek megfelelően a program többféle kereskedelmi kérést is kialakíthat. Így, a vételt jelző ismertetőjel esetében (a Trad_Oper változó értéke egyenlő 10-zel), a ’switch’ operátor végrehajtása során a vezérlést a 10-es variációnak megfelelő (2-3 blokk) függvénycsoport kapja. Ebben az esetben a program először a Close_All(1) függvényt hívja. Ennek a függvénynek a végrehajtása minden Sell megbízás zárásával végződik, amit az EURUSD szimbólumon nyitottak. Miután minden Sell megbízás le lett zárva, ellenőrizzük a rendelkezésre álló pénzt, hogy elegendő-e a következő megbízáshoz. Ezért hívjuk a Lot() felhasználói függvényt (lásd: A megbízás méretét meghatározó függvény). 

Ha a függvény visszatérési értéke ‘false', ez azt jelenti, hogy a rendelkezésre álló pénz nem elég arra sem, hogy a Buy megbízást megnyissuk a minimum megengedett összeggel. Ebben az esetben a Trade() függvény befejeződik. Ha van elegendő pénz, hívjuk az Open_Ord(0) kereskedelmi függvényt, ami nyit egy Buy megbízást, a Lot() függvény végrehajtása során kiszámított lot összegével. A leírt intézkedéscsomag képviseli az Expert Advisor válaszát a piaci helyzetre (az adott kereskedelmi ismertetőjel szerint).

Ha az ismertetőjel a Buy megbízások zárásának a szükségességét jelzik, akkor a 'case 11' variáció teljesül és a vezérlés a 3-4 blokkba kerül. Ebben az esetben, csak a Close_All(0) függvényt hívjuk, hogy bezárja az összes rendelkezésre álló Buy típusú megbízást. A 4-6 blokk felépítése hasonló a 2-4 blokkhoz, ahová a 'case 20' variáció teljesülése esetén kerül a vezérlés, a 'case 21' variáció teljesülése pedig az összes Sell megbízás zárásához vezet.

Vegyük figyelembe, hogy minden, a Trade() trade függvényből hívott kereskedelmi függvényt, amelyek a kereskedelmi kéréseket kialakítják, akkor hajtunk végre – amikor az új tick következtében az EA start() függvényének végrehajtását az ügyfélterminál elindítja. A Trade() függvény kódja úgy van létrehozva, hogy a vezérlést addig nem adja vissza a start() függvénynek (és az ügyfélterminálnak) amíg minden kereskedelmi kérést megvalósító függvényt végre nem hajt. Ennek következtében a kereskedési ismertetőjeleknek megfelelően, minden kereskedelmi kérést hiánytalanul végrehajt az EA. Kivétel lehet az az eset, ha kritikus hiba történik a kereskedés végrehajtása során (lásd: Hibafeldolgozó függvény).

Ha fontos kereskedő ismertetőjelek nincsenek, a Criterion() függvény végrehajtás után a (Trad_Oper változó egyenlő 0-val) 'case 0' variáció teljesül és a Tral_Stop() függvény két egymás utáni hívására kerül sor, hogy a különböző típusú megbízások kért stop értékeit módosítsuk. Az EA-ban megvalósított kereskedési stratégia csak egy megbízás jelenlétét engedi meg, ebből a szempontból a Tral_Stop(0) és Tral_Stop(1) hívásának sorrendje közömbös. Ebben az esetben ez tetszőleges sorrend lehet.

Ha a Criterion() -1 értéket küldött vissza, ez azt jelenti, hogy az EA-t egy olyan szimbólumablakhoz erősítettük hozzá, ami nem EURUSD. Ebben az esetben a Trade() függvény nem hív végrehajtó kereskedelemi függvényeket, hanem visszaküldi a vezérlést a különleges start() függvénybe.

Close_All() kereskedelmet végrehajtó felhasználói függvény

int Close_All( int Tip)

A függvény bezárja az adott típus minden  megbízását.

A Tip paraméter a következő értékeket veheti fel, a bezárandó megbízás típusa szerint:
0 - Buy megbízás zárása;
1 - Sell megbízás zárása.

Ezen függvény végrehajtásához a következő függvények megléte is szükséges: Terminal() megbízásokat nyilvántartó függvény, Events() eseménykövető függvény és Errors() hibafeldolgozó függvény. Ha üzeneteket is meg akarunk jeleníteni, akkor az Inform() függvényt is használnunk kell. Ha az EA nem tartalmazza az Inform() függvényt akkor az üzenetek nem fognak megjelenni.

A következő globális tömbök értékeit használjuk:

  • a jelenlegi megbízások tömbje a Mas_Ord_New, tartalmazza a jelenlegi piaci és függőben levő megbízások jellemzőivel kapcsolatos információt, a függvény utolsó végrehajtásának pillanatában;
  • a Mas_Tip tömb elem értékei a különböző típusú megbízások összegét tartalmazzák (az aktuális pillanatban).
A Close_All() végrehajtó kereskedelmi függvényt a  Close_All.mqh include fájlban megvalósítva:
//---------------------------------------------------------------------------------
// Close_All.mqh
// The code should be used for educational purpose only.
//---------------------------------------------------------------------------- 1 --
// Function closing all market orders of the given type
// Global variables:
// Mas_Ord_New Last known order array
// Mas_Tip Order type array
//---------------------------------------------------------------------------- 2 --
int Close_All(int Tip) // User-defined function
 {
 // int Tip // Order type
 int Ticket=0; // Order ticket
 double Lot=0; // Amount of closed lots
 double Price_Cls; // Order close price
//---------------------------------------------------------------------------- 3 --
 while(Mas_Tip[Tip]>0) // As long as the orders of the ..
 { //.. given type are available 
 for(int i=1; i<=Mas_Ord_New[0][0]; i++)// Cycle for live orders
 {
 if(Mas_Ord_New[i][6]==Tip && // Among the orders of our type
 Mas_Ord_New[i][5]>Lot) // .. select the most expensive one
 { // This one was found at earliest.
 Lot=Mas_Ord_New[i][5]; // The largest amount of lots found
 Ticket=Mas_Ord_New[i][4]; // Its order ticket is that
 }
 }
 if (Tip==0) Price_Cls=Bid; // For orders Buy
 if (Tip==1) Price_Cls=Ask; // For orders Sell
 Inform(12,Ticket); // Message about an attempt to close
 bool Ans=OrderClose(Ticket,Lot,Price_Cls,2);// Close order !:)
 //---------------------------------------------------------------------- 4 --
 if (Ans==false) // Failed :( 
 { // Check for errors:
 if(Errors(GetLastError())==false)// If the error is critical,
 return; // .. then leave.
 }
 //---------------------------------------------------------------------- 5 --
 Terminal(); // Order accounting function 
 Events(); // Event tracking
 }
 return; // Exit the user-defined function
 }
//---------------------------------------------------------------------------- 6 --

Az 1-2 blokkban, a globális változókat írjuk le. A 2-3 blokkban létrehozzuk és leírjuk a lokális változókat. A Mas_Tip[Tip]>0 feltétel a 'while' ciklusoperátor fejlécében (3-6 blokk) azt jelenti, hogy függvény addig fogja magánál tartani a vezérlést, amíg az operátor teljesíti a feladatát, vagyis amíg az adott típus minden megbízását be nem zárja. A Mas_Tip[Tip] globális tömb eleme tartalmazza azt az értéket, ami egyenlő az adott típusú megbízások számával. Például, ha a Close_All() függvényt(1) átadott paraméterrel hívjuk, ez azt jelenti, hogy a függvénynek be kell zárnia minden Sell megbízást (lásd:  A megbízások típusai). 

Ebben az esetben, a Mas_Tip[1] tömbelem értéke egyenlő lesz valamennyi elérhető Sell megbízással (a Terminal() függvény utolsó végrehajtásának a pillanatában. Így, a 'while' ciklusoperátort annyiszor fogjuk végrehajtani, amennyi Sell megbízás elérhető.

Ha a kereskedő nem avatkozik be az EA működésébe (és nem ad kézzel megbízásokat), akkor csak egy darab, egyik vagy másik típusú megbízás lehet elérhető. Azonban, ha a kereskedő kézzel további megbízásokat nyitott, előfordulhat, hogy a Close_All() függvénynek több megbízást kell lezárnia. A megbízások lezárásának legjobb sorrendje az, ha a legnagyobb megbízást zárjuk be legelőször. Például, ha három Sell megbízásunk van a Close_All() függvény végrehajtása pillanatában, az elsőnek nyitott 5 lot, a másodiknak nyitott 1lot és a harmadiknak nyitott 4 lot méretű, akkor a fenti érvelés szerint a megbízásokat a következő sorrendben kell bezárni: először az 5 lotost, azután a 4 lotost, és végül az 1 lotost.

Vegyük figyelembe, hogy lot összege az egyetlen ismertetőjel, ami alapján a megbízások bezárásának a sorrendjét meghatároztuk. A megbízás nyereségét/veszteségét, nyitó árát és egyéb paramétereit (kért stop szintet, a nyitás idejét és a bezárás okát stb.) nem vesszük figyelembe.

Figyelem!

Ha bizonyos típusú megbízásokat egyszerre kell bezárni, fontos, hogy a bezárást a legnagyobb megbízással kezdjük, és azután következzenek a kisebbek.

A megbízások zárásának fenti sorrendjének betartására a 3-4 blokkban a 'for' ciklust használjuk, amiben a legnagyobb méretű megbízást választjuk ki az adott típusú megbízások közül. Ezt a megbízást (a legnagyobbat) Mas_Ord_New globális tömb értékeinek az elemzése alapján keressük meg, ahol megtalálható minden, a kereskedelemben rendelkezésre álló megbízással kapcsolatos információ. Miután ennek a megbízásnak a jegyszámát megtaláltuk, a kettős árnak a megbízás típusa szerinti értékével kiszámoljuk a kért záró árat. Ha Buy típusú megbízást kell lezárni, akkor a Bid értéket használjuk. Ha Sell megbízást, akkor az Ask értéket.

A kereskedelmi kérés kialakítása előtt közvetlenül megjelenítjük, a bezárási kísérlettel kapcsolatos információt. Ezért a program hívja az Inform()függvényt. A megbízás befejezése iránti kereskedelmi kérést a következő sorban alakítjuk ki:

 bool Ans=OrderClose(Ticket,Lot,Price_Cls,2);// Close order !:)

A kiszámított értékeket paraméterekként használjuk: Ticket - jegyszám, Lot - kötésméret, Price_Cls – a kért záró ár, 2 - csúszás.

A 4-5 blokkban a kereskedelem eredményeit elemezzük. Ha az OrderClose() függvény visszatérési értéke 'true', ez azt jelenti, a kérés végrehajtása sikeres és a megbízás le lett zárva. Ebben az esetben a vezérlés átkerül az 5-6 blokkba, ahol az az aktuális pillanatban rendelkezésre álló megbízásokkal kapcsolatos információt frissítik. A Terminal() és Events() függvények végrehajtása után a 'while' ciklus aktuális ismétlése véget ért (az elérhető megbízások száma a ciklus végrehajtása alatt megváltozhat, ezért a megbízásokat nyilvántartó Terminal() függvény végrehajtása kötelező a 'while' ciklus mindegyik ismétlésénél). Ha az adott típusú megbízások még mindig elérhetőek, ezek a 'while' ciklus következő ismétlésénél lesznek lezárva, a Mas_Ord_New és Mas_Tip tömböknek a Terminal() függvény újbóli végrehajtása során kapott értékeit fogjuk a következő megbízás lezárásakor paraméterekként felhasználni.

Ha a kereskedelmi kérés végrehajtása azzal végződik, hogy az OrderClose() függvény 'false' értéket küld vissza, ez azt jelenti, hogy a megbízás nem lett lezárva. Azért, hogy a sikertelenség okát megtudjuk, a program elemzi az utolsó hiba okát. Ezért hívni fogja az Errors() fügvényt (lásd: Hebafeldolgozó függvény). Ha ennek a függvénynek a végrehajtásánál a program azt érzékeli, hogy a hiba kritikus (például a kereskedés tiltva van), a Close_All() függvény befejezi a működését és visszaküldi a vezérlést a kereskedést felügyelő Trade() függvénybe, amely azt továbbadja a különleges start() függvénynek és az EA végrehajtása befejeződik. A következő ticknél a terminál ismét el fogja indítani a start() függvény végrehajtását. Ha a záró ismertetőjel abban a pillanatban még fennáll, akkor a Close_All() függvény hívása újra megtörténik.

Open_Ord() kereskedelmet végrehajtó felhasználói függvény

int Open_Ord ( int Tip)

A függvény nyit egy adott típusú megbízást.

A Tip paraméternek a következő értékei lehetnek, amely jelzi a nyitandó megbízás típusát:
0 - Buy típusú megbízás nyitása;
1 - Sell típusú megbízás nyitása.

Ezen függvény végrehajtásához a következő függvények megléte is szükséges: Terminal() megbízásokat nyilvántartó függvény, Events() eseménykövető függvény és Errors() hibafeldolgozó függvény. Ha üzeneteket is meg akarjuk jeleníteni, akkor az Inform() függvényt is használnunk kell. Ha az EA nem tartalmazza az Inform() függvényt akkor az üzenetek nem fognak megjelenni.

A következő globális változók értékeit használjuk:

  • a Mas_Tip tömb elem értékei a különböző típusú megbízások összegét tartalmazzák (a Terminal() függvény végrehajtásának pillanatában).
  • StopLoss - StopLoss értéke (pontokban);
  • TakeProfit - TakeProfit értéke (pontokban).
A Open_Ord() végrehajtó kereskedelmi függvény az Open_Ord.mqh  include fájlban megvalósítva:
//---------------------------------------------------------------------------------
// Open_Ord.mqh
// The code should be used for educational purpose only.
//---------------------------------------------------------------------------- 1 --
// Function opening one market order of the given type
// Global variables:
// int Mas_Tip Order type array
// int StopLoss The value of StopLoss (amount of points)
// int TakeProfit The value of TakeProfit (amount of points)
//---------------------------------------------------------------------------- 2 --
int Open_Ord(int Tip)
 {
 int Ticket, // Order ticket
 MN; // MagicNumber
 double SL, // StopLoss (as related to the price)
 TP; // TakeProf (as related to the price)
//---------------------------------------------------------------------------- 3 --
 while(Mas_Tip[Tip]==0) // Until they ..
 { //.. succeed
 if (StopLoss<Level_new) // If it is less than allowed..
 StopLoss=Level_new; // .. then the allowed one
 if (TakeProfit<Level_new) // If it is less than allowed..
 TakeProfit=Level_new; // ..then the allowed one
 MN=TimeCurrent(); // Simple MagicNumber
 Inform(13,Tip); // Message about an attempt to open
 if (Tip==0) // Let's open a Buy
 {
 SL=Bid - StopLoss* Point; // StopLoss (price)
 TP=Bid + TakeProfit*Point; // TakeProfit (price)
 Ticket=OrderSend(Symbol(),0,Lots_New,Ask,2,SL,TP,"",MN);
 }
 if (Tip==1) // Let's open a Sell
 {
 SL=Ask + StopLoss* Point; // StopLoss (price)
 TP=Ask - TakeProfit*Point; // TakeProfit (price)
 Ticket=OrderSend(Symbol(),1,Lots_New,Bid,2,SL,TP,"",MN);
 }
 //---------------------------------------------------------------------- 4 --
 if (Ticket<0) // Failed :( 
 { // Check for errors:
 if(Errors(GetLastError())==false)// If the error is critical,
 return; // .. then leave.
 }
 Terminal(); // Order accounting function 
 Events(); // Event tracking
 }
//---------------------------------------------------------------------------- 5 --
 return; // Exit the user-defined function
 }
//---------------------------------------------------------------------------- 6 --

Az Open_Ord() függvény 1-3 blokkjában azokat a globális változókat ismertetjük, amelyek értékeit ebben a függvényben használjuk, valamint létrehozzuk a lokális változókat. A függvény alapvető kódja a 'while' ciklusoperátorban összpontosul (3-5 blokk) azt annyiszor hajtjuk végre, amíg nem jön létre ”Tip” típusú megbízás.

A kereskedési stratégia olyan megbízások nyitását írja elő, ahol a megbízás nyitásával egy időben a stop szinteket is beállítjuk. Általános esetben a kereskedő a piaci árhoz viszonyítva helyezi el a stop szinteket, azonban ezek a stop szintek nem minden esetben tartják be a dealing center által meghatározott minimális távolság követelményét. Ezért, a megbízás nyitása előtt ezt ellenőrizni kell: Ha az utoljára ismert minimális távolság (Level_new) nagyobb, mint a StopLoss vagy TakeProfit külső változók értéke, e változók értékét Level_new-nak állítjuk be.

Minden megbízás nyitására irányuló kereskedelmi kérés tartalmazza az egyedi MagicNumbert ami megegyezik az aktuális szerveridővel. Egy EA végrehajtásának következtében egy szimbólumon csak egy megbízás lehet nyitva (vagy egy függőben levő megbízás lehet) egy időben. Egy megbízás nyitása előtt végrehajtjuk az Inform() függvényt, amely bemutat egy tájékoztató üzenetet a megbízás nyitásának kísérletéről.

A megbízás típusa szerint, az egyik 'if' operátortörzset hajtjuk végre. Például, ha a Tip paraméter értéke egyenlő 0-val, ez azt jelenti, hogy egy Buy megbízást kell nyitni. Ebben az esetben a StopLoss és TakeProfit értékeit kiszámítjuk, a Buy megbízástípusnak megfelelően, azután a vezérlés a következő sorba kerül,

 Ticket=OrderSend(Symbol(),0,Lots_New,Ask,2,SL,TP,"",MN);

ahol létrehozzuk a Buy megbízás kialakulására irányuló kereskedelmi kérést. Hasonló számításokat végzünk, ha a Tip paraméter értéke 1, vagyis egy Sell megbízást kell nyitni.

A hibákat a többi felhasználói kereskedelmet végrehajtó függvényhez hasonlóan dolgozzuk fel. Ha a kereskedelmi kérés végrehajtása sikerül, a függvény befejezi a működését (nincs a 'while' ciklusnak következő ismétlése mert a Terminal() függvény végrehajtása után a Mas_Tip[Tip] elemének az értéke egyenlő lesz 1-gyel). Azonban, ha a kereskedelmi kérés végrehajtása nem sikerül, a hibákat elemezzük (4-5 blokk). Ebben az esetben hívjuk az Errors() hibafeldolgozó függvényt. Ha ennek a visszatérési értéke 'false' (a hiba kritikus), az Open_Ord() függvény végrehajtása véget ér, és a vezérlés egymás után átkerül a Trade() kereskedelmi vezérlő függvénybe, onnan a start() függvénybe majd azután az ügyfélterminálhoz. Mindazonáltal, ha a hiba kiküszöbölhető, az adatokat frissítjük a Terminal() függvényben és a vezérlést ismét megkapja a 'while' ciklus következő ismétlésére, amíg a megbízás nyitása sikerrel nem jár.

Így, az Open_Ord() függvény mindaddig magánál tartja a vezérlést, amíg a megbízás nyitása nem sikerül, vagy kritikus hiba nem történik.

Tral_Stop() kereskedelmet végrehajtó felhasználói függvény

int Tral_Stop ( int Tip)

A függvény módosít minden adott típusú megbízást.

A Tip paraméter következő értéke képviseli a módosítandó megbízás típusát:
0 - a Buy típusú megbízásokat módosítjuk;
1 - a Sell típusú megbízásokat módosítjuk.

Ezen függvény végrehajtásához a következő függvények megléte is szükséges: Terminal() megbízásokat nyilvántartó függvény, Events() eseménykövető függvény és Errors() hibafeldolgozó függvény. Ha üzeneteket is meg akarjuk jeleníteni, akkor az Inform() függvényt is használnunk kell. Ha az EA nem tartalmazza az Inform() függvényt akkor az üzenetek nem fognak megjelenni.

A következő globális változók értékeit használjuk:

-  a jelenlegi megbízások tömbje a Mas_Ord_New, tartalmazza a jelenlegi piaci és függőben levő megbízások jellemzőivel kapcsolatos információt, a függvény utolsó végrehajtásának pillanatában;

- TralingStop - a távolság a piaci ár és StopLoss kívánt értéke között (pontokban).

A Tral_Stop() kereskedelmi függvény a  Tral_Stop.mqh include fájlban megvalósítva:
//---------------------------------------------------------------------------------
// Tral_Stop.mqh
// The code should be used for educational purpose only.
//---------------------------------------------------------------------------- 1 --
// Function modifying StopLosses of all orders of the given type
// Global variables:
// Mas_Ord_New Last known order array
// int TralingStop Value of TralingStop (amount of points)
//---------------------------------------------------------------------------- 2 --
int Tral_Stop(int Tip)
 {
 int Ticket; // Order ticket
 double
 Price, // Market order open price
 TS, // TralingStop (as related to the price)
 SL, // Value of order StopLoss
 TP; // Value of order TakeProfit
 bool Modify; // A criterion to modify.
//---------------------------------------------------------------------------- 3 --
 for(int i=1;i<=Mas_Ord_New[0][0];i++) // Cycle for all orders
 { // Searching for orders of the given type
 if (Mas_Ord_New[i][6]!=Tip) // If this is not our type..
 continue; //.. skip the order
 Modify=false; // It is not assigned to be modified
 Price =Mas_Ord_New[i][1]; // Order open price
 SL =Mas_Ord_New[i][2]; // Value of order StopLoss
 TP =Mas_Ord_New[i][3]; // Value of order TakeProft
 Ticket=Mas_Ord_New[i][4]; // Order ticket
 if (TralingStop<Level_new) // If it is less than allowed..
 TralingStop=Level_new; // .. then the allowed one
 TS=TralingStop*Point; // The same in the relat, price value
 //---------------------------------------------------------------------- 4 --
 switch(Tip) // Go to Order type
 {
 case 0 : // Order Buy
 if (NormalizeDouble(SL,Digits)<// If it is lower than we want..
 NormalizeDouble(Bid-TS,Digits))
 { // ..then modify it:
 SL=Bid-TS; // Its new StopLoss
 Modify=true; // Assigned to be modified.
 }
 break; // Exit 'switch'
 case 1 : // Order Sell
 if (NormalizeDouble(SL,Digits)>// If it is higher than we want..
 NormalizeDouble(Ask+TS,Digits)||
 NormalizeDouble(SL,Digits)==0)//.. or zero(!)
 { // ..then modify it
 SL=Ask+TS; // Its new StopLoss
 Modify=true; // Assigned to be modified.
 }
 } // End of 'switch'
 if (Modify==false) // If there is no need to modify it..
 continue; // ..then continue the cycle
 bool Ans=OrderModify(Ticket,Price,SL,TP,0);//Modify it!
 //---------------------------------------------------------------------- 5 --
 if (Ans==false) // Failed :( 
 { // Check for errors:
 if(Errors(GetLastError())==false)// If the error is critical,
 return; // .. then leave.
 i--; // Decreasing counter
 }
 Terminal(); // Order accounting function 
 Events(); // Event tracking
 }
 return; // Exit the user-defined function
 }
//---------------------------------------------------------------------------- 6 --

Az 1-3 blokkban leírjuk a függvényben használt globális változókat, és létrehozzuk a lokális változókat. A 'for' ciklusban (3-6 blokk) kiválasztjuk az adott típusú megbízásokat és ha azok közül a megbízások közül bármelyiknek a StopLossa távolabb van az aktuális ártól, mint amit a felhasználó beállított, akkor azt a megbízást módosítjuk.

Hogy áttekinthetővé tegyük a kódot, a megbízás néhány paraméterének értékét a Mas_Ord_New tömbből egyszerű változóknak adjuk (3-4 tömb). Majd a TralingStop változó szükséges ellenőrzését elvégezzük: Ha ennek a változónak az értéke kevesebb annál a megengedett minimum távolságnál, amit a dealing center beállított, akkor azt a minimális megengedett értékre fogjuk növelni.

A 4-5 blokkban elvégezzük a megbízás típusa szerinti szükséges számításokat. Például, ha a Tip átvitt paraméter értéke 1 (egy Sell megbízást kell módosítani), a vezérlés a 'switch' operátor 'case 1' variációjába fog kerülni. Itt a StopLos módosításának szükségességét ellenőrizzük (a Követelmények és korlátozások a kereskedelemben részben ismertetett, a megbízástípusokra vonatkozó szabályok szerint). Ha a StopLos nincs beállítva vagy az a TralingStop értékénél távolabb van az aktuális piaci ártól, kiszámoljuk a StopLoss kívánt új értékét. A kereskedelmi kérést a következő sorban alakítjuk ki:
 bool Ans = OrderModify(Ticket,Price,SL,TP,0);//Modify it!

Ismert, hogy e kereskedési stratégia alapján csak egy megbízás nyitása lehetséges. Azonban, a Tral_Stop() függvény lehetőséget nyújt arra, hogy több, azonos típusú megbízását módosítsunk. Ha a kereskedő nem avatkozik be kereskedelembe, az EA-nak nem szükséges több megbízást módosítania. Azonban, ha a kereskedő kézzel nyit egy megbízást (azokon felül, amelyik már nyitva van), el kell döntenünk, melyik a rendelkezésre álló megbízást módosítsuk elsőként.

Amikor azt vizsgáltuk, hogy több meglévő megbízás közül melyiket kell először zárni, akkor eldöntöttük, hogy a bezárás sorrendjét a megbízás lot mérete alapján határozzuk meg. Ez a megoldás nyilvánvaló – a megbízás méretét használja az EA a zárási sorrendet meghatározó ismertetőjelként. A  módosítási sorrend problémájának nincs egyértelmű megoldása. Minden esetben a módosítás sorrendjének szempontját a kereskedő stratégia lényege határozza meg. Ez az ismertetőjel lehet a lot összege, vagy az ha az egyik megbízásnak nincs beállított StopLoss értéke, illetve a StopLoss távolságok különbözőek. Sok esetben ezt az ismertetőjelet kifejezhetjük azzal az indexszel – ami annak a veszteségnek a mérete, ami egy hirtelen árváltozásból eredhet, mikor minden tőzsdei megbízást automatikusan egyszerre bezár a StopLoss.

A Tral_Stop() függvény fenti példájában, a megbízások módosítását véletlen sorrendbe valósítjuk meg - a piaci és függőben lévő megbízások megtalálásának sorrendjében. Minden speciális esetben a függvényt finomítani kell - a megbízások módosításának sorrendjét a speciális kereskedői stratégia szabályai szerint kell programozni.

Fokozottan figyelni kell arra, hogy minden kereskedelmi művelet valós időjű módban történik. Ha túl sok megbízás van az EA-ban létrehozva akkor az nagy mennyiségű kereskedelmi kérést eredményez. Nyilvánvaló, hogy a piac megfordulhat, amíg azokat a kéréseket végrehajtják. Azonban a függvény nem küldi vissza a vezérlést a Trade() függvénybe, amíg minden szükséges módosítást végre nem hajt. Ez azt jelenti, hogy növekszik annak a veszélye, hogy kihagyjunk egy megbízás nyitó vagy záró kereskedelmi kérést. Ezért minden kereskedelmi stratégiát úgy kell kódolni, hogy egy időben ne legyen nagy mennyiségű megbízásunk.

Az 5-6 blokkban a kereskedelmi kérések végrehajtása alatt történt hibákat elemezzük. Ha a hiba kritikus, a függvény be fogja fejezni a működését. Mindazonáltal, ha egy áthidalható hibát kapunk, az ”i” számláló értékét 1-el csökkentjük. Ennek következtében ugyanazon megbízás módosítását ismét megkísérli a program a 'for' ciklus következő ismétlésénél.

A legtöbb esetben a fenti kód végre fog hajtani minden szükséges módosítást. Ugyanakkor, ha bármilyen változás történik a meglévő megbízásokkal (például, egy megbízás a bezárul, mert a piaci ár elérte valamelyik stop szintet) a megbízások módosítása alatt, a Mas_Ord_New tömb szintén megváltozhat. Ez azt okozhatja, hogy valamelyik megbízás módosítása kimaradhat a start() függvény aktuális végrehajtása alatt. Ezt a következő ticknél, a start() függvény következő indításakor korrigálhatja a program.