kedd, április 16, 2013

Egy különleges - támasz ellenállás - indikátor forex robotokhoz

Ahogyan kifejlődött

Amikor tőzsdézni tanultam, sokat kellett küzdenem azzal, hogy mi számít völgynek és mi számít csúcsnak. Éppen ezért sokat gondolkodtam később egy olyan indikátoron, ami megjelöli nekem a csúcsokat és a völgyeket! Mindjárt rávilágítok arra is, hogy miért!

Sokat kísérleteztem, keresgéltem a neten, de sehogyan sem találtam olyan indikátort, amivel elégedett lettem volna, mert sokszor oda is rajzol egy indikátor völgyet és csúcsot, ahová én nem tenném. Viszont, ahová völgy és csúcs megjelölést tennék, oda meg nem tesz jelet!

Na de miért is probléma ez?
Rengeteg stratégiát néztem át az elmúlt évek során, különösen azért, hogy FOREX robotot készítsek belőle. A legtöbb stratégia indikátor betegségben szenved, mert több, mint 6 indikátort használnak, amelyek különféle kombinációi esetén nyitnak pozíciót, amit aztán még többféle kombináció esetében zár le.
A legtöbb stratégia az emberi megérzésre, intuícióra, vagy valami olyasmire hajaz, amiből aztán lehetetlen egy jól működő expert advisor-t összehozni!

Ezzel szemben, a leges-legegyszerűbb stratégiák, amelyekkel kézzel kereskedni is lehet, a támasz-ellenállás átlépésekre alapszik, és ezeket viszont nem nehéz leprogramozni, ha az ember kellő gyakorlatra tesz szert!
És itt jön a csúcs-völgy megállapítás problémája.

Az alapötlet rém egyszerű, ebből sikerült azután építkezni.
Hogyan állapítsunk meg völgyet és csúcsot, ez itt a kérdés. Amikor tanultam a tőzsdézés fortélyait, volt egy érdekes megállapítási "algoritmus", ami segített megtanulni a völgy és csúcs meghatározását. Ha ez nem megy, akkor felejtsük is el, hogy kézzel kereskedni fogunk valaha is!
Erre a "feladatra" az volt a "mankó", hogy feltettem a chart-ra egy 2-es és egy 6-os mozgóátlagot (Moving Average). Ezekkel kezdtem operálni. Ha a gyorsabb MA alulról felfelé keresztezi a lassabbat, akkor ott a közelben kell lennie egy völgynek, míg ha felülről lefelé keresztezi, akkor ott meg egy csúcsnak kell lennie valamerre a keresztezés előtt!

Amint ezt felfedeztem, már sokkal könnyebb volt a völgyeket és csúcsokat szubjektíven meghatározni. Igen ám, de ez kézi módszer, segít a kézi kereskedésben, de nem segít automatizáltan.
Egy olyan indikátorban kezdtem gondolkodni, amely megjelöli a csúcsokat és völgyeket, de jól is használható.

Végül sikerült összerakni! Nem sima vagy exponenciális mozgóátlagot használtam, hanem súlyozottat, és mellé tettem egy logikát, az indikátor kereszteződése után visszamenőleg a Highest() és a Lowest() függvénnyel megkeresi a legalacsonyabb pontot és a legmagasabb pontot  (highest high és lowest low logika). Ott lesznek a csúcsok és völgyek!

De hogy még jobban hangolható legyen a dolog, a Highest() és a Lowest() függvények vizsgálódási paraméterét - tehát, hogy hány gyertyára visszamenőleg keressék meg a csúcsot és völgyet - változtathatóra állítottam be, sőt, a mozgóátlagok paraméterét is!

Addig, amíg az indikátor nyilakkal bejelölte a csúcsot és völgyet, kézi kereskedéshez kiváló, de forex robot számára nem túl használható megoldás született. Sok a baj ezekkel a nyilakkal.
Robot számára valami egyszerűbb kell. Kitaláltam hát, hogy a Donchian channel mintájára elkészítem az indikátor "csatornásított" változatát, amelyben ugyanúgy három paraméterrel lehet meghatározni a tulajdonságát (MA-k és a Highest és Lowest függvények paraméterét).

