//+------------------------------------------------------------------+ //| Price_Distribution.mq4 | //| Copyright © 2006, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, MetaQuotes Software Corp." #property link "http://www.metaquotes.net" #define SECONDS_IN_MINUTE 60 #define SECONDS_IN_HOUR 3600 #define SECONDS_IN_DAY 86400 #define OBJNAME_PREPEND "ValueInRange" #property indicator_chart_window extern string BoxStart = "10:00"; extern string BoxEnd = "23:59"; extern string LineEnd = "10:00"; extern double PlotMagnification = 300.0; extern color BoxColor = C'17,28,28'; extern color LineColor = DarkSlateGray; extern color PlotColor = SlateGray; extern int DaysToPlot = 10; int init() { } int deinit() { DeleteObjects(OBJNAME_PREPEND); return(0); } int start() { int iPlots = 0; // Determine how far back to iterate // Always recalc last complete bar int iBarsToCalc = Bars - IndicatorCounted(); if (iBarsToCalc < Bars) iBarsToCalc++; // Determine start time for current (or just closed) box datetime dtBoxStart = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE) + " " + BoxStart); if (dtBoxStart > TimeCurrent()) dtBoxStart -= SECONDS_IN_DAY; // Determine end time for current (or just closed) box datetime dtBoxEnd = StrToTime(TimeToStr(dtBoxStart,TIME_DATE) + " " + BoxEnd); if (dtBoxEnd < dtBoxStart) dtBoxEnd += SECONDS_IN_DAY; // Simply loop, there are multiple ways to break // While the box close time is after the oldest bar which needs calculation, // calculate the box then add a day and repeat while (true) { // If the box close time is before the oldest bar which needs calculation, exit if (dtBoxEnd < Time[iBarsToCalc]) return(0); // If max number of iterations reached, exit if (iPlots >= DaysToPlot) return(0); // If the range to be plotted has data, plot it if (iBarShift(NULL,PERIOD_M1,dtBoxStart,false) != iBarShift(NULL,PERIOD_M1,dtBoxEnd,false)) { Print(TimeToStr(dtBoxStart), " ", TimeToStr(dtBoxEnd)); doCalcValueInRange(dtBoxStart); iPlots++; } else { Print("No data for ", TimeToStr(dtBoxStart), " ", TimeToStr(dtBoxEnd)); } // Decrement dates dtBoxStart -= SECONDS_IN_DAY; dtBoxEnd -= SECONDS_IN_DAY; } } void doCalcValueInRange(datetime dtBoxStart) { // Determine box end time based on box start time // Insure it's after box start datetime dtBoxEnd = StrToTime(TimeToStr(dtBoxStart,TIME_DATE) + " " + BoxEnd); if (dtBoxEnd < dtBoxStart) dtBoxEnd += SECONDS_IN_DAY; // Determine line end time based on box end time // Insure it's after box end datetime dtLineEnd = StrToTime(TimeToStr(dtBoxEnd,TIME_DATE) + " " + LineEnd); if (dtLineEnd < dtBoxEnd) dtLineEnd += SECONDS_IN_DAY; // Figure out start and end bars for box on the minute chart // Make sure the timestamp of start bar is >= box start time int iStart = iBarShift(NULL,PERIOD_M1,dtBoxStart,false); int iEnd = iBarShift(NULL,PERIOD_M1,dtBoxEnd,false); while (iTime(NULL,PERIOD_M1,iStart) < dtBoxStart) iStart--; // Get the high and low prices for the day double dHigh = iHigh(NULL,PERIOD_M1,iHighest(NULL,PERIOD_M1,MODE_HIGH,iStart-iEnd,iEnd)); double dLow = iLow (NULL,PERIOD_M1,iLowest (NULL,PERIOD_M1,MODE_LOW ,iStart-iEnd,iEnd)); // Draw the box doDrawBox(dtBoxStart,dtBoxEnd,dHigh,dLow); // Draw the high/low lines doDrawRangeLines(dtBoxStart,dtLineEnd,dHigh,dLow); // Draw the price distribution doDrawDistribution(dtBoxStart,dtLineEnd,dHigh,dLow); } void doDrawBox(datetime dtStart, datetime dtEnd, double dHigh, double dLow) { // Draw the box string sObjName = OBJNAME_PREPEND + " " + TimeToStr(dtStart); ObjectCreate(sObjName,OBJ_RECTANGLE,0,dtStart,dHigh,dtEnd,dLow); ObjectSet(sObjName,OBJPROP_COLOR,BoxColor); } void doDrawRangeLines(datetime dtStart, datetime dtEnd, double dHigh, double dLow) { string sObjName; // Draw range high sObjName = OBJNAME_PREPEND + " " + TimeToStr(dtStart) + " " + "High"; ObjectCreate(sObjName,OBJ_TREND,0,dtStart,dHigh,dtEnd,dHigh); ObjectSet(sObjName,OBJPROP_RAY,false); ObjectSet(sObjName,OBJPROP_COLOR,LineColor); // Draw range low sObjName = OBJNAME_PREPEND + " " + TimeToStr(dtStart) + " " + "Low"; ObjectCreate(sObjName,OBJ_TREND,0,dtStart,dLow,dtEnd,dLow); ObjectSet(sObjName,OBJPROP_RAY,false); ObjectSet(sObjName,OBJPROP_COLOR,LineColor); } void doDrawDistribution(datetime dtStart, datetime dtEnd, double dHigh, double dLow) { // Buckets to place 'ticks' into. double dBuckets[50]; ArrayInitialize(dBuckets,0.0); // Var to tally total 'ticks' int iTicks = 0; // Figure out the value to use to "split" prices into different buckets double dSplitter = (dHigh - dLow) / ArraySize(dBuckets); // Get the offset for the first minute bar of the range. double iStartBar = iBarShift(NULL,PERIOD_M1,dtStart,false); while (iTime(NULL,PERIOD_M1,iStartBar) < dtStart) iStartBar--; // Get the offset for the last minute bar of the range. double iEndBar = iBarShift(NULL,PERIOD_M1,dtEnd,false); // Iterate all minutes of the day and place a 'tick' in each bucket // that price touched for (int i=iStartBar;i>=iEndBar;i--) { for (int j=0;j<=ArraySize(dBuckets)-1;j++) { double dBucketHigh = dHigh - (j) *dSplitter; double dBucketLow = dHigh - (j+1)*dSplitter; // If price was above bucket range, no tick if (iLow(NULL,PERIOD_M1,i) > dBucketHigh) continue; // If price was below bucket range, no tick if (iHigh(NULL,PERIOD_M1,i) <= dBucketLow) continue; // bucket gets a tick dBuckets[j] += 1; iTicks++; } } //string sObjName = OBJNAME_PREPEND + " " + TimeToStr(dtStart) + " TickTotal"; //ObjectCreate(sObjName,OBJ_TEXT,0,dtStart,(dHigh+dLow)*0.5); //ObjectSetText(sObjName,"Ticks: " + iTicks); // Draw Bucket Lines for (j=0;j<=ArraySize(dBuckets)-1;j++) { dBucketHigh = dHigh - (j) *dSplitter; dBucketLow = dHigh - (j+1)*dSplitter; // Create a name for the bucket object string sObjName = OBJNAME_PREPEND + " " + TimeToStr(dtStart) + " Bucket " + j+1; // Determine how many bars long it will be. Each bar indicates bucket contained 5% of the price action int iObjLength = 1; if (iTicks > 0) iObjLength = (dBuckets[j]/iTicks)*PlotMagnification; ObjectCreate(sObjName,OBJ_RECTANGLE,0,dtStart,dBucketHigh,dtStart+Period()*60*iObjLength,dBucketLow); ObjectSet(sObjName,OBJPROP_COLOR,PlotColor); } } void DeleteObjects(string sObjNamePrepend) { // delete objects for (int i=ObjectsTotal()-1;i>=0;i--) { string sObjName = ObjectName(i); if (StringFind(sObjName,sObjNamePrepend) == 0) ObjectDelete(sObjName); } }
Sample
Analysis
Market Information Used:
Series array that contains open time of each bar
Series array that contains the highest prices of each bar
Series array that contains the lowest prices of each bar
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
Order Management characteristics:
Other Features: