szerda, február 23, 2011

Építkezés

Már megint jó sok idő telt el, mentségemre legyen mondva, elég rendesen felborult a megszokott életritmusom. De lassan elülnek a hullámok, a FOREX persze marad, az automatikus kereskedelem és a robot építés még mindig a szívem csücske, így természetesen nem hagyok fel ezzel. Minden nap új tapasztalatokat szerzek.

Fura a mai cím, de mégis jó ide, ugyanis elkezdjük "megépíteni" a robotunkat. Nem kell igazi robotra gondolni, de ebben a szakmában így hívják azokat a programokat, amelyek automatikusan kereskednek.

FIGYELEM! Az itt közzétett programkódok saját szellemi termékeim, de szabadon felhasználhatja bárki. Felelősséget azonban nem tudok érte vállalni,  mint ahogyan a kód használatából származó anyagi károkért sem! MINDENKI SAJÁT FELELŐSSÉGÉRE HASZNÁLJA! A kódok CSAK oktatási céllal kerültek ide! Kellő hozzáértés és fegyelem nélkül TILOS éles számlán használni!

A FOREX robotunk két egyéni indikátort használ, mindkettőt kiveséztem a legutóbbi post-ban. Az egyik a TVI, a másik pedig a TrendMagic. Illetve van még egy harmadik indikátor is, amely a stop-loss-okat húzogatja utánunk. Ő a Parabolic SAR.

A két egyéni indikátorral az a szerencsénk, hogy mindkettő forráskódját fel lehet lelni az interneten, ha esetleg valaki nem találná, vagy nem biztos abban, hogy azt találta meg, amire szükség van, az bátran írjon nekem levelet, "postafordultával" elküldöm az indikátorok forráskódját. Javaslom, hogy módosítás nélkül használja mindenki!

Mindkét indikátor színekkel jelzi, hogy szerinte a trend merre megy. De sajnos egyedül egyik sem megbízható, ezért van szükség arra, hogy legalább kettőt használjunk.

A TVI-ből ráadásul kettőt fogunk használni, mert egy kevés lesz.
Kicsit furmányos ez az indikátor, mert nem egy, hanem két forráskódból áll. Az egyik a TVI.mq4, amely a normális TVI jeleket számolja. A másik a TVI_2color.mq4, amely a nevéhez méltóan két színnel jelöli a trend lehetséges irányát. Ez utóbbi indikátor képtelen egyedül működni, csakis kizárólag az előzőekben említett TVI.mq4 indikátorral együtt működik, tehát mindkettőt be kell másolni az indicators mappába.

A TVI-nek három, a TVI_2color-nak négy paramétere van. Ezek magyarázatára nem térnék ki, legyen elég annyi, hogy elmondom hogyan kell beállítani őket.

A TVI paraméter beállításai tehát a következők :
  • r : 50
  • s : 50
  • u : 5
  • tf : 0
Ezekkel a paraméterekkel fel is tehetjük egy chart-ra tanulmányozni, hogy mit is mutat! Szerintem tanulságos.

A TrendMagic-ről is írtam részletesen legutóbb, összesen két paramétere van :
  • CCI : 50
  • ATR : 12
Ezt is feltehetjük ugyanarra a chart-ra, amire feltettük a TVI-t.
Más dolgunk már nincs is, mint megbarátkozni a Parabolic SAR-ral. Ennek is egy színes változatát használjuk, csak azért, mert programozás szempontjából könnyebb ezt kezelni. Aki átírta, úgy nevezte el, hogy "Parabolic trendchaser", vagyis trend hajhász... :o)
Beállításai :
  • AlertsEnabled : false
  • Step : 0.06
  • Maximum : 0.1
  • Precision : 7
  • TimeFrame : 0
A paraméterek értelmezését most szintén nem taglalnám! A lényege, hogy így kell beállítani. Aki nem akar a Parabolic trendchaser-rel bajlódni, az használhatja a beépített Parabolic SAR-t is, a Step és a Maximum paramétereket felhasználva ugyanezt az eredményt fogjuk kapni, csak nem lesz szép színes és később a programozás során nehezebb kezelni.
Ha ezekkel a beállításokkal ezt is felteszitek a chart-ra, akkor látható, hogy igen szűk stop-okat lehet vele húzni, ha a bróker hagyja. De erről kicsit később.

Tehát, meg is vagyunk az indikátorok beállításával. Látszik szépen a chart-on, hogy milyen jól együtt járnak ezek az indikátorok :

TVI-TrandMagic stratégia


A stratégia pedig rém egyszerű, amikor a TVI zöld, a TrendMagic kék, és a Parabolic alsó kék pöttyöket rajzol, akkor long pozíciót nyitunk és a Parabolic-nak megfelelően húzzuk a stop-ot. Amikor a trend vált, akkor egyszerűen "kistoppolódunk" és már készen is állunk a következő pozíció nyitásra.

