Market Profile for AB version 6

I need help to recode this one to be compatible in version 6

_SECTION_BEGIN("MarketProfile");

PlotOHLC(O,H,L,C,"Price",IIf(C>O,colorGreen,colorRed),styleCandle);


EnMP2= ParamList("MarketProfile","Solid|Lines|Letters");
styleLines = ParamStyle("Style", styleLine, maskAll);

Type=ParamList("Type","Price Profile|Volume Profile");
Period= ParamList("Base","Hourly|Daily|Weekly|Monthly",1);


Den = Param("Density", 1, 0.25, 100, 0.25); // Resolution in terms of $
percent=Param("Value Area", 70, 1, 100, 1);
ViewTPOCount= ParamToggle("Show TPO Count", "No|Yes",1);
ViewPOC = ParamToggle("Show POC", "No|Yes",1);
ViewVALVAH = ParamToggle("Show VAL VAH Line", "No|Yes",1);
Viewfill = ParamToggle("Show VA Fill", "No|Yes",1);
Colorpoc=ParamColor("Color POC", colorYellow);
Colorfill=ParamColor("Color Fill", ColorRGB(20,40,60));


EnIB = ParamToggle("Show Initial Balance", "Yes|No");
IBBars = Param("Initial Balance Bars", 2, 0, 10, 1);

if(Period=="Daily"){
BarsInDay = BarsSince(Day() != Ref(Day(), -1));
Bot = TimeFrameGetPrice("L", inDaily, 0);
Top = TimeFrameGetPrice("H", inDaily, 0);
Vol = TimeFrameGetPrice("V", inDaily, 0);
}

if(Period=="Hourly"){
BarsInDay = BarsSince(Minute() != Ref(Minute(), -1));
Bot = TimeFrameGetPrice("L", in5Minute, 0);
Top = TimeFrameGetPrice("H", in5Minute, 0);
Vol = TimeFrameGetPrice("V", in5Minute, 0);
}

if(Period=="Weekly"){
BarsInDay = BarsSince(DayOfWeek() < Ref( DayOfWeek(), -1 ));
Bot = TimeFrameGetPrice("L", inWeekly, 0);
Top = TimeFrameGetPrice("H", inWeekly, 0);
Vol = TimeFrameGetPrice("V", inWeekly, 0);
}

if(Period=="Monthly" ){
BarsInDay = BarsSince(Month() != Ref(Month(), -1));
Bot = TimeFrameGetPrice("L", inMonthly, 0);
Top = TimeFrameGetPrice("H", inMonthly, 0);
Vol = TimeFrameGetPrice("V", inMonthly, 0);
}

CurTop = HHV(H,BarsInDay+1);
Curbot = LLV(L,BarsInDay+1);
Range = Highest(Top-Bot);
TodayRange = Top - Bot;

AveRange = Sum(Top-Bot,30)/30;
LAveRange = AveRange[BarCount-1];

// Initialization
baseX = 0;
baseY = floor(Bot[0]/Den)*Den;
relTodayRange = 0;
firstVisBar = Status("firstvisiblebar");
lastVisBar = Status("lastvisiblebar");

D=.0005;
total=0;
totaldn=0;
totalup=0;
shiftup=0;
shiftdn=0;
startr=0;

for (j=0; j <= 100; j++) {
  x[j] = 0;
}

i0 = 0;
i1 = 0;
for (i=0; i<BarCount; i++) {
  if (BarsInDay[i] == 0 AND i < firstVisBar) {
    i0 = i;
  }
  if (BarsInDay[i] == 0 AND i >= lastVisBar) {
    i1 = i;
  }
}

i1 = BarCount-1;
for (i=i0; i<=i1; i++) {
  if (BarsInDay[i] == 0) {
    baseX = i;
    baseY = floor(Bot[i]/Den)*Den;
    maxY = floor(Top[i]/Den)*Den;
    relTodayRange = (maxY-baseY)/Den;

    for (j=0; j <= relTodayRange; j++) {
      x[j] = 0;
    }
  }
	
	range_x=lastVisBar-firstVisBar;
	spread = Param("X Space", 80, 1, 200, 1);
	tpl = Param("Time Per Letter (mins)", 30, 1, 360, 1);
	Intervalmin=Interval()/60;
	flt =Param("First Letter (Bars)", 1, 1, 60, 1);
	teb=ParamToggle("To Each Bar","No|Yes");
	Color=Param("Color Threshold",20,1,50,1);
	stopg=0;
	stopr=0;
	new=0;
	
	Voloumeunit=Vol[i]/LastValue(BarsInDay);


  if (EnMP2 == "Letters") {
    for (j=0; j<= relTodayRange; j++) {
      if (L[i] <= baseY+j*Den AND H[i] >= baseY+j*Den) {
		PlotText(StrExtract(" A , B , C , D , E , F , G , H ,  I  , J , K , L , M , N , O , P , Q , R , S , T , U , V , W , X , Y , Z, a , b , c , d , e , f , g , h , i , j , k , L , m , n ,o , p , q , r , s , t , u , v , w , x , y , z ",
		IIf(BarsInDay[i]<flt,0,ceil(BarsInDay[i]/(tpl/Intervalmin))-0)), baseX+IIf(teb==1,BarsInDay[i],x[j]*(range_x/spread)), baseY+j*Den, 
		colorWhite,ColorHSB(10+((ceil(BarsInDay[i]/(tpl/Intervalmin)))*Color),160,140));
       x[j]++;

      }
    }
  }
	
  else if (EnMP2 == "Lines" OR EnMP2 == "Solid") {
    for (j=0; j<= relTodayRange; j++) {
     if (L[i] <= baseY+j*Den AND H[i] >= baseY+j*Den) {
		if(Type=="Price Profile"){x[j]=x[j]+1;}
		else if(Type=="Volume Profile"){x[j]=x[j]+round(V[i]/Voloumeunit);}
 	
	   }
    }
  }  

  // Draw Initial Balance after 11am bar is complete
  if (BarsInDay[i] == IBBars+1 AND EnIB == 0) {
    Line1 = LineArray(i-2, curtop[i-1],i+7, curtop[i-1],0,True);
    Plot(Line1,"",colorLightGrey,styleLine+styleDashed|styleNoRescale);
    Line1 = LineArray(i-2, curbot[i-1],i+7, curbot[i-1],0,True);
    Plot(Line1,"",colorLightGrey,styleLine+styleDashed|styleNoRescale);
  }

  // Examine x[j]
  if ((i < BarCount - 1 AND BarsInDay[i+1] == 0) OR i == BarCount-1) {
    maxXj = 0;
	maxj = 0;
    for (j=0; j<= relTodayRange; j++) {
      if (maxXj < x[j]) {maxXj = x[j]; maxj = j; StaticVarSet("Maxj",j); new=j;
	  }
    }
	for ( n = 1; n <= relTodayRange; n++ ) {
       total[n]=x[n]+total[n-1];
        }
	Value_area=(total[relTodayRange]*percent)/100;

	for ( a = 1; a <= relTodayRange; a++ )
	 {
		if(Maxj-a>0 AND Maxj+a<relTodayRange)
		{
			if(MaxXj+total[Maxj+a]-total[Maxj]+total[Maxj-1]-total[Maxj-(a+1)]>=Value_area) {shiftup=a; shiftdn=a; break;}
	 	}	
		else if(Maxj-a<1 ) 
		{
			if(MaxXj+total[Maxj+a]-total[Maxj]+total[Maxj-1]>=Value_area){shiftup=a; shiftdn=maxj-1; break;}		
   		}
		else if(Maxj+a>relTodayRange ) 
		{
			if(MaxXj+total[relTodayRange]-total[Maxj]+total[Maxj-1]-total[Maxj-(a+1)] >=Value_area){shiftup=relTodayRange-maxj; shiftdn=a; break;}		
   		}
	 }

	Vah = LineArray(baseX, baseY+(maxj+shiftup)*Den, i, baseY+(maxj+shiftup)*Den,0,True);
	Val = LineArray(baseX, baseY+(maxj-shiftdn)*Den, i, baseY+(maxj-shiftdn)*Den,0,True);
	poc = LineArray(baseX, baseY+maxj*Den, i, baseY+maxj*Den,0,True);
	if(ViewVALVAH==1){Plot(Vah,"",ParamColor("Color_VA",  colorLightBlue),styleLine|styleNoRescale);
	Plot(Val,"",ParamColor("Color_VA",  colorLightBlue),styleLine|styleNoRescale);}
	if(ViewPOC==1){Plot(poc,"",Colorpoc,styleLine|styleNoRescale);}
	PlotText(""+(baseY+(maxj+shiftup)*Den),i-5,baseY+(maxj+shiftup)*Den,colorWhite);
	PlotText(""+(baseY+(maxj-shiftdn)*Den),i-5,baseY+(maxj-shiftdn)*Den,colorWhite);
	if(ViewTPOCount==1){PlotText(""+total[maxj-1],basex,bot[i]-(Top[i]-bot[i])*0.05,ParamColor("Color_VAL", colorLavender));
	PlotText(""+(total[relTodayRange]-total[maxj]),basex,Top[i],ParamColor("Color_VAH", colorLavender));}



	if(ViewPOC==1){PlotText(""+(baseY+maxj*Den),i-5,baseY+maxj*Den,Colorpoc);}
  }
	
	if (i < BarCount - 1 AND BarsInDay[i+1] == 0 OR i == BarCount-1) {
	
	  for  (p = 1; p < relTodayRange+1; p++){
	  line = LineArray(baseX, baseY+p*Den, baseX+x[p], baseY+p*Den);
	  line2 = LineArray(baseX, baseY+(p-1)*Den, baseX+x[p-1], baseY+(p-1)*Den);

      if (EnMP2 == "Solid")
	  {
	  PlotOHLC( Line,  Line,  Line2, Line2, "",IIf(p>(maxj+shiftup),ParamColor("Color_VAH",  colorLavender),IIf(p<=(maxj+shiftup)AND p>(maxj-shiftdn),ParamColor("Color_VA", colorLightBlue),ParamColor("Color_VAL", colorLavender))) ,styleCloud|styleNoRescale|styleNoLabel);
	  }
	  if (EnMP2 == "Lines") 
	  {
     Plot(line,"",IIf(p>(maxj+shiftup),ParamColor("Color_VAH", colorLavender),IIf(p<=(maxj+shiftup)AND p>(maxj-shiftdn),ParamColor("Color_VA", colorLightBlue),ParamColor("Color_VAL",  colorLavender))) , styleLines|styleNoLabel);
     }
 	
   }
	 if(Viewfill==1){PlotOHLC(Vah,Vah,Val,Val,"",Colorfill,styleCloud|styleNoRescale|styleNoLabel);}

 } 
}


