//+------------------------------------------------------------------+ //| MurreyLevels-Dirigible.mq4 | //| Oleg Fedorov (aka certain) | //| voltIrEvvoyRipyafjamNeidy@gmail.com | //| Version from 15.12.2017 | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Makes a colorful Murray levels, that can be dirigible | //| by the Ruler line. | //| | //| If isNeedAutomake=true, it makes first level complect on the | //| high/low of the initialBarsForExtremums interval - or on bars | //| that you can specify with firstBarNumber and secondBarNumber. | //| | //| You can make new complect by clicking on the label in the | //| right upper corner | //| | //| If you will made Ruler line by hand - you will need to drag it | //| to show levels. Number of line must be the same as label shows. | //| If you want to draw many lines, you need to change timeframe | //| after you will draw it all. | //| | //| If you want to hide some complect of levels on some timeframes, | //| you can check this timeframes at the Ruler line | //+------------------------------------------------------------------+ #property copyright "Oleg Fedorov (aka certain)" #property link "voltIrEvvoyRipyafjamNeidy@gmail.com" #property version "1.21" #property strict #property indicator_chart_window //TODO: //#include //--- input parameters input string Section_of_parameters_01_="---==== Common parameters ====--- "; input bool isNeedAutomake=true; // Automatically create levels complect, if it is nothing yet input bool showOnParentTimeframes=false; //--- input bool showPrices=true; // Add prices to levels descriptions input bool showLevelsLabels=false; // Show additional labels for levels prices //--- input int initialBarsForExtremums=50; // How many bars you need for initial complect? input int timeCoefficient=5; // How long will be lines? input string prefix="MM-dirigible-"; // Which prefix of all indicator's elements? //--- input string Section_of_parameters_02_="---==== Initial points numbers ====--- "; input int firstBarNumber=0; // First point - If you don't want to start from begin of chart input int secondBarNumber=0; // Second point - If you don't want to start from begin of chart //--- input string Section_of_parameters_03_="---==== Colors set ====--- "; input color rulerColor=clrRed; // Color of ruler line input color levelsColor_08=clrRed; // color of 0 and 8 levels input color levelsColor_4=clrRed; // color of 4 level input color levelsColor_26=clrLightGreen; // color of 2 and 6 levels input color levelsColor_35=clrYellow; // color of 3 and 5 levels input color levelsColor_17=clrGreen; // color of all other levels //--- input string Section_of_parameters_04_="---==== Widths set ====--- "; input int rulerWidth=1; // Width of ruler line input int levelsWidth_08=2; // Width of 0 and 8 levels input int levelsWidth_4=1; // Width of 4 level input int levelsWidth_26=1; // Width of 2 and 6 levels input int levelsWidth_35=1; // Width of 3 and 5 levels input int levelsWidth_17=1; // Width of all other levels //--- input string Section_of_parameters_05_="---==== Styles set ====--- "; input int rulerStyle=2; // Style of ruler line input int levelsStyle_08=0; // Style of 0 and 8 levels input int levelsStyle_4=0; // Style of 4 level input int levelsStyle_26=2; // Style of 2 and 6 levels input int levelsStyle_35=2; // Style of 3 and 5 levels input int levelsStyle_17=2; // Style of all other levels //--- global variables int complectNumber=0; string complectSuffix="Complect#"; string allComplectsName[]; string rulerLineShortName="Ruler Line"; string levelShortName="Level"; int firstPointBarNumber=0; int secondPointBarNumber=0; double firstPointPrice,secondPointPrice; datetime firstPointTime,secondPointTime; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { string objectName=""; int i; int maximumBarNumber=0; int minimumBarNumber=0; //--- indicator buffers mapping //--- Data initialization ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,true); //TODO: Set it as a separate function (collect all complects) objectName=GetFullObjectName(rulerLineShortName,complectNumber); if(ObjectFind(objectName)!=-1) { for(i=0;ObjectFind(objectName)!=-1;i++) { complectNumber=i+1; ArrayResize(allComplectsName,complectNumber); allComplectsName[i]=objectName; DelCurrentLineLevels(objectName); DrawMMLevels(objectName); objectName=GetFullObjectName(rulerLineShortName,complectNumber); } } else { if(isNeedAutomake) { MakeRuler(); } } DelCurrentLineLevels(objectName); DrawMMLevels(objectName); setNextRulerLabel(); //TODO: Make it universal (without TF-change needs) //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectDelete("MM-next-Ruler"); } //+------------------------------------------------------------------+ //| 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[]) { //--- //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { string pref=""; int elementNumber; string elementNameSuffix=StringSubstr( sparam, StringFind(sparam,"-",StringLen(prefix+complectSuffix))+1, 0); string elementNamePrefix=StringSubstr(sparam,0,StringLen(prefix)); //--- switch(id) { case CHARTEVENT_OBJECT_DRAG: { if(elementNamePrefix==prefix && elementNameSuffix==rulerLineShortName) { DelCurrentLineLevels(sparam); DrawMMLevels(sparam); } break; } case CHARTEVENT_OBJECT_DELETE: { if(elementNamePrefix==prefix && elementNameSuffix==rulerLineShortName) { DelCurrentLineLevels(sparam); allComplectsName[elementNumber]=""; } break; } case CHARTEVENT_OBJECT_CLICK: { if(sparam=="MM-next-Ruler") { MakeRuler(); DrawMMLevels( GetFullObjectName(rulerLineShortName, complectNumber-1 ) ); setNextRulerLabel(); } break; } } } //+------------------------------------------------------------------+ //| Draw any trendline on the chart | //+------------------------------------------------------------------+ void DrawLine(string objectName, datetime _firstPointTime, double _firstPointPrice, datetime _secondPointTime, double _secondPointPrice, color lineColor, int lineStyle=2, int lineWidth=1, bool isRay=false ) { //--- ObjectCreate(objectName,OBJ_TREND,0, _firstPointTime,_firstPointPrice, _secondPointTime,_secondPointPrice); ObjectSetInteger(0,objectName,OBJPROP_COLOR,lineColor); ObjectSetInteger(0,objectName,OBJPROP_WIDTH,lineWidth); ObjectSetInteger(0,objectName,OBJPROP_STYLE,lineStyle); ObjectSetInteger(0,objectName,OBJPROP_RAY,isRay); } //+------------------------------------------------------------------+ //| Draw all Murray Levels | //+------------------------------------------------------------------+ void DrawMMLevels(string rulerFullName) { string levelFullName; string currentLevelName; string currentLabelName; double trendVolatility; double levelAmount; int lineLength; int i; color currentColor; int currentWidth; int currentStyle; double currentPrice; long currentTimeframes; datetime secondLevelTime; //int secondDayOfWeek; //--- if(ObjectFind(rulerFullName)!=-1) { //--- Initiations CalculateStartingPoints(rulerFullName); trendVolatility=firstPointPrice-secondPointPrice; levelAmount= trendVolatility/8; lineLength = Period()*60*MathAbs(firstPointBarNumber-secondPointBarNumber)*timeCoefficient; secondLevelTime=GetTimeWithShift(firstPointTime+lineLength); currentTimeframes=ObjectGetInteger(0,rulerFullName,OBJPROP_TIMEFRAMES); //--- Drawing for(i=-2;i<11;i++) { currentLevelName=levelShortName+" "+IntegerToString(i); levelFullName=GetFullObjectName(currentLevelName,GetComplectNumber(rulerFullName)); switch(i) { case 0:case 8: { currentColor = levelsColor_08; currentWidth = levelsWidth_08; currentStyle = levelsStyle_08; break; } case 3:case 5: { currentColor = levelsColor_35; currentWidth = levelsWidth_35; currentStyle = levelsStyle_35; break; } case 2:case 6: { currentColor = levelsColor_26; currentWidth = levelsWidth_26; currentStyle = levelsStyle_26; break; } case 4: { currentColor = levelsColor_4; currentWidth = levelsWidth_4; currentStyle = levelsStyle_4; break; } default: { currentColor = levelsColor_17; currentWidth = levelsWidth_17; currentStyle = levelsStyle_17; } } currentPrice=firstPointPrice-levelAmount*i; DrawLine(levelFullName,firstPointTime,currentPrice, secondLevelTime,currentPrice, currentColor,currentStyle,currentWidth); ObjectSetInteger(0,levelFullName,OBJPROP_TIMEFRAMES,currentTimeframes); if(showPrices) { ObjectSetText(levelFullName,DoubleToString(currentPrice,Digits())+" "+GetTimeframeName(currentTimeframes)); if(showLevelsLabels) { currentLabelName=GetFullObjectName( "Label"+IntegerToString(i), GetComplectNumber(rulerFullName) ); ObjectCreate(currentLabelName,OBJ_ARROW_LEFT_PRICE,0,firstPointTime,currentPrice); ObjectSetInteger(0,currentLabelName,OBJPROP_TIMEFRAMES,currentTimeframes); ObjectSetInteger(0,currentLabelName,OBJPROP_COLOR,currentColor); } } } } } //+------------------------------------------------------------------+ //| Utility function - get full name from the short one. | //+------------------------------------------------------------------+ string GetFullObjectName(string shortName,int complect) { //--- return(prefix + complectSuffix+ IntegerToString(complect)+ "-"+shortName ); } //+------------------------------------------------------------------+ //| Utility function - get element number in array - or -1, if it | //| does not exists. | //+------------------------------------------------------------------+ int ArraySearch(const string &array[],string needle) { int elementNumber=-1; int i; int range=ArrayRange(array,0); //--- for(i=0;iHigh[i+1] && High[i]>High[i+2] && High[i]>High[i-1] && High[i]>High[i-2]) { maximumBarNumber=i; break; } } } if(minimumBarNumber==0) { for(i=3;imaximumBarNumber) { firstPointBarNumber=minimumBarNumber; secondPointBarNumber=maximumBarNumber; } else { firstPointBarNumber=maximumBarNumber; secondPointBarNumber=minimumBarNumber; } } else { if(firstBarNumber>secondBarNumber) { firstPointBarNumber=firstBarNumber; secondPointBarNumber=secondBarNumber; } else { firstPointBarNumber=secondBarNumber; secondPointBarNumber=firstBarNumber; } } //--- if(Low[firstPointBarNumber]=shift*2) { if(TimeDayOfWeek(farTime)==0) { farTime+=shift; } if(TimeDayOfWeek(farTime)==6) { farTime+=shift+shift; } } return (farTime); } //+------------------------------------------------------------------+