#property copyright "Paradox" #property link "http://www.forexfactory.com" #property indicator_chart_window extern string BoxLengths = "30,30,50,50,100,100,150,150"; extern string BoxHeights = "15,15,35,35,50,50,40,40"; extern string Shifts = "0,0,0,0,0,0,30,30"; string ValidPrices[] = {"High","Low","MedianClose","MedianHigh","MedianLow","MeanClose","MidHighLow","MidClose"}; extern string Prices = "High,Low,High,Low,High,Low,MedianClose,MidHighLow"; string ValidBoxPositions[] = {"Top","Bottom","Center"}; extern string BoxPositions = "Top,Bottom,Top,Bottom,Top,Bottom,Center,Center"; extern string Colors = "DarkOliveGreen,DarkOliveGreen,DarkGoldenrod,DarkGoldenrod,Chocolate,Chocolate,LightGray,None"; //extern string LockColors = "Lime,Lime,Lime,Lime,LightGray,LightGray,LightGray"; extern string Families = "1,1,2,2,3,3,4,5"; double BoxLengthVals[]; double BoxHeightVals[]; double ShiftVals[]; string PriceVals[]; string BoxPositionVals[]; color ColorVals[]; //color LockColorVals[]; string FamilyVals[]; int LockVals[]; int BoxCount; double Tick = 0; string PREFIX = "CrazyEddyBox"; int ObjectId = 0; bool ValidationPassed = true; //+------------------------------------------------------------------+ // expert initialization function | //+------------------------------------------------------------------+ int init() { deinitGraph(); Tick = MarketInfo(Symbol(), MODE_TICKSIZE); if (Digits % 2 == 1) {Tick *= 10;} StringSplitToDoubles(BoxLengths, ",", BoxLengthVals); BoxCount = ArraySize(BoxLengthVals); StringSplitToDoubles(BoxHeights, ",", BoxHeightVals); StringSplitToDoubles(Shifts, ",", ShiftVals); StringSplit(Prices, ",", PriceVals); //StringSplit(PriceAverages, ",", PriceAverageVals); StringSplit(BoxPositions, ",", BoxPositionVals); StringSplit(Families, ",", FamilyVals); string colorValsTemp[]; StringSplit(Colors, ",", colorValsTemp); //string lockColorValsTemp[]; //StringSplit(LockColors, ",", lockColorValsTemp); ArrayResize(ColorVals, ArraySize(colorValsTemp)); ArrayResize(LockVals, BoxCount); for(int i = 0;i < BoxCount; i++) { LockVals[i] = -1; ColorVals[i] = StringToColor(colorValsTemp[i]); //LockColorVals[i] = StringToColor(lockColorValsTemp[i]); //Print (" PriceVals[i] ", PriceVals[i], " BoxHeightVals[i] ", BoxHeightVals[i], " colorValsTemp[i] ", colorValsTemp[i], " ColorVals[i] ", ColorVals[i]); PriceVals[i] = StringUpperCase(PriceVals[i]); //PriceAverageVals[i] = StringUpperCase(PriceAverageVals[i]); BoxPositionVals[i] = StringUpperCase(BoxPositionVals[i]); } ValidationPassed = Validate(); //Print (" BoxLengthVals ", BoxLengthVals[0]); return(0); } int deinit() { deinitGraph(); Print("shutdown error - ",GetLastError()); return(0); } void start() { if(!ValidationPassed) return; RefreshRates(); //General Info CheckUnlocking(); MoveBoxes(); CheckLocking(); } bool CheckUnlocking() { for(int i = 0;i < ArraySize(BoxLengthVals); i++) { for(int j = i+1;j < ArraySize(BoxLengthVals); j++) { if(FamilyVals[i] == FamilyVals[j]) { string namei = PREFIX + DoubleToStr(i,0); string namej = PREFIX + DoubleToStr(j,0); double top = MathMax(ObjectGet(namei,OBJPROP_PRICE1), ObjectGet(namej,OBJPROP_PRICE1)); double bottom = MathMin(ObjectGet(namei,OBJPROP_PRICE2), ObjectGet(namej,OBJPROP_PRICE2)); if (iClose(Symbol(),Period(),0) > top || iClose(Symbol(),Period(),0) < bottom) { ObjectSet(namei,OBJPROP_BACK,false); ObjectSet(namej,OBJPROP_BACK,false); LockVals[i] = -1; LockVals[j] = -1; } } } } } bool CheckLocking() { for(int i = 0;i < ArraySize(BoxLengthVals); i++) { for(int j = i+1;j < ArraySize(BoxLengthVals); j++) { if(FamilyVals[i] == FamilyVals[j]) { string namei = PREFIX + DoubleToStr(i,0); double top1 = ObjectGet(namei,OBJPROP_PRICE1); double bottom1 = ObjectGet(namei,OBJPROP_PRICE2); string namej = PREFIX + DoubleToStr(j,0); double top2 = ObjectGet(namej,OBJPROP_PRICE1); double bottom2 = ObjectGet(namej,OBJPROP_PRICE2); if ((top1 > bottom2 && top2 > bottom1) || (top2 > bottom1 && top1 > bottom2)) { double diff = 0; if ((top1 - bottom2) < (top2 - bottom1)) diff = (bottom2 - top1) / 2; else diff = (top2 - bottom1) / 2; ObjectSet(namei,OBJPROP_BACK,true); ObjectSet(namej,OBJPROP_BACK,true); ObjectMove(namei, 0, ObjectGet(namei,OBJPROP_TIME1), ObjectGet(namei,OBJPROP_PRICE1) + diff); ObjectMove(namei, 1, ObjectGet(namei,OBJPROP_TIME2), ObjectGet(namei,OBJPROP_PRICE2) + diff); ObjectMove(namej, 0, ObjectGet(namej,OBJPROP_TIME1), ObjectGet(namej,OBJPROP_PRICE1) - diff); ObjectMove(namej, 1, ObjectGet(namej,OBJPROP_TIME2), ObjectGet(namej,OBJPROP_PRICE2) - diff); //ObjectMove(name, 1, endTime, endPrice); LockVals[i] = j; LockVals[j] = i; Print (" i ", i, " j ", j, " top1 ", top1, " bottom1 ", bottom1," top2 ", top2, " bottom2 ", bottom2, " diff ", diff); } } } } } void MoveBoxes() { for(int i = 0;i < BoxCount; i++) { if (LockVals[i] >= 0) continue; string name = PREFIX + DoubleToStr(i,0); //Print (" name ", name, " PriceVals[i] ", PriceVals[i], " BoxHeightVals[i] ", BoxHeightVals[i]); int boxLength = BoxLengthVals[i]; int shift = ShiftVals[i]; double boxHeight = BoxHeightVals[i]; double val,top,bottom; if (PriceVals[i] == "HIGH"){val = High[iHighest(NULL, 0, MODE_HIGH, boxLength, shift)];} else if (PriceVals[i] == "LOW"){val = Low[iLowest(NULL, 0, MODE_LOW, boxLength, shift)];} else if (PriceVals[i] == "MEDIANCLOSE"){val = GetMedian(PRICE_CLOSE, boxLength, shift);} else if (PriceVals[i] == "MEDIANHIGH"){val = GetMedian(PRICE_CLOSE, boxLength, shift);} else if (PriceVals[i] == "MEDIANLOW"){val = GetMedian(PRICE_CLOSE, boxLength, shift);} else if (PriceVals[i] == "MIDHIGHLOW"){val = GetMidline(PRICE_MEDIAN, boxLength, shift);} else if (PriceVals[i] == "MEANCLOSE"){val = GetMean(PRICE_CLOSE, boxLength, shift);} if (BoxPositionVals[i] == "TOP") { top = val; bottom = val - (boxHeight * Tick); } else if (BoxPositionVals[i] == "BOTTOM") { bottom = val; top = val + (boxHeight * Tick); } else if (BoxPositionVals[i] == "CENTER") { top = val + ((boxHeight * Tick) / 2); bottom = val - ((boxHeight * Tick) / 2); } SetBox (name, Time[boxLength+shift], top, Time[shift], bottom, ColorVals[i]); } } //Data Retrieval double GetMidline( int price, int length, int shift) { double high, low; if (price == PRICE_MEDIAN) { high = High[iHighest(NULL, 0, MODE_HIGH, length, shift)]; low = Low[iLowest(NULL, 0, MODE_LOW, length, shift)]; } else if (price == PRICE_CLOSE) { high = Close[iHighest(NULL, 0, MODE_CLOSE, length, shift)]; low = Close[iLowest(NULL, 0, MODE_CLOSE, length, shift)]; } else if (price == PRICE_LOW) { high = Low[iHighest(NULL, 0, MODE_LOW, length, shift)]; low = Low[iLowest(NULL, 0, MODE_LOW, length, shift)]; } else if (price == PRICE_HIGH) { high = High[iHighest(NULL, 0, MODE_HIGH, length, shift)]; low = High[iLowest(NULL, 0, MODE_HIGH, length, shift)]; } return ((high + low) / 2); } double GetMedian( int price, int length, int shift) { double temp[]; ArrayResize(temp,length); for(int i = shift; i < shift+length;i++) { if (price == PRICE_CLOSE) {temp[i-shift] = iClose(Symbol(),Period(),i);} else if (price == PRICE_HIGH) {temp[i-shift] = iHigh(Symbol(),Period(),i);} else if (price == PRICE_LOW) {temp[i-shift] = iLow(Symbol(),Period(),i);} } for(i = 0; i < length;i++) { // Print (" i ", i, " temp[i] ", temp[i]); } int mid = length / 2; //Print ("Length = ", length, " Mid ", mid, " temp[0] ", temp[0], " temp[3] ", temp[3]); ArraySort(temp); //Print ("Length = ", length, " Mid ", mid, " temp[0] ", temp[0], " temp[3] ", temp[3]); double priceRet = temp[mid]; if (length % 2 == 1) { priceRet = (temp[mid] + temp[mid+1]) / 2; } return (priceRet); } double GetMean( int price, int length, int shift) { double priceRet; //for(int i = shift; i < shift+length;i++) //{ if (price == PRICE_CLOSE) {priceRet = iMA(Symbol(),Period(),length,shift,MODE_SMA,price,shift);} else if (price == PRICE_HIGH) {priceRet = iMA(Symbol(),Period(),length,shift,MODE_SMA,price,shift);} else if (price == PRICE_LOW) {priceRet = iMA(Symbol(),Period(),length,shift,MODE_SMA,price,shift);} //} return (priceRet); } int GetPeriodForMinRange(int shift, double MinRange) { int P; P=100; if (GetPriceRange(P,shift) > MinRange) {//range is OK for this P value: try shorter P values for (; P>=1; P--) { //Print ("2 _get_range(P,shift) ", _get_range(P,shift), " P ", P, " shift ", shift); if (GetPriceRange(P,shift) <= MinRange) return(P);//previous P value was the limit } return(P); } return( P); } double GetPriceRange(int period, int shift) { return(High[iHighest(NULL,0,MODE_HIGH,period,shift)] - Low[iLowest(NULL,0,MODE_LOW,period,shift)]); } //End Data Retrieval bool Validate() { Comment(""); if(ArraySize(BoxLengthVals) != ArraySize(BoxHeightVals) || ArraySize(BoxHeightVals) != ArraySize(ShiftVals) || ArraySize(ShiftVals) != ArraySize(PriceVals) || ArraySize(PriceVals) != ArraySize(BoxPositionVals) || ArraySize(BoxPositionVals) != ArraySize(ColorVals) || ArraySize(ColorVals) != ArraySize(FamilyVals) ) { Print (ArraySize(BoxLengthVals),ArraySize(BoxHeightVals),ArraySize(ShiftVals),ArraySize(PriceVals),ArraySize(BoxPositionVals),ArraySize(ColorVals),ArraySize(FamilyVals) ); Comment("Input Counts do not match up"); return (false); } for(int i = 0;i < BoxCount; i++) { bool validPrice = false; for(int j = 0;j < ArraySize(ValidPrices); j++) { if (StringUpperCase(ValidPrices[j]) == PriceVals[i]) {validPrice = true; break;} } if (!validPrice) { Comment("Invalid Price: " + PriceVals[i]); return (false); } } for(i = 0;i < BoxCount; i++) { bool validBoxPosition = false; for(j = 0;j < ArraySize(ValidBoxPositions); j++) { if (StringUpperCase(ValidBoxPositions[j]) == BoxPositionVals[i]) {validBoxPosition = true; break;} } if (!validBoxPosition) { Comment("Invalid BoxPosition: " + BoxPositionVals[i]); return (false); } } return (true); } //---------------------------------------- void deinitGraph() { DeleteObjectsByPrefix(PREFIX); WindowRedraw(); } //+------------------------------------------------------------------+ void objectCreate(string name,int x,int y,string text="-",int size=42, string font="Arial",color colour=CLR_NONE) { ObjectCreate(name,OBJ_LABEL,0,0,0); ObjectSet(name,OBJPROP_CORNER,3); ObjectSet(name,OBJPROP_COLOR,colour); ObjectSet(name,OBJPROP_XDISTANCE,x); ObjectSet(name,OBJPROP_YDISTANCE,y); ObjectSetText(name,text,size,font,colour); } void SetBox(string name , datetime startTime,double startPrice,datetime endTime , double endPrice, color c) { if (ObjectFind(name) < 0) { ObjectCreate(name,OBJ_RECTANGLE,0,startTime,startPrice,endTime ,endPrice); ObjectSet(name,OBJPROP_COLOR,c); ObjectSet(name,OBJPROP_BACK,false); } else { ObjectMove(name, 0, startTime, startPrice); ObjectMove(name, 1, endTime, endPrice); ObjectSet(name,OBJPROP_BACK,false); } } void DeleteObjectsByPrefix(string Prefix) { int L = StringLen(Prefix); int i = 0; while(i < ObjectsTotal()) { string ObjName = ObjectName(i); if(StringSubstr(ObjName, 0, L) != Prefix) { i++; continue; } ObjectDelete(ObjName); } } //End Drawing string StringColorTable[] = {"Black","DarkGreen","DarkSlateGray","Olive","Green","Teal","Navy","Purple","Maroon","Indigo","MidnightBlue","DarkBlue","DarkOliveGreen","SaddleBrown","ForestGreen","OliveDrab","SeaGreen","DarkGoldenrod","DarkSlateBlue","Sienna","MediumBlue","Brown","DarkTurquoise","DimGray","LightSeaGreen","DarkViolet","FireBrick","MediumVioletRed","MediumSeaGreen","Chocolate","Crimson","SteelBlue","Goldenrod","MediumSpringGreen","LawnGreen","CadetBlue","DarkOrchid","YellowGreen","LimeGreen","OrangeRed","DarkOrange","Orange","Gold","Yellow","Chartreuse","Lime","SpringGreen","Aqua","DeepSkyBlue","Blue","Magenta","Red","Gray","SlateGray","Peru","BlueViolet","LightSlateGray","DeepPink","MediumTurquoise","DodgerBlue","Turquoise","RoyalBlue","SlateBlue","DarkKhaki","IndianRed","MediumOrchid","GreenYellow","MediumAquamarine","DarkSeaGreen","Tomato","RosyBrown","Orchid","MediumPurple","PaleVioletRed","Coral","CornflowerBlue","DarkGray","SandyBrown","MediumSlateBlue","Tan","DarkSalmon","BurlyWood","HotPink","Salmon","Violet","LightCoral","SkyBlue","LightSalmon","Plum","Khaki","LightGreen","Aquamarine","Silver","LightSkyBlue","LightSteelBlue","LightBlue","PaleGreen","Thistle","PowderBlue","PaleGoldenrod","PaleTurquoise","LightGray","Wheat","NavajoWhite","Moccasin","LightPink","Gainsboro","PeachPuff","Pink","Bisque","LightGoldenrod","BlanchedAlmond","LemonChiffon","Beige","AntiqueWhite","PapayaWhip","Cornsilk","LightYellow","LightCyan","Linen","Lavender","MistyRose","OldLace","WhiteSmoke","Seashell","Ivory","Honeydew","AliceBlue","LavenderBlush","MintCream","Snow","White","None"}; color ColorColorTable[] = {Black,DarkGreen,DarkSlateGray,Olive,Green,Teal,Navy,Purple,Maroon,Indigo,MidnightBlue,DarkBlue,DarkOliveGreen,SaddleBrown,ForestGreen,OliveDrab,SeaGreen,DarkGoldenrod,DarkSlateBlue,Sienna,MediumBlue,Brown,DarkTurquoise,DimGray,LightSeaGreen,DarkViolet,FireBrick,MediumVioletRed,MediumSeaGreen,Chocolate,Crimson,SteelBlue,Goldenrod,MediumSpringGreen,LawnGreen,CadetBlue,DarkOrchid,YellowGreen,LimeGreen,OrangeRed,DarkOrange,Orange,Gold,Yellow,Chartreuse,Lime,SpringGreen,Aqua,DeepSkyBlue,Blue,Magenta,Red,Gray,SlateGray,Peru,BlueViolet,LightSlateGray,DeepPink,MediumTurquoise,DodgerBlue,Turquoise,RoyalBlue,SlateBlue,DarkKhaki,IndianRed,MediumOrchid,GreenYellow,MediumAquamarine,DarkSeaGreen,Tomato,RosyBrown,Orchid,MediumPurple,PaleVioletRed,Coral,CornflowerBlue,DarkGray,SandyBrown,MediumSlateBlue,Tan,DarkSalmon,BurlyWood,HotPink,Salmon,Violet,LightCoral,SkyBlue,LightSalmon,Plum,Khaki,LightGreen,Aquamarine,Silver,LightSkyBlue,LightSteelBlue,LightBlue,PaleGreen,Thistle,PowderBlue,PaleGoldenrod,PaleTurquoise,LightGray,Wheat,NavajoWhite,Moccasin,LightPink,Gainsboro,PeachPuff,Pink,Bisque,LightGoldenrod,BlanchedAlmond,LemonChiffon,Beige,AntiqueWhite,PapayaWhip,Cornsilk,LightYellow,LightCyan,Linen,Lavender,MistyRose,OldLace,WhiteSmoke,Seashell,Ivory,Honeydew,AliceBlue,LavenderBlush,MintCream,Snow,White,CLR_NONE}; color StringToColor(string sColor) { //sColor = StringUpperCase(sColor); for (int i=0; i=0; length--) { int char = StringGetChar(s, length); if((char > 96 && char < 123) || (char > 223 && char < 256)) s = StringSetChar(s, length, char - 32); else if(char > -33 && char < 0) s = StringSetChar(s, length, char + 224); } return(s); } void StringSplit(string InputString, string Separator, string & ResultArray[]) { //ArrayResize(ResultArray, 0); int lenSeparator = StringLen(Separator), NewArraySize; while (InputString != "") { int p = StringFind(InputString, Separator); if (p == -1) { NewArraySize = ArraySize(ResultArray) + 1; ArrayResize(ResultArray, NewArraySize); ResultArray[NewArraySize - 1] = InputString; //Print (" if ", InputString, " p ", p, " NewArraySize ", NewArraySize, " ResultArray[NewArraySize] ", ResultArray[NewArraySize]); InputString = ""; } else { NewArraySize = ArraySize(ResultArray) + 1; ArrayResize(ResultArray, NewArraySize); ResultArray[NewArraySize - 1] = StringSubstr(InputString, 0, p); //Print (" else ", InputString, " p ", p, " NewArraySize ", NewArraySize, " ResultArray[NewArraySize] ", ResultArray[NewArraySize]); InputString = StringSubstr(InputString, p + lenSeparator); if (InputString == "") { ArrayResize(ResultArray, NewArraySize + 1); ResultArray[NewArraySize] = ""; } } } } void StringSplitToDoubles(string InputString, string Separator, double & ResultArray[]) { int lenSeparator = StringLen(Separator), NewArraySize; while (InputString != "") { int p = StringFind(InputString, Separator); if (p == -1) { NewArraySize = ArraySize(ResultArray) + 1; ArrayResize(ResultArray, NewArraySize); ResultArray[NewArraySize - 1] = StrToDouble(InputString); InputString = ""; } else { NewArraySize = ArraySize(ResultArray) + 1; ArrayResize(ResultArray, NewArraySize); ResultArray[NewArraySize-1] = StrToDouble(StringSubstr(InputString, 0, p)); InputString = StringSubstr(InputString, p + lenSeparator); if (InputString == "") { ArrayResize(ResultArray, NewArraySize + 1); ResultArray[NewArraySize] = 0; } } } }