péntek, február 25, 2011

Építkezés - folytatás II. ...

Szép jó estét mindenkinek! Gondolom már vártátok a folytatást, hát itt van.

Eddig ugye szó esett a FOREX robot és a MetaTrader kapcsolatáról, szó esett a robot felépítéséről is.
Sőt, mi több, el is kezdtük építeni a kis okos robotunkat MetaTrader-ben, a saját C# programozási nyelvén.

Eddig ott tartunk, hogy az indikátorok alapján eldöntöttük, hogy merre az arra, vagyis azt, hogy a mi kis okos FOREX robotunk long - azaz vételi -, vagy short - azaz eladási - pozíciót nyisson.
Most azt fogjuk megbeszélni, hogy na, akkor hogyan is nyissunk pozíciót!

Csapjunk is a közepébe, íme a kód és már meg is beszéljük hogyan működik :
      if (TMTrend == "Long" && TVITrend == "Long" && !nyitott)
      {
         ticket=OrderSend(Symbol(),OP_BUY,maxlots,Ask,slippage,0,0,"TrendMagic-TVI - Long",MathRand(),0,Green);
         err = GetLastError();
         if (err != 0 && ticket < 0)
         {
            Print("Error # ", err, "  ", ErrorDescription(err));
         }
      } 
Első ránézésre talán bonyolultnak tűnik, de nem az.
Minden ahhoz az alapvető feltételhez van kötve, hogy az indikátorok mit mutatnak.
Tehát három feltétel meglétét vizsgáljuk. Az első kettő a két indikátor együttállása, a harmadik pedig a start() függvény elején vizsgált feltétel szerint beállított nyitott nevű változónk. Ez ugye igaz értéket vesz fel, ha az aktuális devizapáron van már nyitott pozíciónk.
Tehát a feltétel vizsgálja, hogy long nyitási lehetőség van-e és azt, hogy NINCS nyitott pozíciónk. Mert ha már van, akkor nem nyitunk rá. (ez majd a rákötésnél lesz érdekes, de ott még nem tartunk)
Tehát a '!' jel az, amely a tagadás (szakmaibban szólva negálás) ebben a nyelvben, ha egy változó hamis értéket tartalmaz, akkor ez igazzá változtatja és fordítva. Tehát, ha van nyitott pozíciónk, akkor ezzel a jellel hamis értéket kapunk és nem teljesül az if utasításunk, ha pedig nincs nyitott pozíciónk, akkor igaz értéket kapunk és ha mindkét indikátor long-ot mutat, akkor már folytatjuk is a végrehajtást a következő utasítás soron.

Nem gatyázunk, ez már maga a pozíció nyitás. Sajnos ez is kétesélyes, vagy sikerül, vagy nem. Éppen ezért ha nem sikerül, akkor arról tudnunk kell.
De ne szaladjunk ennyire előre.
Az OrderSend() függvény gondoskodik arról, hogy a pozíció megnyíljon, bármilyen irányba. Nyilván az első paramétere az instrumentum neve - vagyis a devizapár neve - lesz, ahol a pozíciót nyitni szeretnénk, a második a már sokkal érdekesebb, mert itt mondjuk meg miféle pozíciót nyitunk.
Nézzük csak, miket lehet nyitni :
  • OP_BUY : ez egyszerűen egy long, azaz vásárlási (buy) pozíció nyitást jelent, semmi extra
  • OP_SELL : a long párja, vagyis a short, eladási (sell) pozíció
  • OP_BUYLIMIT : na, ez már érdekes, ha az ár elér egy bizonyos szintet, akkor nyit egy long-ot
  • OP_SELLLIMIT : ez az előző short testvére
  • OP_BUYSTOP : ez nagyon hasonló a buy limit-hez, de kicsit másképp működik, mindjárt kitérünk rá
  • OP_SELLLIMIT : ez pedig az előző párja