Ez nagyon bejött! A csatornából kitörő gyertya azonnal jelzi a trend megindulását, a csatorna érintése viszont tökéletes megoldás oldalazás végig kereskedésére! A robotok is szeretik, mert egy határozott vonal átlépést sokkal könnyebb ellenőrizni programból, mint nyilakat keresgélni visszamenőleg X gyertyára!

Az indikátor neve : TopBottomChannel.
Paraméterei :
  • sens : alapérték 20, azt a gyertyaszámot adja meg, amelyen belül meg kell keresni a legmagasabb, vagy a legalacsonyabb pontját a gyertyatrendnek.
  • slowMA : alapérték 6, lassú mozgóátlag periódus ideje.
  • fastMA : alapérték 2, gyors mozgóátlag periódus ideje.
Lehet játszani a beállításokkal, de az alapértékek általában jók. M1-től fölfelé kereskedésre is lehet hazsnálni, mindjárt leírom hogyan.

Az indikátor :

 //+------------------------------------------------------------------+  
 //|                       TopBottomChannel.mq4 |  
 //|                  Copyright © 2009, Janos Antal |  
 //|                                 |  
 //+------------------------------------------------------------------+  
 #property copyright "Copyright © 2013, Janos Antal"  
 #property link   "http://tozsdecapak.blogspot.hu"  
   
 #property indicator_chart_window  
 #property indicator_buffers 2  
 #property indicator_color1 DodgerBlue  
 #property indicator_color2 Red  
   
 #include <stderror.mqh>  
 #include <stdlib.mqh>  
   
 #include <WinUser32.mqh>  
   
 #import "user32.dll"  
   int RegisterWindowMessageA(string lpstring);  
 #import  
   
 #define CHART_CMD_UPDATE_DATA  33324  
   
 extern int sens = 20;  
 extern int slowMA = 6;  
 extern int fastMA = 2;  
   
 double top[], bottom[];  
 int bar;  
 int hwnd = 0;  
 //+------------------------------------------------------------------+  
 //| Custom indicator initialization function             |  
 //+------------------------------------------------------------------+  
   
 int UpdateChartWindow()  
 {    
   if(hwnd == 0) {  
    //Megkeressük a chart window-t az update-eléshez  
    hwnd = WindowHandle(Symbol(), Period());  
   }  
   if(hwnd!= 0) {  
    if (IsDllsAllowed() == false) {  
      //DLL calls engedélyezve kell legyen  
      Print("Dll calls must be allowed");  
      return (-1);  
    }  
    if (PostMessageA(hwnd,WM_COMMAND,CHART_CMD_UPDATE_DATA,0) == 0) {  
      //Nem sikerült, bezárult az ablak  
      hwnd = 0;  
    } else {  
      //Sikerült  
      int MT4InternalMsg = RegisterWindowMessageA("MetaTrader4_Internal_Message");  
      PostMessageA(hwnd,MT4InternalMsg,2,1);       
      return (0);  
    }  
   }  
   return (-1);  
 }  
   
 int init()  
  {  
   SetIndexStyle(0,DRAW_LINE,0,2);  
   SetIndexBuffer(0,top);  
   SetIndexLabel(0,"Top");  
   SetIndexArrow(0,241);  
   
   SetIndexStyle(1,DRAW_LINE,0,2);  
   SetIndexBuffer(1,bottom);  
   SetIndexLabel(1,"Bottom");  
   SetIndexArrow(1,242);  
   return(0);  
   bar=0;  
  }  
 //+------------------------------------------------------------------+  
 //| Custom indicator deinitialization function            |  
 //+------------------------------------------------------------------+  
 int deinit()  
  {  
 //----  
     
 //----  
   return(0);  
  }  
 //+------------------------------------------------------------------+  
 //| Custom indicator iteration function               |  
 //+------------------------------------------------------------------+  
 int start()  
 {  
   int  counted_bars=IndicatorCounted();  
   int bi;  
   int ti;  
   int index,i,j;  
   double FMWA1, FMWA2, SMWA1, SMWA2, t,b;  
       
   if(counted_bars<0) return(-1);   
   if(counted_bars>0) counted_bars--;   
     
   int limit = Bars-counted_bars;  
     
   if (bar == Bars)  
   {  
    return;  
   }else  
   {  
    bar=Bars;  
   }  
     
   if (limit < 1500)  
    limit=1500;  
   
   for(i=limit;i>0;i--)  
   {  
    FMWA1=iMA(NULL,0,slowMA,0,MODE_LWMA,PRICE_CLOSE,i);  
    FMWA2=iMA(NULL,0,slowMA,0,MODE_LWMA,PRICE_CLOSE,i-1);  
    SMWA1=iMA(NULL,0,fastMA,0,MODE_LWMA,PRICE_CLOSE,i);  
    SMWA2=iMA(NULL,0,fastMA,0,MODE_LWMA,PRICE_CLOSE,i-1);  
      
    top[i]=GlobalVariableGet("Top"+Symbol()+Period());  
    bottom[i]=GlobalVariableGet("Bottom"+Symbol()+Period());      
              
    if (SMWA1 > FMWA1 && SMWA2 < FMWA2)            
    {  
      bi=iLowest(Symbol(),Period(),MODE_LOW,sens,i);  
      b=Low[bi];  
      for(j=0;j<=bi;j++)  
      {  
       bottom[j]=b;  
      }  
      GlobalVariableSet("Bottom"+Symbol()+Period(),b);  
    }  
      
    if (SMWA1 < FMWA1 && SMWA2 > FMWA2)            
    {  
      ti=iHighest(Symbol(),Period(),MODE_HIGH,sens,i);  
      t=High[ti];  
      for(j=0;j<=ti;j++)  
      {  
       top[j]=t;  
      }  
      GlobalVariableSet("Top"+Symbol()+Period(),t);      
    }   
   }  
     
   UpdateChartWindow();  
 }  

