In deze blog bespreken we een grafische indicator die is gebaseerd op de slope-direction-trend. Deze indicator is al in verschillende vormen gepubliceerd, maar er was nog geen versie die alle tijdframes in één enkele grafische panel op je scherm weergeeft.
Er zijn al meerdere versies van deze indicator beschikbaar, maar om het overzichtelijk te houden, laat ik je zien hoe je deze kunt gebruiken om de huidige trend voor alle tijdframes in één oogopslag te bekijken.
Je kunt hier zoeken voor meer resultaten over de slope direction line.
Ik heb deze indicator aangepast en in een grafisch paneel geplaatst dat alle tijdframes weergeeft. Een van de aanpassingen is dat gebruikers de methode voor de tweede voortschrijdende gemiddelde kunnen selecteren. De originele code gebruikte een lineair gewogen gemiddelde, terwijl ik de optie bied om de methode voor het gladstrijken te kiezen. Wanneer je voor beide berekeningen een lineair gewogen gemiddelde gebruikt, kan de indicator te responsief zijn, wat kan leiden tot valse signalen over de huidige trend. Door een eenvoudig gemiddelde te gebruiken voor de tweede berekening, krijg je een trend die beter aangeeft waar de prijs naartoe gaat.
Een andere wijziging die ik heb aangebracht, is dat je niet alleen de richting van de trend (omhoog, omlaag of vlak) kunt krijgen, maar ook de waarde ervan. Hierover zal ik in een volgend artikel meer vertellen, waarin ik uitleg hoe je een dubbele slope-direction-indicator kunt gebruiken en daarmee een trading systeem kunt maken.
Maar laten we nu een snelle blik op de code werpen. Eerst definieer ik alle objectnamen die ik ga gebruiken. Dit is een goede praktijk omdat elke keer dat je een objectnaam tussen aanhalingstekens plaatst, er ruimte in het programma voor wordt gereserveerd. Door ze eenmalig te definiëren (met een define-instructie), gebruik je de ruimte in je code maar één keer.
// Definieer trend richtingen #define UPTREND 1 #define DOWNTREND -1 #define FLATTREND 0 // Definieer objecten #define TrendPanel "TrendPanel" #define InfoLine1 "InfoLine1" #define InfoLine2 "InfoLine2" #define TrendLabel "Trend: M1 M5 M15 M30 H1 H4 D1 W1 MN" #define TrendUp "\233" #define TrendDown "\234" #define TrendFlat "\232" #define TrendUnknown "\251" #define StatObjectError "%s(%d) Kon '%s' niet aanmaken. Fout = %d"
Vervolgens definieer ik twee arrays. Een met de pixelpositie voor elk van de 9 tijdframes en de tweede met de tijdframes zelf. Deze zijn gedefinieerd als globale variabelen.
// Definieer globale variabelen int TrendPosition[] = { 44, 64, 88, 114, 136, 156, 174, 194, 216 }; int TrendPeriods[] = { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1 };
De OnInit() functie van onze indicator roept een functie aan om het paneel en de objecten binnen het paneel te maken. Het doet ook een snelle controle op het aantal bars dat gebruikt wordt om de trend te berekenen. Minder dan 3 is eigenlijk nutteloos.
//+------------------------------------------------------------------+ //| Initialisatiefunctie van de aangepaste indicator | //+------------------------------------------------------------------+ int OnInit() { // Maak objecten voor het indicatorpaneel if(Create_Panel() && BarCount >= 3) return(INIT_SUCCEEDED); else return(INIT_FAILED); }
Ik ga niet in detail in op hoe de GetTrend() functie werkt, daar is al goede documentatie over beschikbaar. We bekijken gewoon de grafische functie DisplayTrend().
//+------------------------------------------------------------------+ //| Toon de huidige trend voor alle tijdframes //+------------------------------------------------------------------+ void DisplayTrend(void) { int i, cntr, Trend, LastTrend; string str; for(i=1; i<10; i++) { str = "Trend" + DoubleToStr(i, 0); Trend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method); if(Trend == FLATTREND) { // Ik ben vlak, vind de laatste trendrichting cntr = 1; do { LastTrend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method, false, cntr++); } while(LastTrend == Trend); ObjectSetText(str, TrendFlat, 8, "WingDings", (LastTrend == UPTREND ? Green : Red)); ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 6); } else { ObjectSetText(str, (Trend == UPTREND ? TrendUp : TrendDown), 8, "WingDings", (Trend == UPTREND ? Green : Red)); ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 5 + (Trend == UPTREND ? 1 : -1)); } } }
In feite loop je gewoon door de TrendPeriods[] array (om alle tijdframes te krijgen) en stel je de trendpijl in op basis van de trendrichting van dat tijdframe. Als de trend vlak is, zoeken we de eerste richting die niet vlak is om te weten waar de trend vandaan kwam, zodat we de zijpijl in de kleur van die richting kunnen weergeven.
De Create_Panel() functie in onze OnInit() maakt de objecten die aan de linksonderkant van het scherm zijn verankerd en gebruikt TrendPosition[] om de pijlen op de juiste plaats te zetten.
//+------------------------------------------------------------------+ //| Maak het trendpaneel in de linksonderhoek van het scherm //+------------------------------------------------------------------+ bool Create_Panel(void) { int i; string str; // Maak het trendindicatorvenster if(ObjectCreate(TrendPanel, OBJ_RECTANGLE_LABEL, 0, 0, 0)) { ObjectSetInteger(0, TrendPanel, OBJPROP_XDISTANCE, 1); ObjectSetInteger(0, TrendPanel, OBJPROP_YDISTANCE, 29); ObjectSetInteger(0, TrendPanel, OBJPROP_XSIZE, 240); ObjectSetInteger(0, TrendPanel, OBJPROP_YSIZE, 26); ObjectSetInteger(0, TrendPanel, OBJPROP_BGCOLOR, White); ObjectSetInteger(0, TrendPanel, OBJPROP_BORDER_TYPE, 0); ObjectSetInteger(0, TrendPanel, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSetInteger(0, TrendPanel, OBJPROP_COLOR, Red); ObjectSetInteger(0, TrendPanel, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, TrendPanel, OBJPROP_WIDTH, 2); ObjectSetInteger(0, TrendPanel, OBJPROP_BACK, false); ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTED, false); ObjectSetInteger(0, TrendPanel, OBJPROP_HIDDEN, true); ObjectSetString(0, TrendPanel, OBJPROP_TOOLTIP, "\n"); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, TrendPanel, GetLastError()); return(false); } if(ObjectCreate(InfoLine1, OBJ_LABEL, 0, 0, 0)) { ObjectSet(InfoLine1, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(InfoLine1, OBJPROP_XDISTANCE, 6); ObjectSet(InfoLine1, OBJPROP_YDISTANCE, 15); ObjectSetInteger(0, InfoLine1, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, InfoLine1, OBJPROP_HIDDEN, true); ObjectSetString(0, InfoLine1, OBJPROP_TOOLTIP, "\n"); ObjectSetText(InfoLine1, TrendLabel, 8, "Arial", Black); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine1, GetLastError()); return(false); } if(ObjectCreate(InfoLine2, OBJ_LABEL, 0, 0, 0)) { ObjectSet(InfoLine2, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(InfoLine2, OBJPROP_XDISTANCE, 6); ObjectSet(InfoLine2, OBJPROP_YDISTANCE, 5); ObjectSetInteger(0, InfoLine2, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, InfoLine2, OBJPROP_HIDDEN, true); ObjectSetString(0, InfoLine2, OBJPROP_TOOLTIP, "\n"); ObjectSetText(InfoLine2, " " + DoubleToStr(BarCount, 0) + " / " + DoubleToStr(Method, 0), 8, "Arial", Black); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine2, GetLastError()); return(false); } // Maak trendobject en toon huidige trend for(i=1; i<10; i++) { str = "Trend" + DoubleToStr(i, 0); if(ObjectCreate(str, OBJ_LABEL, 0, 0, 0)) { ObjectSet(str, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(str, OBJPROP_XDISTANCE, TrendPosition[i-1]); ObjectSet(str, OBJPROP_YDISTANCE, 5); ObjectSetInteger(0, str, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, str, OBJPROP_HIDDEN, true); ObjectSetString(0, str, OBJPROP_TOOLTIP, "\n"); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, str, GetLastError()); return(false); } } // Toon huidige trend DisplayTrend(); // Alles goed return(true); }
Deze functie retourneert TRUE als het is gelukt om alle objecten te maken, of FALSE als er een fout is opgetreden bij het maken van een object. Het mooie is dat de indicator in het EXPERT-tabblad van je console de foutcode en het regelnummer van de code waar de fout is opgetreden, weergeeft.
We moeten ook de trendindicator bijwerken voor elke nieuwe tick die we ontvangen. Dit gebeurt door DisplayTrend() aan te roepen in onze start() functie.
//+------------------------------------------------------------------+ //| Iteratiefunctie van de aangepaste indicator | //+------------------------------------------------------------------+ int start() { // Toon huidige trend voor alle tijdframes DisplayTrend(); return(0); }
Tot slot vernietigen we alle objecten die door de indicator zijn gemaakt wanneer we de indicator sluiten.
//+------------------------------------------------------------------+ //| Deinitialisatiefunctie | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Verwijder objecten van de indicator if(ObjectFind(TrendPanel) >= 0) ObjectDelete(TrendPanel); if(ObjectFind(InfoLine1) >= 0) ObjectDelete(InfoLine1); if(ObjectFind(InfoLine2) >= 0) ObjectDelete(InfoLine2); for(int i=1; i<10; i++) if(ObjectFind("Trend"+DoubleToStr(i, 0)) >= 0) ObjectDelete("Trend"+DoubleToStr(i, 0)); }
Dat is het zo'n beetje. Je hebt nu een mooi indicatorpaneel dat de huidige trend voor alle tijdframes toont in de linksonderhoek van je scherm.
Veel plezier ermee!
Reactie 0