Mi a különbség a LIMIT és a STOP pozíció nyitás között? Sok!
A LIMIT mindig egy felső határt, a STOP pedig egy alsó határt jelöl. Vagyis, például egy buy limit esetén amikor a limitet meghaladja az ár, akkor nyit pozíciót, minimálisan a megadott limit áron és nem kevesebbért.
A buy stop pedig akkor fog pozíciót nyitni, amikor az ár leesik arra a bizonyos árszintre, amit megadunk és legfeljebb azon az áron nyit pozíciót, amit megadunk. Tehát a limit ár általában magasabb, mint a pillanatnyi ár, a stop pedig alacsonyabb, de ez a stratégiától függ természetesen. Mindenesetre így tervezték ezeket a pozíció nyitási lehetőségeket.

Két következtetést lehet levonni ebből. Az egyik, hogy a limit egy felső határ fölött, de legalább annyiért, ha a beérkező tick magasabb, akkor magasabban fog pozíciót nyitni, a stop pedig egy alsó határ alatt nyit pozíciót, maximum annyiért, de ha a tick alacsonyabb, akkor alacsonyabban fog pozíciót nyitni.
A másik következtetés, hogy ezek nem azonnali pozíció nyitások, hanem feltételesek, tehát amíg a pozíció meg nem nyílik, törölni is lehet őket mindenféle következmények nélkül.

Az első kettőt fogjuk használni, ugyanis ezek az azonnali pozíció nyitások. A többit nem is fogjuk használni, ezek általában kézi kötésnél játszanak szerepet, automatikus kereskedésben még sosem láttam ilyen kötést...

Nos, visszatérve a pozíció nyitó OrderSend() függvényünkre, a harmadik paraméterünk azt mondja meg, hogy mekkora méretű pozíciót nyitunk. Erről a nap végére tartogatok egy kis magyarázatot.
A következő paraméter az ár, amin szeretnénk pozíciót nyitni.Ezt megadhatjuk közvetlenül is, de ennek nem sok értelme van, ugyanis a program végrehajtása során ez az ár változhat. Tehát érdemes a pillanatnyi áron vásárolni.

No és akkor itt most álljunk meg egy szóra, mert itt jön az a rész, amit néha a kereskedők elfelejtenek. Aki nem felejti el ezeket, nyugodtan átlépheti ezt a bekezdést, de szerintem érdemes elolvasni. Fél perc...
A devizapárokkal történő kereskedés két áron zajlik. A vételi és az eladási áron. A MetaTrader a vételi árat Ask-nak hívja, az eladási árat pedig Bid-nek. A kettő közötti árrést nevezzük spread-nek.
Mivel a brókereknek az eladási ár a legfontosabb, így az eladási árat követhetjük nyomon a grafikonokon. Tehát venni az Ask áron tudunk, eladni viszont a Bid áron.

Éppen azért, ha pillanatnyi áron szeretnénk long pozíciót nyitni, akkor az az Ask ár lesz.

A következő három paraméter a slippage, amit már a múltkori post-ban megbeszéltünk, majd a stop-loss és a take-profit következik, melyeket hogyha 0-ra állítunk, akkor nem létezők lesznek, most ezt használjuk.
A következő paraméter egy egyszerű szöveges komment, amit úgy fogalmazunk meg, ahogy akarunk.

Az ezt követő paraméter a magic number, amit senki sem tud pontosan mi célt szolgál, ami biztos, hogy a felhasználó saját döntése alapján azt ír ide, amit akar, mint egyedi azonosítót.
Egyetlen dolgot fedeztem fel ezzel kapcsolatban, hogy a MetaTrader nem szereti, ha két különböző devizapáron azonos magic number-rel jelzett pozíció van nyitva. Egyszerűen megkavarodik és hülyeséget csinál.
Éppen ezért ide mindig kivétel nélkül valamilyen véletlen számot szoktam tenni. Lehet egy jól meghatározott konstans érték is, de akkor mindenképpen gondoskodjunk arról, hogy a különböző devizapárokon különböző magic number-eket használjunk!
Ezt követően a pozíció nyitás lejárati idejét lehet megadni, ami persze csak akkor értelmes, ha limit, vagy stop pozíciókat nyitunk és akkor is csak addig, amíg meg nem nyílik a pozíció. Ezért ez nekünk mindig 0.

