Real-time Intraday Range Chart

I'm trying to create a real time intraday range chart using the IB-plugin, and I want to use the midpoint between the bid and ask as the value to chart (instead of using the close value or last trade) .

I'm using the code below, but I'm not getting a new range bar once the range has been exceeded (see screen shot). My ticksize is 0.01 and my range is 5 ticks just for troubleshooting purposes.

Can someone please help me understand why my code is not giving me a normal range chart?


// Plot RANGE bars based on the midpoint between the bid/ask (instead of using Close values)
TimeFrameMode(4);   // set to Range Bars 
TimeFrameSet(5);    //  set the range
RequestTimedRefresh(3,false);   //  refresh the chart if it's in the background
CurrentMidPoint=C;     // initialize the CurrentMidPoint array for backfill purposes.  I don't think I can backfill bid/ask midpoints.

// Get current real-time data and calculate the midpoint
CurrentMidPoint[BarCount-1] = (Bid+Ask)/2;

_N(Title = StrFormat("Custom Range {{NAME}} - {{INTERVAL}} {{DATE}} Bid %g, Ask %g, Mid %g, Open %g, High %g, Low %g", Bid, Ask, CurrentMidPoint, Open, High, Low));
Plot(CurrentMidPoint,"MidPoint Chart",colorBlack,styleCandle); 


First: TimeFrameSet is not for changing selected chart interval. It is for mixing multiple intervals in one chart. You need to select correct interval from "Interval" combo box (or View->Intraday menu). If you do so, you can just remove TimeFrameMode and TimeFrameSet. They are not needed

There is missing bit of information in your post. What are your data source settings? I mean what base time interval do you have in File->Database Settings?

Please follow this advice: How to ask a good question

Regarding the first point about the TimeFrameSet, after removing those lines from the code, the range bars are still sometimes longer than 10 ticks even with my interval set to 10R with tick size of 0.01.

For the second point, there is additional info with details related to the data source settings in the clip below.


As shown in the original screen shot for this post, the high and low values are not always 10 ticks apart, so they can vary. When the midpoint goes higher than the high or lower than the low, the bar that is drawn is longer than the 10 point (10R) interval. So far I haven't found a pattern to when the issue occurs. I believe a lot of the bars are drawn as expected, it's just some that don't stay within or close to the 10 points. When the issue occurs, the bars can be 15 or 20 points long.

I meant you should TYPE 5R into "Interval" combo (or select View->Intraday menu after you define 5R custom interval in the Tools->Preferences).



Also, keep in mind that "R" is a multiple of TickSize defined in Window->Symbol Information. So please make sure to enter proper TickSize.


Thanks for clarifying. The issue persists with the 5R and 10R settings as described.

I simplified the code and have a new screen shot that shows the chart not maintaining the proper high and low values for each range bar. Only the current range bar has a somewhat accurate high and low, although the current bar continues to exceed the interval length of 5 ticks with tick size of 0.01. Once a new bar is drawn, the prior bar seems to be redrawn with a very low "low value".

Revised Code:

_SECTION_BEGIN("Midpoint Price");

CurrentMidPoint[BarCount-1] = (Bid+Ask)/2;

_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Bid %g, Ask %g, Mid %g", Bid, Ask, CurrentMidPoint));
Plot(CurrentMidPoint,"MidPoint Chart",colorBlack,styleCandle); 


My goal is to have a range chart that aligns with the interval (e.g. 5R) and the price that is being charted is the midpoint between the bid and ask prices.

What you do is incorrect.
GetRtData is not an array function!
If returns number being last retrieved real-time value.


To plot array price you should insert array price variable into plot function (e.g. Close).
And since GetRtData gets last value just some line style makes sense but not styleBar or styleCandle.

_SECTION_BEGIN("Midpoint Price");

Bid=GetRTData("Bid");//not an array!
Ask=GetRTData("Ask"); //not an array! 
CurrentMidPoint = (Bid+Ask)/2; //not an array! 

_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Bid %g, Ask %g, Mid %g", Bid, Ask, CurrentMidPoint));
// array plot
Plot(Close,"Price Chart",colorDefault,styleCandle); 
// number plot
Plot(CurrentMidPoint,"Last MidPoint",colorBlack, styleLine /* | styleDashed */ ); 

If you want to store Bid Ask then take a look here:

