#property copyright "SD_SR_But CU" #property description "THIS IS A FREE INDICATOR" #property indicator_chart_window #property indicator_buffers 4 #property indicator_color1 clrNONE #property indicator_color2 clrNONE #property indicator_color3 clrNONE #property indicator_color4 clrNONE #property indicator_width1 5 #property indicator_width2 5 #property indicator_width3 3 #property indicator_width4 3 extern int BackLimit = 5000; extern int TimeFrame = 0; extern string TimeString = "0=Current, 60=H1, 240=H4, 1440=Day, 10080=Week, 43200=Month"; extern color color_support_weak = clrAqua; extern color color_support_untested = clrNavy; extern color color_support_verified = clrBlue; extern color color_support_proven = clrBlue; extern color color_support_turncoat = clrDeepSkyBlue; extern color color_resist_weak = clrPink; extern color color_resist_untested = clrMaroon; extern color color_resist_verified = clrIndianRed; extern color color_resist_proven = clrIndianRed; extern color color_resist_turncoat = clrTomato; extern bool zone_show_weak = true; extern double zone_fuzzfactor = 0.75; extern bool zone_solid = true; extern int zone_linewidth = 1; extern int zone_style = 0; extern bool zone_show_info = true; extern int zone_info_fontsize = 10; extern color zone_info_color_support = clrDeepSkyBlue; extern color zone_info_color_resistance = clrMagenta; extern string zone_info_ftype = "Century Gothic"; extern int zone_label_shift = -5; extern bool zone_show_alerts = true; extern bool zone_alert_popups = true; extern bool zone_alert_sounds = false; extern int zone_alert_waitseconds = 120; extern bool zone_merge = true; extern bool zone_extend = true; extern bool fractals_show = false; extern int FractalUpArrowCode1 = 236; extern int FractalDownArrowCode1 = 238; extern int FractalUpArrowCode2 = 228; extern int FractalDownArrowCode2 = 230; extern double fractal_fast_factor = 2.0; extern double fractal_slow_factor = 5.0; extern bool SetGlobals = true; //template code start1 extern string button_note1 = "CU"; extern int btn_Subwindow = 1;//***** extern ENUM_BASE_CORNER btn_corner = CORNER_RIGHT_UPPER; // chart btn_corner for anchoring extern string btn_text = "SD CU"; extern string btn_Font = "Impact"; extern int btn_FontSize = 9; //btn__font size extern color btn_text_ON_color = clrWhite; extern color btn_text_OFF_color = C'120,120,120'; extern color btn_background_color = clrDarkRed; extern color btn_border_color = clrBlack; extern int button_x = 700; //btn__x extern int button_y = 0; //btn__y extern int btn_Width = 80; //btn__width extern int btn_Height = 20; //btn__height extern string UniqueButtonID = "SupplyDemandCU"; extern string button_note2 = "bn2CU"; bool show_data = true; string IndicatorName, IndicatorObjPrefix; //template code end1 double FastDnPts[], FastUpPts[], SlowDnPts[], SlowUpPts[]; double zone_hi[1000], zone_lo[1000]; int zone_start[1000], zone_hits[1000], zone_type[1000], zone_strength[1000], zone_count = 0; bool zone_turn[1000]; #define ZONE_SUPPORT 1 #define ZONE_RESIST 2 #define ZONE_WEAK 0 #define ZONE_TURNCOAT 1 #define ZONE_UNTESTED 2 #define ZONE_VERIFIED 3 #define ZONE_PROVEN 4 #define UP_POINT 1 #define DN_POINT -1 int time_offset = 0; //+------------------------------------------------------------------------------------------------------------------+ string GenerateIndicatorName(const string target) //don't change anything here { string name = target; int try = 2; while (WindowFind(name) != -1) { name = target + " #" + IntegerToString(try++); } return name; } //+------------------------------------------------------------------------------------------------------------------+ string buttonId; int OnInit() { IndicatorName = GenerateIndicatorName(btn_text); IndicatorObjPrefix = "__" + IndicatorName + "SupplyDemandCU"; IndicatorShortName(IndicatorName); IndicatorDigits(Digits); double val; if (GlobalVariableGet(IndicatorName + "_visibility", val)) show_data = val != 0; ChartSetInteger(ChartID(), CHART_EVENT_MOUSE_MOVE, 1); buttonId = IndicatorObjPrefix + UniqueButtonID; createButton(buttonId, btn_text, btn_Width, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color); ObjectSetInteger(ChartID(), buttonId, OBJPROP_YDISTANCE, button_y); ObjectSetInteger(ChartID(), buttonId, OBJPROP_XDISTANCE, button_x); // put init() here init2(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------------------------------------------------------+ //don't change anything here void createButton(string buttonID,string buttonText,int width,int height,string font,int fontSize,color bgColor,color borderColor,color txtColor) { ObjectDelete (ChartID(),buttonID); ObjectCreate (ChartID(),buttonID,OBJ_BUTTON,btn_Subwindow,0,0);//*** ObjectCreate (ChartID(),buttonID,OBJ_BUTTON,0,0,0); ObjectSetInteger(ChartID(),buttonID,OBJPROP_COLOR,txtColor); ObjectSetInteger(ChartID(),buttonID,OBJPROP_BGCOLOR,bgColor); ObjectSetInteger(ChartID(),buttonID,OBJPROP_BORDER_COLOR,borderColor); ObjectSetInteger(ChartID(),buttonID,OBJPROP_XSIZE,width); ObjectSetInteger(ChartID(),buttonID,OBJPROP_YSIZE,height); ObjectSetString (ChartID(),buttonID,OBJPROP_FONT,font); ObjectSetString (ChartID(),buttonID,OBJPROP_TEXT,buttonText); ObjectSetInteger(ChartID(),buttonID,OBJPROP_FONTSIZE,fontSize); ObjectSetInteger(ChartID(),buttonID,OBJPROP_SELECTABLE,0); ObjectSetInteger(ChartID(),buttonID,OBJPROP_CORNER,btn_corner); ObjectSetInteger(ChartID(),buttonID,OBJPROP_HIDDEN,1); ObjectSetInteger(ChartID(),buttonID,OBJPROP_XDISTANCE,9999); ObjectSetInteger(ChartID(),buttonID,OBJPROP_YDISTANCE,9999); } //+------------------------------------------------------------------------------------------------------------------+ int deinit() { ObjectsDeleteAll(ChartID(), IndicatorObjPrefix); //put deinit() here deinit2(); return(0); } //+------------------------------------------------------------------------------------------------------------------+ //don't change anything here bool recalc = true; void handleButtonClicks() { if (ObjectGetInteger(ChartID(), buttonId, OBJPROP_STATE)) { ObjectSetInteger(ChartID(), buttonId, OBJPROP_STATE, false); show_data = !show_data; GlobalVariableSet(IndicatorName + "_visibility", show_data ? 1.0 : 0.0); recalc = true; start(); } } //+------------------------------------------------------------------------------------------------------------------+ void OnChartEvent(const int id, //don't change anything here const long &lparam, const double &dparam, const string &sparam) { handleButtonClicks(); } //+------------------------------------------------------------------------------------------------------------------+ int start() { handleButtonClicks(); recalc = false; //put start () here start2(); if (show_data) { ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_ON_color); for (int banzai=0; banzai 0 && zone_strength[i] > ZONE_UNTESTED) { if (zone_hits[i] == 1) lbl = lbl + ",Test:" + zone_hits[i]; else lbl = lbl + ",Test:" + zone_hits[i]; } int adjust_hpos; int wbpc = WindowBarsPerChart(); int k; k = Period() * 60 + (20 + StringLen(lbl)); if (wbpc < 80) adjust_hpos = Time[0] + k * 4; else if (wbpc < 125) adjust_hpos = Time[0] + k * 8; else if (wbpc < 250) adjust_hpos = Time[0] + k * 15; else if (wbpc < 480) adjust_hpos = Time[0] + k * 29; else if (wbpc < 950) adjust_hpos = Time[0] + k * 58; else adjust_hpos = Time[0] + k * 115; // int shift = k * zone_label_shift; double vpos = zone_hi[i] - (zone_hi[i] - zone_lo[i]) / 2; string s = "SSSR#"+i+"LBL"; ObjectCreate(s, OBJ_TEXT, 0, 0, 0); ObjectSet(s, OBJPROP_TIME1, adjust_hpos + shift); ObjectSet(s, OBJPROP_PRICE1, vpos); ObjectSetText(s, StringRightPad(lbl, 36, " "),zone_info_fontsize,zone_info_ftype,use_color); } } CheckAlerts(); return(0); } //+------------------------------------------------------------------------------------------------------------------+ void CheckAlerts() { static int lastalert = 0; if (zone_show_alerts == false) return; if (Time[0] - lastalert > zone_alert_waitseconds) if (CheckEntryAlerts() == true) lastalert = Time[0]; } bool CheckEntryAlerts() { for (int i=0; i= zone_lo[i] && Close[0] < zone_hi[i]) { if (zone_show_alerts == true) { if (zone_alert_popups == true) //----------------------- { if (zone_type[i] == ZONE_SUPPORT) Alert("S&D @ " + Symbol()+ "," + TimeFrameToString(TimeFrame) + "Demand Zone Entered");//Alert(Symbol() + TimeFrameToString(TimeFrame) + ": Support Zone Entered"); else Alert("S&D @ " + Symbol()+ "," + TimeFrameToString(TimeFrame) + "Supply Zone Entered");//Alert(Symbol() + TimeFrameToString(TimeFrame) + ": Resistance Zone Entered"); } if (zone_alert_sounds == true) PlaySound("alert.wav"); } return(true); } } //----- return(false); } void DeleteGlobalVars() { if (SetGlobals == false) return; GlobalVariableDel("SSSR_Count_"+Symbol()+TimeFrame); GlobalVariableDel("SSSR_Updated_"+Symbol()+TimeFrame); int old_count = zone_count; zone_count = 0; DeleteOldGlobalVars(old_count); } void DeleteOldGlobalVars(int old_count) { if (SetGlobals == false) return; for (int i=zone_count; i5; shift--) { double atr = iATR(NULL, TimeFrame, 7, shift); double fu = atr/2 * zone_fuzzfactor; bool isWeak; bool touchOk = false; bool isBust = false; double close = iClose(NULL, TimeFrame, shift); double high = iHigh(NULL, TimeFrame, shift); double low = iLow(NULL, TimeFrame, shift); double hi_i; double lo_i; if (FastUpPts[shift] > 0.001) { // a zigzag high point isWeak = true; if (SlowUpPts[shift] > 0.001) isWeak = false; hival = high; if (zone_extend == true) hival += fu; loval = MathMax(MathMin(close, high-fu), high-fu*2); turned = false; hasturned = false; isBust = false; bustcount = 0; testcount = 0; for (i=shift-1; i>=0; i--) { hi_i = iHigh(NULL, TimeFrame, i); lo_i = iLow(NULL, TimeFrame, i); if ((turned == false && FastUpPts[i] >= loval && FastUpPts[i] <= hival) || (turned == true && FastDnPts[i] <= hival && FastDnPts[i] >= loval)) { // Potential touch, just make sure its been 10+candles since the prev one touchOk = true; for (j=i+1; j= loval && FastUpPts[j] <= hival) || (turned == true && FastDnPts[j] <= hival && FastDnPts[j] >= loval)) { touchOk = false; break; } } if (touchOk == true) { // we have a touch. If its been busted once, remove bustcount // as we know this level is still valid & has just switched sides bustcount = 0; testcount++; } } if ((turned == false && hi_i > hival) || (turned == true && lo_i < loval)) { // this level has been busted at least once bustcount++; if (bustcount > 1 || isWeak == true) { // busted twice or more isBust = true; break; } if (turned == true) turned = false; else if (turned == false) turned = true; hasturned = true; // forget previous hits testcount = 0; } } if (isBust == false) { // level is still valid, add to our list temp_hi[temp_count] = hival; temp_lo[temp_count] = loval; temp_turn[temp_count] = hasturned; temp_hits[temp_count] = testcount; temp_start[temp_count] = shift; temp_merge[temp_count] = false; if (testcount > 3) temp_strength[temp_count] = ZONE_PROVEN; else if (testcount > 0) temp_strength[temp_count] = ZONE_VERIFIED; else if (hasturned == true) temp_strength[temp_count] = ZONE_TURNCOAT; else if (isWeak == false) temp_strength[temp_count] = ZONE_UNTESTED; else temp_strength[temp_count] = ZONE_WEAK; temp_count++; } } else if (FastDnPts[shift] > 0.001) { // a zigzag low point isWeak = true; if (SlowDnPts[shift] > 0.001) isWeak = false; loval = low; if (zone_extend == true) loval -= fu; hival = MathMin(MathMax(close, low+fu), low+fu*2); turned = false; hasturned = false; bustcount = 0; testcount = 0; isBust = false; for (i=shift-1; i>=0; i--) { hi_i = iHigh(NULL, TimeFrame, i); lo_i = iLow(NULL, TimeFrame, i); if ((turned == true && FastUpPts[i] >= loval && FastUpPts[i] <= hival) || (turned == false && FastDnPts[i] <= hival && FastDnPts[i] >= loval)) { // Potential touch, just make sure its been 10+candles since the prev one touchOk = true; for (j=i+1; j= loval && FastUpPts[j] <= hival) || (turned == false && FastDnPts[j] <= hival && FastDnPts[j] >= loval)) { touchOk = false; break; } } if (touchOk == true) { // we have a touch. If its been busted once, remove bustcount // as we know this level is still valid & has just switched sides bustcount = 0; testcount++; } } if ((turned == true && hi_i > hival) || (turned == false && lo_i < loval)) { // this level has been busted at least once bustcount++; if (bustcount > 1 || isWeak == true) { // busted twice or more isBust = true; break; } if (turned == true) turned = false; else if (turned == false) turned = true; hasturned = true; // forget previous hits testcount = 0; } } if (isBust == false) { // level is still valid, add to our list temp_hi[temp_count] = hival; temp_lo[temp_count] = loval; temp_turn[temp_count] = hasturned; temp_hits[temp_count] = testcount; temp_start[temp_count] = shift; temp_merge[temp_count] = false; if (testcount > 3) temp_strength[temp_count] = ZONE_PROVEN; else if (testcount > 0) temp_strength[temp_count] = ZONE_VERIFIED; else if (hasturned == true) temp_strength[temp_count] = ZONE_TURNCOAT; else if (isWeak == false) temp_strength[temp_count] = ZONE_UNTESTED; else temp_strength[temp_count] = ZONE_WEAK; temp_count++; } } } // look for overlapping zones... if (zone_merge == true) { merge_count = 1; int iterations = 0; while (merge_count > 0 && iterations < 3) { merge_count = 0; iterations++; for (i = 0; i < temp_count; i++) temp_merge[i] = false; for (i = 0; i < temp_count-1; i++) { if (temp_hits[i] == -1 || temp_merge[j] == true) continue; for (j = i+1; j < temp_count; j++) { if (temp_hits[j] == -1 || temp_merge[j] == true) continue; if ((temp_hi[i] >= temp_lo[j] && temp_hi[i] <= temp_hi[j]) || (temp_lo[i] <= temp_hi[j] && temp_lo[i] >= temp_lo[j]) || (temp_hi[j] >= temp_lo[i] && temp_hi[j] <= temp_hi[i]) || (temp_lo[j] <= temp_hi[i] && temp_lo[j] >= temp_lo[i])) { merge1[merge_count] = i; merge2[merge_count] = j; temp_merge[i] = true; temp_merge[j] = true; merge_count++; } } } // ... and merge them ... for (i=0; i 3) temp_strength[target] = ZONE_PROVEN; if (temp_hits[target] == 0 && temp_turn[target] == false) { temp_hits[target] = 1; if (temp_strength[target] < ZONE_VERIFIED) temp_strength[target] = ZONE_VERIFIED; } if (temp_turn[target] == false || temp_turn[source] == false) temp_turn[target] = false; if (temp_turn[target] == true) temp_hits[target] = 0; temp_hits[source] = -1; } } } // copy the remaining list into our official zones arrays zone_count = 0; for (i=0; i= 0 && zone_count < 1000) { zone_hi[zone_count] = temp_hi[i]; zone_lo[zone_count] = temp_lo[i]; zone_hits[zone_count] = temp_hits[i]; zone_turn[zone_count] = temp_turn[i]; zone_start[zone_count] = temp_start[i]; zone_strength[zone_count] = temp_strength[i]; if (zone_hi[zone_count] < Close[4]) zone_type[zone_count] = ZONE_SUPPORT; else if (zone_lo[zone_count] > Close[4]) zone_type[zone_count] = ZONE_RESIST; else { for (j=5; j<1000; j++) { if (iClose(NULL, TimeFrame, j) < zone_lo[zone_count]) { zone_type[zone_count] = ZONE_RESIST; break; } else if (iClose(NULL, TimeFrame, j) > zone_hi[zone_count]) { zone_type[zone_count] = ZONE_SUPPORT; break; } } if (j == 1000) zone_type[zone_count] = ZONE_SUPPORT; } zone_count++; } } } void DrawZones() { if (SetGlobals == true) { GlobalVariableSet("SSSR_Count_"+Symbol()+TimeFrame, zone_count); GlobalVariableSet("SSSR_Updated_"+Symbol()+TimeFrame, TimeCurrent()); } for (int i=0; i P) P = TimeFrame; P = P / TimeFrame*2 + MathCeil(P / TimeFrame / 2); if (shift < P) return(false); if (shift > iBars(Symbol(), TimeFrame)-P) return(false); for (int i=1; i<=P; i++) { if (M == UP_POINT) { if (iHigh(NULL, TimeFrame, shift+i) > iHigh(NULL, TimeFrame, shift)) return(false); if (iHigh(NULL, TimeFrame, shift-i) >= iHigh(NULL, TimeFrame, shift)) return(false); } if (M == DN_POINT) { if (iLow(NULL, TimeFrame, shift+i) < iLow(NULL, TimeFrame, shift)) return(false); if (iLow(NULL, TimeFrame, shift-i) <= iLow(NULL, TimeFrame, shift)) return(false); } } return(true); } void FastFractals() { int shift; int limit = MathMin(Bars-1, BackLimit); int P = TimeFrame * fractal_fast_factor; FastUpPts[0] = 0.0; FastUpPts[1] = 0.0; FastDnPts[0] = 0.0; FastDnPts[1] = 0.0; for (shift=limit; shift>1; shift--) { if (Fractal(UP_POINT, P, shift) == true) FastUpPts[shift] = iHigh(NULL, TimeFrame, shift); else FastUpPts[shift] = 0.0; if (Fractal(DN_POINT, P, shift) == true) FastDnPts[shift] = iLow(NULL, TimeFrame, shift); else FastDnPts[shift] = 0.0; } } void SlowFractals() { int shift; int limit = MathMin(iBars(Symbol(), TimeFrame) - 1, BackLimit); int P = TimeFrame * fractal_slow_factor; SlowUpPts[0] = 0.0; SlowUpPts[1] = 0.0; SlowDnPts[0] = 0.0; SlowDnPts[1] = 0.0; for (shift=limit; shift>1; shift--) { if (Fractal(UP_POINT, P, shift) == true) SlowUpPts[shift] = iHigh(NULL, TimeFrame, shift); else SlowUpPts[shift] = 0.0; if (Fractal(DN_POINT, P, shift) == true) SlowDnPts[shift] = iLow(NULL, TimeFrame, shift); else SlowDnPts[shift] = 0.0; } } bool NewBar() { static datetime LastTime = 0; if (iTime(NULL, TimeFrame, 0) != LastTime) { LastTime = iTime(NULL, TimeFrame, 0)+time_offset; return (true); } else return (false); } void DeleteZones() { int len = 5; int i; while (i < ObjectsTotal()) { string objName = ObjectName(i); if (StringSubstr(objName, 0, len) != "SSSR#") { i++; continue; } ObjectDelete(objName); } } string TimeFrameToString(int tf) //code by TRO { string tfs; switch(tf) { case PERIOD_M1: tfs = "M1" ; break; case PERIOD_M5: tfs = "M5" ; break; case PERIOD_M15: tfs = "M15" ; break; case PERIOD_M30: tfs = "M30" ; break; case PERIOD_H1: tfs = "H1" ; break; case PERIOD_H4: tfs = "H4" ; break; case PERIOD_D1: tfs = "D1" ; break; case PERIOD_W1: tfs = "W1" ; break; case PERIOD_MN1: tfs = "MN"; } return(tfs); } string StringRepeat(string str, int n = 1) { string outstr = ""; for(int i = 0; i < n; i++) outstr = outstr + str; return(outstr); } string StringRightPad(string str, int n=1, string str2=" ") { return(str + StringRepeat(str2,n-StringLen(str))); }