Megnyitott pozíciót csak lezárni lehet, törölni nem!
Ezt azért húztam alá, mert nagyon fontos! Törölni csakis azokat a megbízásokat lehet, amelyek még nem teljesültek, amelyek már teljesültek, azok nyitott pozíciók és csak lezárni lehet őket, ez persze már pénzbe kerül (ára a spread-től és a pozíció méretétől függ), míg a nem teljesült megbízásokat büntetlenül törölhetjük bármikor, ingyenesen.

A legutolsó paraméter pedig a chart-on a nyitást ábrázoló nyilacska színe, ami szintén szabadon választott.

A függvény visszatérési értéke a pozíció nyitási jegy száma, ha sikerült a nyitás. (emlékszünk ugye a múltkori leírásra, miért kezeli így a program ezeket).
Ha ticket nem valami értelmes értéket tartalmaz, akkor nem sikerült a pozíció nyitás és akkor a hibát a felhasználó tudtára kell adni. Erre valók a következő sorok.

Először is pozíció nyitás után kiolvassuk a hiba számát a GetLastError() függvénnyel. Ha ez nem nulla és a ticket változónk is valamilyen nullánál kisebb értéket tartalmaz (tipikusan -1), akkor nem sikerült a pozíció nyitás és a hibár egy Print() függvénnyel a Naplóba írjuk.
A Napló tartalma a MetaTrader kereskedési felületén megtekinthető bármikor a program futásakor, tehát ide mindig üzenhetünk, hogyha a felhasználót szeretnénk tájékoztatni valamiről, ami nem a chart-on kell, hogy legyen.

Tehát ennyit a long pozíció nyitásáról.
A short pozíció nyitása is ugyanilyen egyszerű, csak ott a Bid árat kell megadnunk, és már nyílik is a pozíció.
Tehát így néz ki a short nyitás :
if (TMTrend == "Short" && TVITrend == "Short" && !nyitott)
      {
         ticket=OrderSend(Symbol(),OP_SELL,maxlots,Bid,slippage,0,0,"TrendMagic-TVI - Short",MathRand(),0,Green);
         err = GetLastError();
         if (err != 0 && ticket < 0)
         {
            Print("Error # ", err, "  ", ErrorDescription(err));
         }
      }

Látható milyen egyszerű.

A következő post-ban a stop húzást fogjuk megvalósítani, ezáltal lesz egy stratégiánk, ami jelek alapján pozíciót nyit és zár, indulhat a back test. A back test-ek végrehajtásához a legjobb a hétvége, akkor lehet nyugodtan tesztelgetni.
Tehát igyekszünk holnap minden finomra csiszolni a programunkon, hogy vasárnap békésen tesztelhessen mindenki!

A pozíció méretről ígértem egy kis elmélkedést.
A FOREX esetében - amikor is nem részvényeket vásárlunk, hanem devizapárokat - nem darabonként vesszük, adjuk, hanem kötegekben, csomagokban. Ezt a FOREX úgy nevezi, hogy Lot. Egy ilyen kereskedési egység 100.000 alapdevizát jelent, ha azt a tizedespont után 5 számjegy követi.
Ehhez a tőkeáttétel szerinti fedezet szükséges, ha a tőkeáttételünk 1:100, akkor ennek az egy század részét kell a számlán tartanunk, ha vásárolni akarunk. Ez 1000 USD. Tehát ez nagyon sok. Éppen ezért, mivel a pénzünknek csak maximum 3%-át kockáztatjuk, a maximális kötési mennyiséget be kell lőnünk.

Ha 0.01 lot-ot kötünk, akkor "csak" 10 USD-t kockáztatunk, tehát az óvatosság nem csakhogy nem árt, hanem inkább még használ is.

Nincsenek megjegyzések:

Megjegyzés küldése