_SECTION_END();

Having an error on this part

PlotText(StrExtract(" A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q , R , S , T , U , V , W , X , Y , Z, a , b , c , d , e , f , g , h , i , j , k , L , m , n ,o , p , q , r , s , t , u , v , w , x , y , z ",
IIf(BarsInDay[i]<flt,0,ceil(BarsInDay[i]/(tpl/Intervalmin))-0)), baseX+IIf(teb==1,BarsInDay[i],x[j](range_x/spread)), baseY+jDen,
colorWhite,ColorHSB(10+((ceil(BarsInDay[i]/(tpl/Intervalmin)))*Color),160,140)); or paste code here

Also on this part.

if (L[i] <= baseY+jDen AND H[i] >= baseY+jDen) {

is it..if (L[i] <= baseY+jDen AND H[i] >= baseY+jDen) {

The code is not for version "X" or version "Y". Any newer version runs any code for older version.

The trouble with that code is that it is simply wrong. It contains errors that show with ANY version. Like error 10 subscript out of range which is explained in the Users Guide. It is also discussed in the Knowledge Base: http://www.amibroker.com/kb/2014/09/22/do-not-make-assumptions-on-number-of-bars/

Simply put, you can access array elements without making sure that they are within the array bounds, i.e. within 0...BarCount-1 range.

someindex = ...unknown data...
y = array[ someindex ] ; // wrong - index may be out of bounds

if( someindex >= 0 AND someindex < BarCount ) y = array[ someindex ]; // correct

With that information you should be able to fix this incorrect formula yourself.

1 Like

Hi @Tomasz,

It will be very kind of your genius to introduce TPO charts as a feather to the AmiBroker arsenal by now.

A suggestion only from an ardent user.

Thank you

1 Like

No idea how Market Profile work in real-time.
Besides from my view it just fancy tool.
Anyway tried with my limited coding knowledge :smile: & just few line of code…… this I got.
Not sure about correctness …….
MarketProfile

When you collapse them together for a day with 30 min prints, it will create a bell-like curve forming the normal distribution of price w.r.t. time - which I think is a valuable information as price spent most time at that level facilitating both buyers and sellers. Next day's Open is a crucial clue, and using previous day's value area, trading decisions can be taken. What's fancy in that? Who knows, may be better than falsifying Indicators as one can hone his trading skills rather than following foolish lagging signals.

Untitled
Image Source: www.esignal.com

@Cougar
Please confirm is the above code of Market Profile concept is correct? or someone else who trade using Market Profile.
000000
Use above code concept to code it.............

Thorough search of the old Yahoo Group and internet reveals that the same above code has been modified or edited in some form or other since 2009-2010.

NOT accurate as prints are lost because of pixel allocation w.r.t. ticks as per the code. Also letters are cluttered and dependent on the tick-size of a Symbol rather being auto-adjusted as per the real time tick w.r.t. chart scales.

It is also very interesting to note that during 2004-2006 many users started requesting TPO or Market Profile charts in similar fashion we are discussing today. Then the requests got subdued until 2008-2013. More or else every year individuals pop up with this request.

So, request for a Professional Market Profile Chart with all known features as per Steidlmayer or Dalton's book is nothing new in AmiBroker.

Market profile aka "volume at price" is provided by built-in functions for over 10+ years:
http://www.amibroker.com/f?plotvapoverlay
http://www.amibroker.com/f?plotvapoverlaya

Plus ability to create ANY kind of customized "market profile" chart by means of PriceVolDistribution universal, general purpose function:
http://www.amibroker.com/guide/afl/pricevoldistribution.html

This means that ANY IMAGINABLE "market profile" can be drawn.

Instead of giving fixed "one look" chart that one person would love and the other would hate, AmiBroker gives freedom to create whatever you wish.

3 Likes

Yes @Tomasz since you have provided sample codes for PriceVolDistribution it has evidently become extremely easy to code "Volume Profile".

However, any Market Profile related book/article that I have picked up either Steidlmayer, Dalton, Keppler or TASC issues, the authors have also shown the Market Dynamics using a TPO chart. And many users over the past decade have sporadically requested for the same.

According to the authors, at first glance TPOs might look very messy but upon studying each fragments slowly (like a detective building a case with clues) substantiates what Market is likely to do next. Agreed it is intuitive and subjective but another way of studying the markets.

You being an ace programmer, may I please request you to kindly publish a KB on how to draw correctly TPO charts using AFL like you have over-simplified drawing hundreds of other indicators. It will immensely help beginners like me to explore the uncharted adventurous trickery filled territories of AFL.

Thank you

P.S. AFL being a brainchild of your genius; it is of great pleasure to use AB and enjoy its blazing speed and efficiency. Thus, intend not to use other platforms for one little mole.

1 Like

To my knowledge Market Profile is study about Price distribution(TPO based) to understand the behavior of Market Participants and Volume Profile is study about Volume Distribution

Existing AFLs in the internet domain provide the facility to read the TPOs. But currently there is no comfort to compress or expand the datapoint to see more visual information.

By the way it is more of a visual tool to take trading decision than math involved. Hence from a market profile perspective, it is more of an art rather than a science.

Without having proper graphical interface supporting data compression and expansion on x and y axis it is tough to build a professional market profile tool in Amibroker.

NFMAY%20(30%20Minute)%202019_05_19%20(15_39_20)

1 Like

using the fuctions like http://www.amibroker.com/guide/afl/pricevoldistribution.html one can build amazing distribution on any datasets. But the compression/expansion issues remains the same.

What the heck are you actually talking about (once again)?

You can plot multiple profile side by side in AmiBroker too!
You just need to know your stuff (and by your post(s) you definitely do not know AB at all).

Do you see below picture?
It is similar plot as in your picture of different software -> multi profiles per session.
Do you see any problem in that picture? I don't (except for it looking fancy).

1

Also I don't see a problem if zooming out (with more sessions than in your picture).

38

So what exactly are you actually talking about?

??

3 Likes

I dont want to quote examples from external tools. Im not commenting about the coding ability in Amibroker. Infact Amibroker is the best tool for system trading or math rule based trading.

But market profile differs. It is more of graphic tool to understand the market participation. And it require horizontal compression & vertical compression and expansion of data points to understand the visual reference better. For Example compressing the horizontal scale to see last 15 days of market profile trading activity or pan and zoom to the a particular price and time level. Those are the critical reading for a market profile users.

Iam a market profile user since the year 2012-13 onwards and the sad part is that still no much importance from the Amibroker Community on how to utilize those graphical tools.

Plotting the Profile charts alone doesn't gives a professional user a comfort apart from that many graphical supportive narratives are there. Go back and check the other professional tools available in the market you know the difference.

Once again you are too vague!
I have shown to you two pictures - one being zoomed in and another being zoomed out (and both do same thing as your picture. And adding additional profile for overall chart range on left side is no problem too).

What is missing there??
What is the issue there in my pictures (-> what is missing in your opinion)?
Be specific/detailed.
Your understanding of "horizontal compression & vertical compression and expansion of data points" may mean something different to other people. (As aside you can make profile(s) to auto adjust to current zoom level if that's your issue.)


I am quoting you again:

You need to show video/more pictures of what is meant exactly and what is missing/not possible in your opinion (note: opinion is not equal to actual fact).

So 15 days activity are zoomed out in below picture (any problem there?).

1

For example we may keep chart zoom level and may zoom to particular date's or session's profile via Analysis - Explorer showing more information of that chosen date's profile.

4

What else do you mean?

No, I don't use other software.
The thing is you want something to be added to AB but in order to provide something you need to be detailed and precisely. Otherwise it is pointless.

Fact remains most or all that Market Profile stuff can be done via AFL (also).

5 Likes