Indikatoren: SuperTrend

 

SuperTrend:

SuperTrend Trendindikator.

Super Trend Indikator

Autor: Nikolay Kositsin

 

Also das ist absolut nicht mein Programmierstil.

Man sieht ja vor Bäumen den Wald nicht mehr = man sieht ja vor lauter Commentar den Code nicht mehr.

Auserdem wird der input parameter 'shift' überhaupt nicht verwendet.

Ich hab das neu programmiert, in meinem Stil, vielleicht können sich die Herren 'Superprogrammierer' ein Scheiberl abschneiden.

//+------------------------------------------------------------------+
//|                                                   Supertrend.mq5 |
//| Original code found on          https://www.mql5.com/de/code/527 | 
//| Original code from Jason Robinson, rewritten by Nikolay Kositsin |
//| Improved by Ing. Otto Pauser alias Kronenchakra                  |
//+------------------------------------------------------------------+ 

//--- inckudes
#include <Utils.mqh>

//--- general properties
#property copyright COPY 
#property link      LINK 
#property version   "1.00"

//--- indicator properties
#property indicator_chart_window
#property indicator_buffers 4 
#property indicator_plots   4

//--- input parameters
input int CCIPeriod  =  50;   // CCI indicator period 
input int ATRPeriod  =   5;   // ATR indicator period
input int Level      =   0;   // CCI activation level

//---- indicator buffers
double   ATR[],
         CCI[];
double   TrendUp[],
         TrendDn[];
double   SignUp[],
         SignDn[];
         
//---- global variables
int      min_rates_total;
int      ATR_Handle,
         CCI_Handle;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   min_rates_total=MathMax(CCIPeriod,ATRPeriod);

   CCI_Handle=iCCI(NULL,0,CCIPeriod,PRICE_TYPICAL);
   if(InvalidHandle(CCI_Handle,"iCCI"))
      return(INIT_FAILED);

   ATR_Handle=iATR(NULL,0,ATRPeriod);
   if(InvalidHandle(ATR_Handle,"iATR"))
      return(INIT_FAILED);

   string shortname=IndiShortName("Supertrend",CCIPeriod,ATRPeriod);
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);

   InitBuffer(TrendUp,DRAW_LINE ,"Supertrend Up"         ,clrLime,min_rates_total,0  ,2,true);
   InitBuffer(TrendDn,DRAW_LINE ,"Supertrend Down"       ,clrRed ,min_rates_total,0  ,2,true);
   InitBuffer(SignUp ,DRAW_ARROW,"Supertrend signal Buy" ,clrLime,min_rates_total,108,1,true);
   InitBuffer(SignDn ,DRAW_ARROW,"Supertrend signal Sell",clrRed ,min_rates_total,108,1,true);

   ArraySetAsSeries(ATR,true);
   ArraySetAsSeries(CCI,true);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double& high[],
                const double& low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   if                                                    // check
      (
          BarsCalculated(CCI_Handle)<rates_total ||      // check CCI indicator
          BarsCalculated(ATR_Handle)<rates_total ||      // check ATR indicator
          rates_total<min_rates_total                    // check for enough bars
      )
          return(0);                                     // try next tick

   int limit,to_copy,bar;

   ArraySetAsSeries(high,true);                          // has to be set AsSeries every tick
   ArraySetAsSeries(low ,true);

   if(prev_calculated>rates_total || prev_calculated<=0) // checking for the first start of the indicator calculation
      limit=rates_total-min_rates_total;                 // starting index for calculation of all bars
   else
      limit=rates_total-prev_calculated;                 // starting index for calculation of new bars

   to_copy=limit+1;                                      // copy ATR-Data to buffer
   if(CopyBuffer(ATR_Handle,0,0,to_copy,ATR)<=0) return(0);

   to_copy++;                                            // copy CCI-Data to buffer
   if(CopyBuffer(CCI_Handle,0,0,to_copy,CCI)<=0) return(0);

   for(bar=limit; bar>=0; bar--)                         // calculation main loop
     {
      TrendUp[bar]=NULL;                                 // clear all buffers
      TrendDn[bar]=NULL;
      SignUp [bar]=NULL;
      SignDn [bar]=NULL;
                                                         // calculate the lines
      if(CCI[bar]>=Level && CCI[bar+1]<Level) TrendUp[bar]=TrendDn[bar+1];
      if(CCI[bar]<=Level && CCI[bar+1]>Level) TrendDn[bar]=TrendUp[bar+1];

      if(CCI[bar]>Level)                                 
        {
         TrendUp[bar]=low[bar]-ATR[bar];
         if(TrendUp[bar]<TrendUp[bar+1] && CCI[bar+1]>=Level) TrendUp[bar]=TrendUp[bar+1];
        }

      if(CCI[bar]<Level)                                 
        {
         TrendDn[bar]=high[bar]+ATR[bar];
         if(TrendDn[bar]>TrendDn[bar+1] && CCI[bar+1]<=Level) TrendDn[bar]=TrendDn[bar+1];
        }

      if(TrendDn[bar+1]!=0.0 && TrendUp[bar]!=0.0) SignUp[bar]=TrendUp[bar];  // check signal UP
      if(TrendUp[bar+1]!=0.0 && TrendDn[bar]!=0.0) SignDn[bar]=TrendDn[bar];  // check signal DOWN
     }
    
   return(rates_total);
}
//+------------------------------------------------------------------+
//|                                                        Utils.mqh |
//|                               Copyright © 2018, Ing. Otto Pauser | 
//|                       https://www.mql5.com/de/users/kronenchakra | 
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| definitions                                                      |
//+------------------------------------------------------------------+

