#property description "Der Indikator zeigt die Kerzen mit dem älteren auf die aktuelle Zeitrahmen." //--- Indikator Einstellungen #property indicator_chart_window #property indicator_buffers 16 #property indicator_plots 8 //---- plot 1 #property indicator_label1 "BearBody" #property indicator_color1 clrSeaGreen,clrSeaGreen //---- plot 2 #property indicator_label2 "BearBodyEnd" #property indicator_color2 clrSeaGreen,clrSeaGreen //---- plot 3 #property indicator_label3 "BearShadow" #property indicator_color3 clrSalmon,clrSalmon //---- plot 4 #property indicator_label4 "BearShadowEnd" #property indicator_color4 clrSalmon,clrSalmon //---- plot 5 #property indicator_label5 "BullBody" #property indicator_color5 clrOlive,clrOlive //---- plot 6 #property indicator_label6 "BullBodyEnd" #property indicator_color6 clrOlive,clrOlive //---- plot 7 #property indicator_label7 "BullShadow" #property indicator_color7 clrSkyBlue,clrSkyBlue //---- plot 8 #property indicator_label8 "BullShadowEnd" #property indicator_color8 clrSkyBlue,clrSkyBlue //--- vordefinierte Konstante #define INDICATOR_EMPTY_VALUE 0.0 //--- Eingabeparameters input ENUM_TIMEFRAMES InpPeriod=PERIOD_H4; // Der Zeitrahmen für die Berechnung des Indikators input datetime InpDateStart=D'2013.01.01 00:00'; // das Anfangsdatum der Analyse //--- die Indikator Puffers für die Bären Kerzen double ExtBearBodyFirst[]; double ExtBearBodySecond[]; double ExtBearBodyEndFirst[]; double ExtBearBodyEndSecond[]; double ExtBearShadowFirst[]; double ExtBearShadowSecond[]; double ExtBearShadowEndFirst[]; double ExtBearShadowEndSecond[]; //--- die Indikator Puffers für die Bullen Kerzen double ExtBullBodyFirst[]; double ExtBullBodySecond[]; double ExtBullBodyEndFirst[]; double ExtBullBodyEndSecond[]; double ExtBullShadowFirst[]; double ExtBullShadowSecond[]; double ExtBullShadowEndFirst[]; double ExtBullShadowEndSecond[]; //--- globale Variablen datetime ExtTimeBuff[]; // Puffer für Zeit mit der höheren Zeitrahmen int ExtSize=0; // die Größe des Zeitpuffers int ExtCount=0; // der Index innerhalb des Zeitpuffers int ExtStartPos=0; // die Anfangsposition für die Berechnung des Indikators bool ExtStartFlag=true; // Die Hilfsflagge für das Erhalten der Anfangsposition datetime ExtCurrentTime[1]; // die letzte Zeit wenn der Bar auf dem älteren Zeitrahmen gebildet war datetime ExtLastTime; // die letzte Zeit auf dem älteren Zeitrahmen, für den die Berechnung erzeugt war bool ExtBearFlag=true; // die Flagge für die Bestimmung der Ordnung der Speicherung von Daten in die Bären Indikator Puffers bool ExtBullFlag=true; // die Flagge für die Bestimmung der Ordnung der Speicherung von Daten in die Bullen Indikator Puffers int ExtIndexMax=0; // der Index des maximalen Elementes in dem Array int ExtIndexMin=0; // der Index des minimalen Elementes in dem Array int ExtDirectionFlag=0; // die Richtung Die Bewegungen des Preises in der aktuellen Kerze //--- der Einzug zwischen dem Eröffnungspreis und Schlusspreis der Kerze für die richtige Zeichnung const double ExtEmptyBodySize=0.2*SymbolInfoDouble(Symbol(),SYMBOL_POINT); //+------------------------------------------------------------------+ //| Zeichnung der Hauptteil der Kerze | //+------------------------------------------------------------------+ void FillCandleMain(const double &open[],const double &close[], const double &high[],const double &low[], const int start,const int last,const int fill_index, int &index_max,int &index_min) { //--- finden Sie die Indexe der maximalen und minimalen Elemente in den Arrays index_max=ArrayMaximum(high,ExtStartPos,last-start+1); // Maximum in Hoch index_min=ArrayMinimum(low,ExtStartPos,last-start+1); // Minimum in Tief //--- bestimmen Sie, wie viel Bars auf den aktuellen Zeitrahmen wir werden zeichnen int count=fill_index-start+1; //--- wenn der Schlusspreis am ersten Bar mehr als der Schlusspreis am letzten Bar - es gibt Bullen Kerze if(open[start]>close[last]) { //--- wenn früher die Kerze Bullen war, so freimachen wir die Werte den Bären Indikator Puffers if(ExtDirectionFlag!=-1) ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count); //--- Bären Kerze ExtDirectionFlag=-1; //--- bilden Sie die Kerze FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start], close[last],high[index_max],low[index_min],start,count,ExtBearFlag); //--- Funktionsausgang return; } //--- wenn der Schlusspreis am ersten Bar weniger als der Schlusspreis am letzten - es gibt Bullen Kerze if(open[start]<close[last]) { //--- wenn früher die Kerze Bären war, so freimachen wir die Werte den Bären Indikator Puffers if(ExtDirectionFlag!=1) ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,start,count); //--- Bullen Kerze ExtDirectionFlag=1; //--- bilden Sie die Kerze FormCandleMain(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,close[last], open[start],high[index_max],low[index_min],start,count,ExtBullFlag); //--- Funktionsausgang return; } //--- wenn sie in diesem Teil der Funktion, so bedeutet es, so stellt sich der Eröffnungspreis am ersten Bar gleich //--- dem Schlusspreis am letzten Bar; wir werden solche Kerze Bären halten //--- wenn früher die Kerze Bullen war, so freimachen wir die Werte der Bullen Indikator Puffers if(ExtDirectionFlag!=-1) ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count); //--- Bären Kerze ExtDirectionFlag=-1; //--- wenn Schlusspreise und Eröffnungspreise gleich sind, dann verschoben Sie für die korrekte Anzeige if(high[index_max]!=low[index_min]) FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start], open[start]-ExtEmptyBodySize,high[index_max],low[index_min],start,count,ExtBearFlag); else FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond, open[start],open[start]-ExtEmptyBodySize,high[index_max], high[index_max]-ExtEmptyBodySize,start,count,ExtBearFlag); } //+------------------------------------------------------------------+ //| Zeichnung das Ende der Kerze | //+------------------------------------------------------------------+ void FillCandleEnd(const double &open[],const double &close[], const double &high[],const double &low[], const int start,const int last,const int fill_index, const int index_max,const int index_min) { //--- wenn es nur eine Bar gibt, dann wir nicht zeichnen if(last-start==0) return; //--- wenn der Schlusspreis am ersten Bar mehr als der Schlusspreis am letzten Bar - es gibt Bullen Kerze if(open[start]>close[last]) { //--- bilden Sie das Ende der Kerze FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond, open[start],close[last],high[index_max],low[index_min],fill_index,ExtBearFlag); //--- Funktionsausgang return; } //--- wenn der Schlusspreis am ersten Bar weniger als der Schlusspreis am letzten - es gibt Bullen Kerze if(open[start]<close[last]) { //--- bilden Sie das Ende der Kerze FormCandleEnd(ExtBullBodyEndFirst,ExtBullBodyEndSecond,ExtBullShadowEndFirst,ExtBullShadowEndSecond, close[last],open[start],high[index_max],low[index_min],fill_index,ExtBullFlag); //--- Funktionsausgang return; } //--- wenn sie in diesem Teil der Funktion, so bedeutet es, so stellt sich der Eröffnungspreis am ersten Bar gleich //--- dem Schlusspreis am letzten Bar; wir werden solche Kerze Bären halten //--- bilden Sie das Ende der Kerze if(high[index_max]!=low[index_min]) FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start], open[start]-ExtEmptyBodySize,high[index_max],low[index_min],fill_index,ExtBearFlag); else FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start], open[start]-ExtEmptyBodySize,high[index_max],high[index_max]-ExtEmptyBodySize,fill_index,ExtBearFlag); } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Überprüfen Sie die Indikator Periode if(!CheckPeriod((int)Period(),(int)InpPeriod)) return(INIT_PARAMETERS_INCORRECT); //--- die Anzeige der Preisdaten auf dem Vordergrund ChartSetInteger(0,CHART_FOREGROUND,0,1); //--- Bindung von Indikator Puffers SetIndexBuffer(0,ExtBearBodyFirst); SetIndexBuffer(1,ExtBearBodySecond); SetIndexBuffer(2,ExtBearBodyEndFirst); SetIndexBuffer(3,ExtBearBodyEndSecond); SetIndexBuffer(4,ExtBearShadowFirst); SetIndexBuffer(5,ExtBearShadowSecond); SetIndexBuffer(6,ExtBearShadowEndFirst); SetIndexBuffer(7,ExtBearShadowEndSecond); SetIndexBuffer(8,ExtBullBodyFirst); SetIndexBuffer(9,ExtBullBodySecond); SetIndexBuffer(10,ExtBullBodyEndFirst); SetIndexBuffer(11,ExtBullBodyEndSecond); SetIndexBuffer(12,ExtBullShadowFirst); SetIndexBuffer(13,ExtBullShadowSecond); SetIndexBuffer(14,ExtBullShadowEndFirst); SetIndexBuffer(15,ExtBullShadowEndSecond); //--- stellen Sie einige Werte der Eigenschaften für die Konstruktion des Indikators ein for(int i=0;i<8;i++) { PlotIndexSetInteger(i,PLOT_DRAW_TYPE,DRAW_FILLING); // der Typ der graphischen Konstruktion PlotIndexSetInteger(i,PLOT_LINE_STYLE,STYLE_SOLID); // der Stil der Linie auf die Zeichnung PlotIndexSetInteger(i,PLOT_LINE_WIDTH,1); // die Dicke der Linie auf die Zeichnung } //--- 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[]) { //--- wenn es noch keine berechnete Bars gibt if(prev_calculated==0) { //--- bekommen Sie die Zeit wenn der Bar auf dem älteren Zeitrahmen erschienen war if(!GetTimeData()) return(0); } //--- stellen Sie die gerade Richtung der Indexierung ein ArraySetAsSeries(time,false); ArraySetAsSeries(high,false); ArraySetAsSeries(low,false); ArraySetAsSeries(open,false); ArraySetAsSeries(close,false); //--- Variable zur Berechnung den Anfang des Bars int start=prev_calculated; //--- wenn der Bar gebildet ist, so berechnen wir den Indikatorwert darauf if(start!=0 && start==rates_total) start--; //--- die Zyklus von die Berechnung der Indikatorwerte for(int i=start;i<rates_total;i++) { //--- füllen Sie die i-ten Elemente des Indikator Puffers mit dem leeren Werten aus FillIndicatorBuffers(i); //--- führen Sie die Berechnung für die Bars seit dem Datum InpDateStart durch if(time[i]>=InpDateStart) { //--- zum ersten Mal bestimmen Sie eine Position mit der wir werden die Werte anzeigen if(ExtStartFlag) { //--- speichern Sie der Index des Anfangsbar ExtStartPos=i; //--- bestimmen Sie das erste Datum auf dem älteren Zeitrahmen, das mehr als time[i] while(time[i]>=ExtTimeBuff[ExtCount]) if(ExtCount<ExtSize-1) ExtCount++; //--- ändern Sie die Flaggewert, um in diesen Block nicht mehr zu geraten ExtStartFlag=false; } //--- prüfen Sie, ob es noch Elemente in das Array sind if(ExtCount<ExtSize) { //--- warten Sie, wenn der Zeitwert auf dem aktuellen Zeitrahmen der Wert auf dem älteren Zeitrahmen erreichen wird if(time[i]>=ExtTimeBuff[ExtCount]) { //--- zeichnen Sie den Hauptteil der Kerze (ohne Zeichnung zwischen der letzten und vorletzten Bar) FillCandleMain(open,close,high,low,ExtStartPos,i-1,i-2,ExtIndexMax,ExtIndexMin); //--- zeichnen Sie das Ende der Kerze (das Gebiet zwischen der letzten und vorletzten Bar) FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin); //--- bewegen Sie die Anfangsposition für die Zeichnung der nächsten Kerze ExtStartPos=i; //--- erhöhen Sie der Array Zähler ExtCount++; } else continue; } else { //--- der Fehlerwert zu stürzen ResetLastError(); //--- bekommen Sie die letzte Datum auf dem älteren Zeitrahmen if(CopyTime(Symbol(),InpPeriod,0,1,ExtCurrentTime)==-1) { Print("Fehler beim Kopieren die Daten, Kode = ",GetLastError()); return(0); ;} //--- wenn das neue Datum mehr ist, so beenden wir die Bildung der Kerze if(ExtCurrentTime[0]>ExtLastTime) { //--- freimachen Sie das Gebiet zwischen der letzten und vorletzten Bar in den Hauptindikator Puffers ClearEndOfBodyMain(i-1); //--- zeichnen Sie dieses Gebiet mit dem Hilfs-Indikator Puffers FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin); //--- bewegen Sie die Anfangsposition für die Zeichnung der nächsten Kerze ExtStartPos=i; //--- stürzen Sie die Fahne der Preisrichtung ExtDirectionFlag=0; //--- speichern Sie das neue letzte Datum ExtLastTime=ExtCurrentTime[0]; } else { //--- bilden Sie die Kerze FillCandleMain(open,close,high,low,ExtStartPos,i,i,ExtIndexMax,ExtIndexMin); } } } } //--- den Wert prev_calculated für den nächsten Anruf zurückgeben return(rates_total); } //+------------------------------------------------------------------+ //| Überprüfen Sie die Indikator Periode auf die Korrektheit | //+------------------------------------------------------------------+ bool CheckPeriod(int current_period,int high_period) { //--- die Periode des Indikators soll mehr als der Zeitrahmen sein, auf dem er dargestellt wird if(current_period>=high_period) { Print("Fehler! Der Wert von der Indikator Periode soll mehr als der aktuellen Zeitrahmen sein!"); return(false); } //--- wenn die Periode des Indikators eine Woche oder einer Monat ist, so ist die Periode korrekt if(high_period>32768) return(true); //--- bringen Sie die Werte der Perioden bis zu Minuten if(high_period>30) high_period=(high_period-16384)*60; if(current_period>30) current_period=(current_period-16384)*60; //--- die Periode des Indikators soll Fach der Zeitrahmen sein, auf dem er dargestellt wird if(high_period%current_period!=0) { Print("Fehler! Der Wert der Periode des Indikators soll Fach der aktuellen Zeitrahmen sein!"); return(false); } //--- die Periode des Indikators soll der Wert der Zeitrahmen übertreten, auf dem er in 3 oder mehr Mal dargestellt wird if(high_period/current_period<3) { Print("Fehler! Der Wert der Periode des Indikators soll der Wert der aktuellen Zeitrahmen in 3 oder mehr Mal übertreten!"); return(false); } //--- die Periode des Indikators ist für den aktuellen Zeitrahmen korrekt return(true); } //+------------------------------------------------------------------+ //| Bekommen Sie die Daten der Zeit auf dem älteren Zeitrahmen | //+------------------------------------------------------------------+ bool GetTimeData(void) { //--- der Fehlerwert zu stürzen ResetLastError(); //--- kopieren Sie alle Daten auf die aktuelle Zeit if(CopyTime(Symbol(),InpPeriod,InpDateStart,TimeCurrent(),ExtTimeBuff)==-1) { //--- der Fehlerwert zu stürzen int code=GetLastError(); //--- drucken Sie der Fehlertext PrintFormat("Fehler beim Kopieren die Daten! %s",code==4401 ? "Die Geschichte wird noch beladen!" : "Kode = "+IntegerToString(code)); //--- geben Sie false für den nochmaligen Versuch der Beladung der Daten zurück return(false); } //--- bekommen Sie die Größe des Arrays ExtSize=ArraySize(ExtTimeBuff); //--- stellen Sie der Index des Zyklus für das Array gleich der Null ein ExtCount=0; //--- stellen Sie die Position der aktuellen Kerze in diesem Zeitrahmen gleich der Null ein ExtStartPos=0; ExtStartFlag=true; //--- bekommen Sie der letzten Wert der Zeit auf dem älteren Zeitrahmen ExtLastTime=ExtTimeBuff[ExtSize-1]; //--- die erfolgreiche Ausführung return(true); } //+------------------------------------------------------------------+ //| Die Funktion bildet den Hauptteil der Kerze. Je nach dem Wert | //| der Flagge, die Funktion bestimmt, welche Daten sich in welche | //| Arrays für die korrekte Abbildung einschreiben sollen. | //+------------------------------------------------------------------+ void FormCandleMain(double &body_fst[],double &body_snd[], double &shadow_fst[],double &shadow_snd[], const double fst_value,const double snd_value, const double fst_extremum,const double snd_extremum, const int start,const int count,const bool flag) { //--- prüfen Sie der Wert der Flagge if(flag) { //--- bilden Sie der Körper der Kerze FormMain(body_fst,body_snd,fst_value,snd_value,start,count); //--- bilden Sie der Schatten der Kerze FormMain(shadow_fst,shadow_snd,fst_extremum,snd_extremum,start,count); ;} else { //--- bilden Sie der Körper der Kerze FormMain(body_fst,body_snd,snd_value,fst_value,start,count); //--- bilden Sie der Schatten der Kerze FormMain(shadow_fst,shadow_snd,snd_extremum,fst_extremum,start,count); } } //+------------------------------------------------------------------+ //| Die Funktion bildet das Ende der Kerze. Je nach dem Wert der | //| Flagge, die Funktion bestimmt, welche Daten sich in welche Arrays| //| für die korrekte Abbildung einschreiben sollen. | //+------------------------------------------------------------------+ void FormCandleEnd(double &body_fst[],double &body_snd[], double &shadow_fst[],double &shadow_snd[], const double fst_value,const double snd_value, const double fst_extremum,const double snd_extremum, const int end,bool &flag) { //--- prüfen Sie der Wert der Flagge if(flag) { //--- bilden Sie das Ende der Körper der Kerze FormEnd(body_fst,body_snd,fst_value,snd_value,end); //--- bilden Sie das Ende der Schatten der Kerze FormEnd(shadow_fst,shadow_snd,fst_extremum,snd_extremum,end); //--- ändern Sie der Wert der Flagge gegen das Entgegengesetzte flag=false; } else { //--- bilden Sie das Ende der Körper der Kerze FormEnd(body_fst,body_snd,snd_value,fst_value,end); //--- bilden Sie das Ende der Schatten der Kerze FormEnd(shadow_fst,shadow_snd,snd_extremum,fst_extremum,end); //--- ändern Sie der Wert der Flagge gegen das Entgegengesetzte flag=true; } } //+------------------------------------------------------------------+ //| Die Entleerung das Ende der Kerze (das Gebiet zwischen der | //| letzten und vorletzten Bar) | //+------------------------------------------------------------------+ void ClearEndOfBodyMain(const int ind) { ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,ind,1); ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,ind,1); } //+------------------------------------------------------------------+ //| Die Entleerung der Kerze | //+------------------------------------------------------------------+ void ClearCandle(double &body_fst[],double &body_snd[],double &shadow_fst[], double &shadow_snd[],const int start,const int count) { //--- die Überprüfung if(count!=0) { //--- füllen Sie der Indikator Puffers mit dem leeren Wert aus ArrayFill(body_fst,start,count,INDICATOR_EMPTY_VALUE); ArrayFill(body_snd,start,count,INDICATOR_EMPTY_VALUE); ArrayFill(shadow_fst,start,count,INDICATOR_EMPTY_VALUE); ArrayFill(shadow_snd,start,count,INDICATOR_EMPTY_VALUE); } } //+------------------------------------------------------------------+ //| Die Bildung des Hauptteiles der Kerze | //+------------------------------------------------------------------+ void FormMain(double &fst[],double &snd[],const double fst_value, const double snd_value,const int start,const int count) { //--- die Überprüfung if(count!=0) { //--- füllen Sie die Indikator Puffers Werte aus ArrayFill(fst,start,count,fst_value); ArrayFill(snd,start,count,snd_value); } } //+------------------------------------------------------------------+ //| Die Bildung das Ende der Kerze | //+------------------------------------------------------------------+ void FormEnd(double &fst[],double &snd[],const double fst_value, const double snd_value,const int last) { //--- füllen Sie die Indikator Puffers Werte aus ArrayFill(fst,last-1,2,fst_value); ArrayFill(snd,last-1,2,snd_value); } //+------------------------------------------------------------------+ //| Füllen Sie die i-ten Elemente des Indikator Puffers mit dem | //| leeren Werte aus | //+------------------------------------------------------------------+ void FillIndicatorBuffers(const int i) { //--- stellen Sie der leer Wert in die Zelle der Indikator Puffers ein ExtBearBodyFirst[i]=INDICATOR_EMPTY_VALUE; ExtBearBodySecond[i]=INDICATOR_EMPTY_VALUE; ExtBearShadowFirst[i]=INDICATOR_EMPTY_VALUE; ExtBearShadowSecond[i]=INDICATOR_EMPTY_VALUE; ExtBearBodyEndFirst[i]=INDICATOR_EMPTY_VALUE; ExtBearBodyEndSecond[i]=INDICATOR_EMPTY_VALUE; ExtBearShadowEndFirst[i]=INDICATOR_EMPTY_VALUE; ExtBearShadowEndSecond[i]=INDICATOR_EMPTY_VALUE; ExtBullBodyFirst[i]=INDICATOR_EMPTY_VALUE; ExtBullBodySecond[i]=INDICATOR_EMPTY_VALUE; ExtBullShadowFirst[i]=INDICATOR_EMPTY_VALUE; ExtBullShadowSecond[i]=INDICATOR_EMPTY_VALUE; ExtBullBodyEndFirst[i]=INDICATOR_EMPTY_VALUE; ExtBullBodyEndSecond[i]=INDICATOR_EMPTY_VALUE; ExtBullShadowEndFirst[i]=INDICATOR_EMPTY_VALUE; ExtBullShadowEndSecond[i]=INDICATOR_EMPTY_VALUE; } |