Kereskedés

Az időtáv gyakorlatilag bármi lehet, M1-től D1-ig, bár azt meg kell mondjam, hogy magasabb időtávon biztosabb a jel, de aki tőzsdézik, jól tudja ezt.

Trendben
Pozíció nyitás : amikor az alsó vonal alatt zár egy gyertya, short pozíció nyitása, illetve ha a felső vonal fölött zár a gyertya, akkor long. Stop-loss lehet az átlépés helye, vagy a korábbi völgy, azaz a csatorna alja.

Pozíció zárás: több megoldás működhet, nekem ami eddig legjobban bejött, az az, ha mondjuk a felső vonal fölött zár a gyertya, megnyitom a long-ot, majd az árfolyam elkezd felfelé mozogni. Amikor visszateszt, vagy counter trend kezdődik, létrejön egy újabb mozgóátlag keresztezés, és a TopBottomChannel felső vonala felugrik. Na ekkor zárom a a long-ot. Short-nál ugyanígy, csak ellentétes irányban természetesen.
Másik megoldás egy követő stop, ami lehet ATR alapú (ha a bróker enged közeli stopokat), vagy lehet fix. Lehet nullába húzós (break even stop) is, majd ezután indul a követő stop húzás. 

Oldalazásban
Pozíció nyitás : amikor a csatorna vonala "ugrik", akkor detektálja a mozgóátlagok kereszteződését. Ekkor általában "megérinti" a csatorna tetjét, vagy az alját egy gyertya, de nem lépi át (oldalaz). Ekkor érdemes trend irányú pozíciót nyitni! Tehát ha a felső vonal "ugrott", akkor short, mert már lefelé megy az árfolyam, ha a pedig az alsó vonalat érinti, akkor long. Stop-loss lehet a csatorna vonal maga, célárnak pedig meg lehet jelölni a másik csatorna vonalát.

Pozíció zárás : amikor eléri az ár az alsó csatornát, akkor céláron, vagy kézzel ott. Esetleg követő stop, de ez rosszabb hatásfokkal működik. 

Sok sikert a kereskedéshez!

Nincsenek megjegyzések:

Megjegyzés küldése