A programunk tehát a következő részekből fog állni :
  • Indikátorok adatainak begyüjtése
  • A jelzések alapján pozíció nyitás
  • A nyitott pozíciók stop-jainak húzogatása
A zárással azért nem foglalkozunk, mert a kistoppolódás miatt úgysem kell zárnunk.

A program kód eleje mindig azzal kezdődik, hogy a felhasználótól bekérjük az indulási paramétereket, illetve az alapbeállítások módosítását tesszük lehetővé számukra. Akinek nem tetszik az 50-es érték a TVI esetében, bátran átállíthatja saját felelősségére.

Nem szeretném elmagyarázni a nyelv egyes elemeit, remélem mindenki programozott már és tudja mi az a változó, meg hogy globális változó, függvényhívás, deklaráció, definíció, stb.

Tehát a program azoknak a változóknak a definíciójával kezdődik, amelyeket a felhasználó számára is elérhetővé szeretnénk tenni, egyben a programunk ezeken keresztül tartja a kapcsolatot a felhasználóval, ha adatokat kérünk be.
Ezek a változók a hagyományos C#-ban megszokott típusúak lehetnek, de az elé írt extern klauzulával lehet őket láthatóvá tenni a felhasználó számára.
A mi esetünkben a következő lesz a lista :
extern double maxlots=0.01;
extern int slippage=5;
extern int TrendMagicCCI=50;
extern int TrendMagicATR=5;
extern int TVI_rs=50;
Látható tehát, milyen adatokat kérünk, illetve az is látható, hogy nem csak kérünk, de alapbeállításként fel is ajánlunk egy-egy értéket. Ennek ugyebár ott az értelme, hogyha a felhasználó ránk bízná a program paraméterezését, akkor is legyen valami induló adat.

Nézzük sorban őket:
  • maxlots : ez a kötéseink során fontos, azt fogja tartalmazni, milyen méretű pozíciót nyithatunk. Ez most egyenlőre egy fix érték lesz, amit ide beállítunk.
  • slippage : ez egy csúszó érték, amely szintén a kötések során fontos. Azt az értéket tartalmazza, amivel a bróker eltérhet az általunk megadott kötési, zárási ártól. Erről mindjárt írok egy-két sort, mert ez fontos, meg kell értenetek, mire való ez.
  • TrendMagicCCI : ez ugyebár a TrendMagic indikátorunk CCI paramétere
  • TrendMagicATR : ez pedig a TrendMagic indikátor ATR paramétere
  • TVI_rs : ez pedig a TVI indikátorunk r és s értéke (a kettőt mindig ugyanarra az értékre állítjuk) az u értéket viszont nem engedjük ki a kezünk közül, az fixen 5.
Tehát pár mondat a slippage-ről. Amikor a MetaTrader-en keresztük utasítást adunk a brókernek, hogy nyisson, vagy zárjon egy pozíciót, akkor meg kell adnunk egy árat. Ez az ár azonban nem biztos, hogy a pillanatnyi ár. Ha ugyanis miközben az utasítás az internet éterén keresztül beérkezik a brókerhez, ott feldolgozásra kerül és közben egy újabb tick érkezik, az ár máris megváltozik és a kötést nem engedi végrehajtani a rendszer.
Ezért vezették be a slippage nevű paramétert, amely megadja, hogy a bróker a pozícióink kezelésekor mennyivel térhet le az utasításban megadott ártól. Ez minden esetben az aktuális valutapár, vagy részvény értékének felel meg, tehát ha a tizedespont után 5 számjegyet látunk, akkor az ötödik számjegyre vetített értéket jelenti. Az alapként beállított 5-ös érték EURUSD esetében (ahol 5 számjegy követi a tizedespontot, de a negyedik számjegy jelenti az 1 PIP-et) mindössze 0.5 PIP csúszást enged meg a brókernek.

Ha ezt az értéket 0-ra állítanánk, egy gyorsan változó piac esetében többszöri próbálkozás ellenére sem biztos, hogy ott nyitunk pozíciót, ahol akarunk. Esetleg előfordulhat az is, hogy egyáltalán nem tudunk pozíciót nyitni, vagy zárni.

Az 5-ös érték általában jól működik és kellően kicsi ahhoz, hogy kötni lehessen. Nem ajánlott módosítani, de ezt mindenki maga döntheti el. Ha kivesszük az extern klauzulát előle, a felhasználó nem tudja piszkálni, de az érték ott lesz benne.

Ahogyan már egy korábbi post-ban ecseteltük, az Expert Advisor három részből épül fel. Van egy init(), egy deinint() és egy start() függvénye. Ezek közül az init() akkor fut le, amikor a chart-ra feltesszük a programot, de csak egyetlen egyszer fut le. A feladata azoknak a tevékenységeknek az elvégzése, amelyeket a kereskedés előtt egyszer meg kell tenni.
Ugyanígy a deinit() függvény pedig akkor fut le, amikor levesszük a chart-ról a FOREX robotunkat, ez is csak egyszer fut le, hasonlóképpen az előzőekhez a futás utáni takarítás a dolga.
A start() függvény viszont a szíve az Expert Advisor-nak, ugyanis ez fut le minden egyes alkalommal, amikor csak érkezik egy tick, azaz egy kereskedési adat.