(BTW (#1), IB data just send 250 millisecond snapshots.)

(BTW (#2), as for streaming quotes IQFeed plugin of AB stores Bid/Ask to Aux1 and Aux2 array fields. Base interval 1-tick.)

The problem is in your code. To display RANGE chart you have to do just SINGLE LINE

Plot( C, "Chart", colorDefault, styleCandle ); // this displays proper chart

This and nothing else is needed.

The code that you are using incorrect in many areas.

  1. It writes to LAST element of array, but all remaining array elements are UNSET (random)
  2. It does not write to OHL arrays, and OHL arrays are REQUIRED for candlesticks. Even if you only pass Close array to Plot() it implicitly using OHL arrays (unless you call PlotOHLC)

Your code is unnecessary. You don't need to calculate anything yourself.

MidPoint is automatically calculated for forex by IB TWS , you don't need to calculate it yourself. What you need is to select MID point in plugin settings (File->Database Settings->Configure)


I've confirmed that (File -> Database Settings -> Configure) is set to the midpoint, and I've replaced my formula with the single line:

Plot( C, "Chart", colorDefault, styleCandle );

But that is plotting values based on the last trade, not anything related to the current bid or ask (see new screen shot below). Since I'm looking at option data, there are not trades constantly, so the chart is not being updated even though the bid and ask values have moved away from the value of the last trade . My goal is to have a chart with the price that is being charted that is the midpoint between the bid and ask prices.


If you want to change the very last price displayed on chart you should modify last bar of CLOSE array this way:

// modify LAST price on chart
Close[ BarCount - 1 ] = (GetRTData("Bid")+GetRTData("Ask"))/2; 
Plot( Close, "Chart", colorDefault, styleCandle );

After testing the code to modify the last bar of the CLOSE array, I noticed my last bar would grow taller than the interval (5R) temporarily, but then after it was no longer the last bar it would be completely redrawn using different data.

In the first screen shot below, it shows the last bar (which starts at 10:44:55) while it was still being drawn, and the midpoint of the bid/ask had dropped to 2.35 as shown. With the interval set to 5R and tick size of 0.01, it doesn't seem like the same bar would span the range from 2.42 to 2.35.


The next screen shot shows the same bar after it was no longer the current bar. The bar was redrawn and it doesn't reflect that the bid/ask price was ever at 2.35. I did not perform a backfill or any other changes between screen shots.

I'd like for the height of the range bars to always stay within the interval range (5R in this example), and after the last bar is drawn showing the range of the midpoint of the bid/ask, I would like the bar to remain static at least until I exit the program.

That is normal because all bars except last one represent what is sent by IB plugin which is based on TRADES not offers. Also the chart represents TRADES, not offers. The code given above temporarily modifies last bar close (i.e. last price) to be midpoint of Bid and Ask and this is for display only. Modifications done to Close array affect only current execution, they are NOT stored anywhere.

Does this mean it is not possible to plot a range chart with the bid/ask midpoint or does this just mean I need to write different code, possibly using the PlotOHLC function?

I tried using the code below, but I had received guidance to use arrays instead. While the code below is producing valid values for the open, high, low, and close, I'm only getting vertical lines that don't reflect the values in the arrays being plotted.


// Plot RANGE bars based on the midpoint between the bid/ask (instead of using Close values)

CurrentInterval=-(Interval(1));   // get the range interval

// The 4 variables below will replace the standard Open, High, Low, and Close
MPO=0;			// Initialize Mid Point Open array
MPH=0;			// Initialize Mid Point High array
MPL=10000;    	// Initialize Mid Point Low array  This is set to a high value initially to ensure the first tick will be lower, so the code will update it going forward.
MPC=0;			// Initialize Mid Point Close array

LastTick=0;		// Track the last tick during each bar because the last tick determines when a new bar needs to be started

CurrentMidPoint = (Bid+Ask)/2;  // Get the current midpoint
LastTick[0]=CurrentMidPoint;	 // Initialize the very first LastTick value
MPO[0]=CurrentMidPoint;		 // Initialize the very first Open value

_N(Title = StrFormat("CustomPrice5 {{NAME}} - {{INTERVAL}} {{DATE}} Bid %g, Ask %g, Mid %g, Open %g, High %g, Low %g, Close %g {{VALUES}}", Bid[BarCount-1], Ask[BarCount-1], CurrentMidPoint, MPO, MPH, MPL, MPC ));

NextBar=False;     //  NextBar tracks whether or not a new bar is needed based on the current midpoint value (CurrentMidPoint)
LastTimeNum=LastValue(TimeNum());     //LastTimeNum is used to track number of seconds since chart has been redrawn
for( i = 1; i < BarCount; i++ )
{  if (i < (BarCount -1) AND MPC[i] == 0)  // if the bar beeing processed is not the latest bar, and if no existing values exist, use the standard O, H, L, C values to initialize them
	{                                      // I believe using standard O, H, L, C may help when backfilling since the historical intraday bid and ask values are not available
	  MPO[i] = O[i];
	  MPH[i] = H[i];
	  MPL[i] = L[i];
	  MPC[i] = C[i];  
    if (i == (BarCount -1))  //  Processing the latest bar
       x=0;   //x is a counter to track the number of repetitions of the "while" loop.  This is too try to avoid the "endless loop" error.
	   while (NextBar==False AND (x < 1000000))    //  NextBar tracks whether or not a new bar is needed based on the current midpoint value (CurrentMidPoint)
		CurrentMidPoint = (Bid+Ask)/2;
		// If price goes below or above current bar range, set NextBar to True and capture the price value that is outside the bar range.   
		if ((MPH[BarCount-1] - CurrentMidPoint) > (BarSize) OR (CurrentMidPoint - MPL[BarCount-1]) > (BarSize))
			LastTick[BarCount-1] = CurrentMidPoint;
		else     // else the CurrentMidPoint is within the range of the current bar
			if (MPO[i]==0)
				MPO[i]=LastTick[BarCount-2];      	// set the Open (MPO) to the LastTick from the prior bar
			if (MPL[i] > CurrentMidPoint)
				MPL[i] = CurrentMidPoint;			// adjust the low value when the current mid point is lower
			if (MPH[i] < CurrentMidPoint)
				MPH[i] = CurrentMidPoint;  			// adjust the high value when the current mid point is higher
			MPC[i] = CurrentMidPoint; 				// The midpoint close value is always set to the current midpoint
		x=x+1;	//x is a counter to track the number of repetitions of the "while" loop.  This is too try to avoid the "endless loop" error.
		//Redraw the chart every 10 seconds	
		if ((LastValue(TimeNum()) - LastTimeNum) > 10)     //LastTimeNum is used to track number of seconds since chart has been redrawn
		  PlotOHLC(MPO,MPH,MPL,MPC,"Range Chart",0,styleCandle);


Do you have access to historical data of ask/bid ?
If yes, you can plot what you want


Bid, Ask returned by GetRTData are numbers, NOT ARRAYS

Hi, how to store the bid and ask data in static variables.
iam trying a code below but it never works and plots only the last value with a single straight horizontal line.


xBid = GetRTData("Bid");
xAsk =GetRTData("Ask");
tempBID = Nz( StaticVarGet( "BID_" + FullName() ));
tempASK = Nz( StaticVarGet( "ASK_" + FullName() ));
StaticVarSet( "BID_" + FullName(), xBid );
StaticVarSet( "ASK_" + FullName(), xAsk );
Plot( tempBID,"BID" , colorGreen, 1);


I checked the link "" given above but its not available. Thanks.

@ragTrader , FWIW, here is an article from the old UserKB that shows a way to do it.

Take note, as stated in the main index page, that any info on that site IT IS NOT AUTHORITATIVE SOURCE OF INFORMATION. - Users’ KB site was created in 2007 as community driven kb and contains UNOFFICIAL information.

If you copy/paste the code, you'll run in some errors, since some chars are not properly displayed.
For instance the sequence &gt; should be replaced by the 'greater than' symbol >.

Hi, thanks for your time. Do appreciate it.
Will check the article as you did mentioned.

First of all, hijacking not-relevant threads to conduct unrelated discussion is NOT welcome.
Create new thread, don't hijack 3-year old thread.

Second thing: what is wrong with your code is that you are not thinking about types of variables that you use. In short GetRTData function returns scalar NUMBER, not array. It was clearly said here Real-time Intraday Range Chart - #15 by awilson A single number does not produce chart.

You need to store the value that you get from GetRTData in the very last array item as shown here: Real-time Intraday Range Chart - #10 by Tomasz

1 Like

Thread is 3 year old and it was hijacked for irrelevant subject.