szerda, március 23, 2011

Készre csiszolás

Megint kicsit elmaradtam, de majd most megpróbálom bepótolni a várva várt készre csiszolással...

Tehát FOREX robotunk már készen van nagyjából, bár igazából még csak a pozíció nyitásokat beszéltük meg. Arról volt szó, hogy pozíció zárás nem is lesz benne, hiszen stop-loss-t fogunk beállítani, ez fogja zárni a pozíciónkat, méghozzá úgy, hogy az árhoz minél közelebb húzzuk.
A folyamatos ár után húzott - követő - stopunkat addig húzogatjuk, amíg a stop-loss a kötési ár fölé/alá (függően attól, hogy long, vagy short pozíciónk van) kerül, lehetőleg minél jobban.
Ekkor, ha az ár visszaesik, akkor a stop-loss ugyan bezárja a pozíciót, de ekkor már nyereséges lesz.
Na, jó, de hogyan lehet ezt csinálni?

A dolog rém egyszerű, a Parabolic trendchaser egyéni indikátort fogjuk ügyesen felparaméterezni, és az ő jelzéseire állítjuk be a stop-loss-t. Sajnos ez nem lesz mindig lehetséges, de erről majd picit később.

Mindenek előtt, a programunk elején, közvetlenül a start() függvény elejére illesszünk be egy új sort, ahol három új változót fogunk felvenni.
Tehát a start() függvényünknek így kell kezdődnie :
int start()
  {
   int err, ticket;
   double stoploss, ParUp, ParDn;
A három double változó feladat lesz a stop-loss kiszámítása és húzása. Az első két int változó feladata a pozíció nyitások lebonyolítása, a ticket számát tartalmazza és az esetleges hibakódot.

No, de nézzük csak hogyan kell a stopot húzni.A teljes kód a következőképpen néz ki, a jelentését mindjárt meg is beszéljük :
orders=OrdersTotal();
      
if (orders != 0)
      {
         for(pos=0;pos
         {         
            if(OrderSelect(pos, SELECT_BY_POS,MODE_TRADES))
            {  
               ParUp=iCustom(NULL,0,"Parabolic trendchaser", false, 0.06,0.1,7,0,0,1);
               ParDn=iCustom(NULL,0,"Parabolic trendchaser", false, 0.06,0.1,7,0,1,1);
               
               if (OrderType() == OP_BUY && OrderSymbol() == Symbol() && ParDn != 0)
               {
                  stoploss = ParDn;                  
                  
                  if (OrderModify(OrderTicket(),OrderOpenPrice(), stoploss, OrderTakeProfit(),0,Blue))
                     Print("Stop-loss módosítva!");
                  else
                  {
                     Print("Stop-loss nem módosult! ", DoubleToStr(stoploss,5));
                     Print("Hibaüzenet : ",ErrorDescription(GetLastError()));
                  }
               }else if (OrderType() == OP_SELL && OrderSymbol() == Symbol() && ParUp != 0)
               {
                  stoploss = ParUp;

                  if (OrderModify(OrderTicket(),OrderOpenPrice(), stoploss, OrderTakeProfit(),0,Blue))
                     Print("Stop-loss módosítva!");
                  else
                  {
                     Print("Stop-loss nem módosult! ", DoubleToStr(stoploss,5));
                     Print("Hibaüzenet : ",ErrorDescription(GetLastError()));
                  }
               }                  
            }else
               Print("Nem sikerült húzni a Stop-Loss-t, nem találom a pozíciót!");
         }
      }
Az OrdersTotal() függvény elárulja nekünk, hogy mennyi nyitott pozíció van ezen a számlán, minden devizapáron.
A legelső if utasítás arról gondoskodik, hogy csakis kizárólag akkor foglalkozzunk a stop húzással, ha van nyitott pozíciónk.
Ezután egyesével végig szaladunk egy for ciklus segítségével a pozíciókon. A ParUp és a ParDn értékek kiszámításával kezdjük, hiszen nemsokára szükségünk lesz rá. Ezek adják majd a stop szinteket.

A következő if utasítással azt vizsgáljuk, hogy :
  • Long pozíció-e az éppen vizsgált soron következő pozíció
  • Az aktuális chart-nak megfelelő devizapáron köttetett-e (képzeljük csak el, ha egy EURUSD-n futó programunk lezárná az EURHUF long pozíciónkat... Kellemetlen lenne...)
  • És azt is vizsgáljuk, hogy van-e kiszámított érték egyáltalán, mert ha nincs, akkor minek túráztatjuk magunkat
Ha a feltételek teljesülnek, akkor az OrderModify() függvénnyel beállítjuk a stopot. A top értéke a Parabolic trendchaser indikátor alsó pöttyének az értéke lesz, ezért a stoploss változónkba is ezt írjuk be és ezt is állítjuk be stopnak.
Figyeljük meg, hogy az aktuális adatokat kikérjük a pozícióról és azokat vissza is írjuk az OrderModify() függvénybe, tehát csak a stopot módosítjuk. (tehát az OrderTicket() függvény megmondja az aktuálisan kiválasztott pozíciónk ticket számát, az OrderOpenPrice() elárulja milyen áron nyitottuk a pozíciót, ha van take profit beállítva, akkor az OrderTakeProfit() ezt is elárulja. Mindezeket visszaírjuk a módosításba eredeti formájukban, tehát nem bántjuk őket, így tudjuk csak  stop-loss-t módosítani)

Természetesen vizsgáljuk a visszatérési értékét a függvénynek, tehát ha igaz értékkel tér vissza, akkor közöljük a program felhasználójával, hogy sikerült, ha pedig nem sikerült, azt is közöljük, de a hiba okát is kiírjuk, erre való az ErrorDescription(GetLastError()) összefüggés.
Az igazsághoz persze az is hozzátartozik, hogy a programunk elejére be kell szúrnunk még két sort, ahhoz, hogy a hibakiírás működhessen, mégpedig ezt a két sort :
#include <stderror.mqh>
#include <stdlib.mqh>
Ezekkel biztosíthatjuk, hogy az előbb említett hibakezelő függvények működhessenek.
Érdemes a többi include utasítás alá beilleszteni, ha van. De mindenképpen a többi #-kal kezdődő sorokhoz.

A  short pozíciónál ugyanez az eljárás, de ott a Parabolic trendchaser indikátor felső pöttyének az értékét fogjuk beállítani.

A FOREX robotunk még nem az igazi, összeraktuk, készre csiszoltuk, de még nem políroztuk fel, ugyanis vannak még szépség hibái.
Például az, hogyha a Parabolic trendchaser indikátor éppen nem mutat alul pöttyöt, csak felül (mert ugye ez is egy Parabolic SAR rokon és vagy fönt, vagy lent vannak pöttyei), akkor nem húz stopot a program.
Akkor sem fog stopot húzni, hogyha túlságosan közel vagyunk pillanatnyi árhoz.

Ezeket az eseményeket le kell kezelnünk, különben stop nélkül maradunk és nem, vagy túl későn lesz lezárva a pozíciónk, amiből komoly veszteségek származhatnak.
Mindenesetre ez a kis program jól szemlélteti, hogy hogyan érdemes nekifeszülni egy ilyen program megírásának és mire érdemes gondolni közben.

A következő post-ban a legutóbbi két esemény kezelésével foglalkozunk, megoldást keresünk rá, szemléltetve a MetaTrader további lehetőségeit.

Ezután a teljes programkódot közzéteszem, hogyha valakinek nincs kedve az egészet begépelni, vagy ha esetleg lemaradt, akkor egyben láthatja a kódot.
Telis-tele lesz megjegyzésekkel, hogy mi miért van, így talán azok is követni tudnak majd, akik eddig nem olvasták el az összes post-ot.

Ha pedig mindenki a kezébe kaparintotta a működő robotot, jöhet a tesztelés, melynek fázisait szintén végignézzük, illetve a fejlesztés további szakaszai jönnek, a veszteségek kiküszöbölése és egy jó kis money management kerül bele.