#define COPY   "Copyright © 2018, Ing. Otto Pauser"
#define LINK   "https://www.mql5.com/de/users/kronenchakra"
#define SPACER "—————————————————————" 

//+------------------------------------------------------------------+
//| abbreviations                                                    |
//+------------------------------------------------------------------+

#define PRICE ENUM_APPLIED_PRICE
#define TIMEF ENUM_TIMEFRAMES

//+------------------------------------------------------------------+
//| Auxiliary functions                                              |
//+------------------------------------------------------------------+

void InitBuffer(double &_buffer[], ENUM_DRAW_TYPE _type, string _label, color _color, int _begin, int _arrow=159, int _width=1, bool _series=false)
{
   static int idx=0;                                  // initialize bufferindex to 0
   SetIndexBuffer     (idx,_buffer);                  // initialize buffer
   ArrayInitialize    (_buffer ,NULL);                // initialize buffer
   ArraySetAsSeries   (_buffer ,_series);             // set AsSeries
                                                      // set properties
   PlotIndexSetInteger(idx,PLOT_DRAW_TYPE  ,_type );
   PlotIndexSetInteger(idx,PLOT_LINE_COLOR ,_color);
   PlotIndexSetInteger(idx,PLOT_LINE_WIDTH ,_width);
   PlotIndexSetInteger(idx,PLOT_DRAW_BEGIN ,_begin);
   PlotIndexSetInteger(idx,PLOT_ARROW      ,_arrow);
   PlotIndexSetString (idx,PLOT_LABEL      ,_label);
   PlotIndexSetDouble (idx,PLOT_EMPTY_VALUE,NULL  );
   idx++;                                             // increment bufferindex for next call
}

bool InvalidHandle(int _handle, string _msg)
{
   if(_handle==INVALID_HANDLE)                     // check handle
      Alert("*ERROR* creating "+_msg+" handle.");  // info
   return(_handle==INVALID_HANDLE);                // return true if invalid
}

string IndiShortName(string _name, int val_1, int val_2=NULL, int val_3=NULL)
{
   string result=_name+"("+IntegerToString(val_1);
   if(val_2!=NULL)
      result=result+","+IntegerToString(val_2);
   if(val_3!=NULL)
      result=result+","+IntegerToString(val_3);
   return(result+")");
}

//+------------------------------------------------------------------+
//| Calculation functions                                            |
//+------------------------------------------------------------------+
double StdDeviation(int position,const double &price[],const double &MAprice[],int period)
{
   int i;
   double StdDev_dTmp=0.0;

   if(position<period) return(StdDev_dTmp);        // check position

   for(i=0;i<period;i++)                           // calcualte StdDev
      StdDev_dTmp+=MathPow(price[position-i]-MAprice[position],2);

   StdDev_dTmp=MathSqrt(StdDev_dTmp/period);

   return(StdDev_dTmp);                            // return calculated value
}

Sieht doch gleich ganz übersichtlich aus.

Könnte sich eventuell auch MetaQutes was abschauen, zB: wie man Plotbuffer in nur einer Zeile definiert.

Dateien:
supertrend.mq5  11 kb
Utils.mqh  7 kb
 

Otto,

das:

      TrendUp[bar]=NULL;                                 // clear all buffers
      TrendDn[bar]=NULL;
      SignUp [bar]=NULL;
      SignDn [bar]=NULL;

ist gefährlich. NULL ist vom typ 'void'. Irgendwann später könnte vielleicht, um MT5 noch schneller zu machen, tatsächlich nix zugewiesen werden (dann bliebe der alt bestehen) oder es entsteht ein Zufallswert, wenn der Speicherplatz wechselt.

Imho wäere es besser für das Symbol _Symbol und für Werte entweder EMPTY_VALUE oder direkt 0 verwenden. So verleihst Du dem Nichts ein Sein. ;)