नमस्ते दोस्तों! आज हम बात करेंगे एक शानदार इंडिकेटर "आइडियल ज़िगज़ैग" के बारे में। यह एक साधारण लेकिन बहुत तेज़ ज़िगज़ैग इंडिकेटर है।
इसमें न तो कोई लटकी हुई चोटियाँ हैं और न ही गलत चोटियाँ। चोटियों को पुनः प्राप्त करने की प्रक्रिया को समय के अनुसार अनुकूलित किया गया है।

फायदे:
- सबसे महंगा कार्य, जो गणनाओं में होता है, वह है iBarShift। इसे चोटियों की पुनः प्राप्ति के लिए आवश्यक सभी चक्रों के लिए पूरी तरह से प्रतिस्थापित कर दिया गया है। इसलिए, इसे ArrayBSearch द्वारा प्रतिस्थापित किया गया है। इसका मतलब है कि यह इंडिकेटर अपने MQL4 समकक्ष से अधिक कुशल होगा;
- प्रत्येक बार के लिए सभी आवश्यक डेटा सिर्फ किसी भी क्षण में ही नहीं, बल्कि इतिहास में किसी भी क्षण के लिए भी EA के लिए उपलब्ध है;
- कोई लटकी हुई चोटियाँ नहीं;
- इंडिकेटर मानों की खोज किए बिना चोटियों को खोजने का प्रभावी तरीका;
- बहुत तेज़;
- इतिहास में डेटा सम्मिलन और समय फ़्रेम बदलने पर सही कार्य करता है;
- EA में उपयोग के लिए बिल्कुल सही।
नुकसान:
- मेमोरी की आवश्यकता। ज़िगज़ैग को सही ढंग से चित्रित करने के लिए 2 बफर की आवश्यकता होती है (एक पर्याप्त नहीं है क्योंकि इसमें देरी होती है), जबकि यहाँ 5 बफर का उपयोग किया गया है। मेरी राय में, यह कमी पूरी तरह से लाभ #6 द्वारा धूमिल हो जाती है। तेजी से ज़िगज़ैग कोई भी सही ढंग से दो बफरों पर इतिहास सम्मिलन को संसाधित नहीं कर सकता।
- अतिरिक्त रेखाएँ उपलब्ध हैं। यह डेटा को Expert Advisor के लिए दृश्यमान बनाने के लिए आवश्यक है। ये रेखाएँ कभी भी दिखनी नहीं चाहिए।
प्रिंसिपल:
ज़िगज़ैग चैनलिंग सिद्धांत द्वारा चित्रित किया जाता है। चैनल की चौड़ाई बिंदुओं (IdealZZ) या प्रतिशत के रूप में (IdealZZP) परिभाषित की जा सकती है।
चोटियों की पुनः प्राप्ति:
input int ChannelWidth=100; #property indicator_chart_window datetime LastTime; int ZZHandle; //+------------------------------------------------------------------+ //| कस्टम इंडिकेटर प्रारंभिककरण फ़ंक्शन | //+------------------------------------------------------------------+ void OnInit() { LastTime = 0; ZZHandle = iCustom(_Symbol, Period(), "IdealZZ", ChannelWidth); } //+------------------------------------------------------------------+ //| GetValue | //+------------------------------------------------------------------+ bool GetValue(double dir,int bar,int prevBar,double &peak, int &peakBar,datetime &peakTime,const datetime &T[]) { if(dir<0) { double t[1]; if(0>=CopyBuffer(ZZHandle,2,bar,1,t)) return false; int i= ArrayBsearch(T, (datetime)t[0]); if(i==prevBar) { if(0>=CopyBuffer(ZZHandle,2,bar+1,1,t)) return false; i=ArrayBsearch(T,(datetime)t[0]); } double v[1]; if(0>=CopyBuffer(ZZHandle,1,i,1,v)) return false; if(v[0]==EMPTY_VALUE) { if(0>=CopyBuffer(ZZHandle,2,bar+1,1,t)) return false; i=ArrayBsearch(T,(datetime)t[0]); if(0>=CopyBuffer(ZZHandle,1,i,1,v)) return false; } peak=v[0]; peakBar=i; peakTime=(datetime)t[0]; } else if(dir>0) { double t[1]; if(0>=CopyBuffer(ZZHandle,3,bar,1,t)) return false; int i= ArrayBsearch(T, (datetime)t[0]); if(i==prevBar) { if(0>=CopyBuffer(ZZHandle,3,bar+1,1,t)) return false; i=ArrayBsearch(T,(datetime)t[0]); } double v[1]; if(0>=CopyBuffer(ZZHandle,0,i,1,v)) return false; if(v[0]==EMPTY_VALUE) { if(0>=CopyBuffer(ZZHandle,3,bar+1,1,t)) return false; i=ArrayBsearch(T,(datetime)t[0]); if(0>=CopyBuffer(ZZHandle,0,i,1,v)) return false; } peak=v[0]; peakBar=i; peakTime=(datetime)t[0]; } else { return(false); } return(true); } //+------------------------------------------------------------------+ //| GetValue | //+------------------------------------------------------------------+ void SetPt(string name,double price,datetime time) { ObjectCreate(0,name,OBJ_ARROW,0,time,price); ObjectSetInteger(0,name,OBJPROP_ARROWCODE,108); ObjectSetDouble(0,name,OBJPROP_PRICE,price); ObjectSetInteger(0,name,OBJPROP_TIME,time); } //+------------------------------------------------------------------+ //| कस्टम इंडिकेटर इटरेशन फ़ंक्शन | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &T[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if(LastTime==T[0]) return(rates_total); LastTime=T[0]; ArraySetAsSeries(T,true); double dir_[1]; if(0>=CopyBuffer(ZZHandle,4,1,1,dir_)) return rates_total; double dir=dir_[0]; double rdir=-dir; if(dir==EMPTY_VALUE) return(rates_total); double v1,v2,v3,v4,v5; int i1,i2,i3,i4,i5; datetime t1,t2,t3,t4,t5; if( GetValue(dir,1,0,v1,i1,t1,T) && GetValue(rdir,i1,0,v2,i2,t2,T) && GetValue(dir,i2,i1,v3,i3,t3,T) && GetValue(rdir,i3,i2,v4,i4,t4,T) && GetValue(dir,i4,i3,v5,i5,t5,T) ) { SetPt("1",v1,t1); SetPt("2",v2,t2); SetPt("3",v3,t3); SetPt("4",v4,t4); SetPt("5",v5,t5); Print(v1," ",v2," ",v3," ",v4," ",v5," ",i1," ",i2," ",i3," ",i4," ",i5); } else { Print("ऐसा लगता है कि कोई त्रुटि है..."); } return(rates_total); } //+------------------------------------------------------------------+
यह उदाहरण एक ऐसा इंडिकेटर है जो (बार में एक बार) पहले पांच चोटियों को चिह्नित करता है (जिसमें वर्तमान में बन रही है)।
ध्यान दें! कोड तब गलत काम कर सकता है, यदि शून्य बार मोड सक्षम है।
शून्य बार मोड:
यह मोड DrawZeroBar वेरिएबल कोड में सक्षम किया जा सकता है। यह डिफ़ॉल्ट रूप से बंद है। इसे सक्षम करना विशेष रूप से अनुशंसित नहीं है, खासकर यदि इंडिकेटर का उपयोग Expert Advisor में किया जा रहा है।
इसे उपयोग में लाने का आनंद लें। कृपया मुझे किसी भी खामी के बारे में सूचित करें।