Miután programunk nagyon egyszerű és nem helyez el mindenféle objektumot a chart-on (erről is lesz később szó), ezért csak a start() függvény megírására kell koncentrálnunk.

Mielőtt azonban a lelkét kezdenénk fejlesztgetni a robotunknak, érdemes az extern változók után felvenni a globális változóinkat.
Azokat a változókat érdemes ide felvenni, amelyek értékére két beérkező tick között is szükségük lesz, tehát ha ezt a start() függvényen belül vennénk fel, minden egyes tick alkalmával, amikor lefut  start() függvény, a változó újra és újra létrejönne, de azzal a kezdőértékkel, amivel definiáljuk, illetve ha az nincs, akkor valamilyen véletlen szerű kezdőértékkel.
Ilyenek azok a globális változók, amelyek a program futása közben végig meg kell, hogy őrizzék az értéküket, amíg le nem állítjuk.

Tipikusan állapot jelző változókra van itt szükség, vagy számlálókra, és ehhez hasonlókra.
Valami ilyesmi lehet :
int currentbar;
string TMTrend, TVITrend;
int orders;
bool nyitott;
 Némi magyarázat :
  • A currentbar változó fogja tartalmazni az aktuális gyertyák számát, amelyet a chart megjelenít. Ez fontos lesz majd.
  • a string változók arra valók, hogy az egyes indikátorok által jelzett trendet jelöljék. Ez lesz az alapja a pozíció nyitásnak
  • Az orders változó arra lesz hivatott, hogy a pozíció kezelések alkalmával a pozíció egyedi azonosítóját tartalmazza majd.
  • A nyitott nevű változónk pedig azt mutatja majd, hogy van-e nyitott pozíciónk már, avagy sem
 Most pedig lássuk a FOREX robot lelkét!

Azzal fogjuk kezdeni, hogy amikor egy újabb tick érkezik, megvizsgáljuk, hogy ez a tick egy új gyertya legelső tick-je, vagy pedig egy már folyamatban lévő gyertya valahányadik tick-je.
Miért jó ez nekünk?
Azért, mert a tőzsdeiskolákban mindenhol azt tanítják, hogy csak a már bezárult gyertya az igazi gyertya, a még be nem zárult gyertya változhat, hiszen a piacon bármi megtörténhet. Előfordulhat, hogy a bika gyertyából az adott időintervallumon belül hirtelen medve gyertya lesz. Na, ekkor aztán fuccs a stratégiának. Tehát csak a bezárult gyertyákkal foglalkozunk.

A kód így néz ki :
if (currentbar < Bars)
      currentbar = Bars;
   else
      return;
A magyarázat pedig nagyon egyszerű.
A currentbar nevű változónk, amelyet globálisnak vettünk fel, tartalmazza a chart-on található gyertyák számát. Kezdetben egyébként valami teljesen kiszámíthatatlan értéket tartalmaz, tehát elsőre biztosan lefut a start() függvényünk. (ha ez semmiképpen sem akarjuk, akkor az init() függvényünkben ennek a változónak adhatunk értéket, valahogy így : currentbar = Bars; Így pontosan azt az értéket fogja tartalmazni, ami a chart-on van, így a programunk addig nem fut le, amíg az aktuális gyertya le nem zárul. Íme egy lehetséges és értelmes módja az init() függvény használatának.)
A Bars rendszerváltozó az aktuális gyertyák számát tartalmazza, amelybe beletartozik az éppen be nem zárt gyertya is. Ez a globális rendszerváltozó a MetaTrader saját globális változója és csakis olvasható értéket tartalmaz. Lesz még pár ilyen amivel megismerkedünk.
Tehát a kódrészlet úgy működik, hogy ha az általunk megjegyzett gyertyák száma kevesebb, mint a chart-on lévő aktuális gyertyák száma, akkor bizony ez éppen egy új gyertya nyitását jelenti, tehát jól megjegyezzük mennyi is a chart-on a gyertyák száma és hagyjuk lefutni a start() függvényt.
Ha viszont az eltárolt gyertyaszám megegyezik a chart-on lévő gyertyaszámmal, akkor az érkező tick az aktuális gyertyához tartozik, tehát egy return utasítással be is fejezzük a start() függvényünk futását.

Miután az új gyertyát megkezdő tick az előző gyertya záró tick-je is egyben, így a start() függvényünk minden esetben lefut, amikor egy újabb gyertya lezárul, de csakis akkor, nem máskor. Ilyen egyszerű.

A legközelebbi post-ban innen folytatjuk a kód írását. Talán kedvcsinálónak ennyi is elég lesz mára. Igyekszem nem három hónap múlva folytatni... :o)

Nincsenek megjegyzések:

Megjegyzés küldése