Custom Heads Up Display (HUD)

All sample GUI interfaces provided in the library package include a simple Heads Up Display on the upper right corner of the menu bar.

Example: HUD sample

By default it displays basic information about the primary chart symbol (Open, Close, High. Low, Volume, Date). But it can be customized to include any data point rendered on the chart including studies and series overlays.

The look and feel of it can also be modified since it is a simple HTML list. Here is sample HTML showing what it may look like:

<ul class="hu">
	<li><span class="huLabel">O: </span><span id="huOpen" class="huField"></span></li>
	<li><span class="huLabel">H: </span><span id="huHigh" class="huField"></span></li>
	<li><span class="huLabel">V: </span><span id="huVolume" class="huField"></span></li>
	<li><span class="huLabel">C: </span><span id="huClose" class="huField"></span></li>
	<li><span class="huLabel">L: </span><span id="huLow" class="huField"></span></li>
	<li><span class="huLabel">D: </span><span id="huDate" class="huField"></span></li>
</ul>

The HUD data is updated through an injection API to the headsUpHR function which renders the cross hairs. Sample code for this injection is outlined further down in this tutorial.

All of the available information for the particular crossHair tick is in placed in an object called prices. All you have do to is update the corresponding innerHTML of the placeholder you placed on your HTML page:

HUD

It is a good idea to clear up all the fields before you reset them, in case one of the fields is not available (if you have panned into the future, for example). This way you never display wrong data.

Here is sample code to illustrate the functionality:

function prependHeadsUpHR() {
	var tick = this.barFromPixel(this.cx);
	var prices = this.chart.xaxis[tick];
	$$("huOpen").innerHTML = "";
	$$("huClose").innerHTML = "";
	$$("huHigh").innerHTML = "";
	$$("huLow").innerHTML = "";
	$$("huDate").innerHTML = "";
	$$("huVolume").innerHTML = "";
	if (prices) {
		if (prices.data) {
			$$("huOpen").innerHTML = this.formatPrice(prices.data.Open);
			$$("huClose").innerHTML = this.formatPrice(prices.data.Close);
			$$("huHigh").innerHTML = this.formatPrice(prices.data.High);
			$$("huLow").innerHTML = this.formatPrice(prices.data.Low);
			$$("huVolume").innerHTML = CIQ.condenseInt(prices.data.Volume);
			if (!this.chart.xAxis.noDraw) {
				var tickDate = prices.data.displayDate;
				if (!tickDate) tickDate = prices.data.DT;
				if (this.chart.xAxis.formatter) {
					$$("huDate").innerHTML = this.chart.xAxis.formatter(tickDate);
				} else if (this.internationalizer) {
					var str = this.internationalizer.monthDay.format(tickDate);
					if (!CIQ.ChartEngine.isDailyInterval(this.layout.interval))
						str += " " + this.internationalizer.hourMinute.format(tickDate);
					else {
						str = this.internationalizer.yearMonthDay.format(tickDate);
					}
					$$("huDate").innerHTML = str;
				} else if (CIQ.ChartEngine.isDailyInterval(this.layout.interval)) {
					$$("huDate").innerHTML = CIQ.mmddyyyy(CIQ.yyyymmddhhmm(tickDate));
				} else {
					$$("huDate").innerHTML = CIQ.mmddhhmm(CIQ.yyyymmddhhmm(tickDate));
				}
			}
		}
	}
}

CIQ.ChartEngine.prototype.prepend("headsUpHR", prependHeadsUpHR);

If, for example, you wanted to add the MACD data to the HUD, pick the fields you want out of the prices object and add them to the code shown above.

Namely:

  • Signal macd (12,26,9)
  • MACD macd (12,26,9)
  • MACD1 macd (12,26,9)
  • MACD2 macd (12,26,9)
  • macd (12,26,9)_hist -- this is the data point for the histogram displayed on the study.

This is what the entire price object looks like when you have the MACD study enabled:

HUD sample

Note: The study names change depending on the settings you have selected. Different settings will cause different study names. This one includes (12,26,9), because it was set with a Fast MA Period of 12, Slow MA Period of 26 and Signal Period of 9. See the study tutorial for more details ( Custom Studies) . So your code needs to be smart enough to find the right MACD in the data set.

Anything displayed on the chart will have a corresponding variable on the prices object. You will need to create an HTML container for it to show up and set the value.


Example1:

Adding close price for comparison symbols on heads up display

Again here is an injection to "headsUp" which will display the data. The chart will run this in all circumstances where a heads up display ought to be updated:

// Update the heads up display
function prependHeadsUpHR() {
	var tick = Math.floor((CIQ.ChartEngine.crosshairX - this.chart.left) / this.layout.candleWidth);
	var prices = this.chart.xaxis[tick];

	// We first set the divs to blank. If a user is hovering over the "future" section of the chart then there won't be any prices
	$$$("#huOpen").innerHTML = "";
	$$$("#huClose").innerHTML = "";
	$$$("#huHigh").innerHTML = "";
	$$$("#huLow").innerHTML = "";
	$$$("#huVolume").innerHTML = "";
	if (prices != null) {
		if (prices.data) {
			$$$("#huOpen").innerHTML = this.formatPrice(prices.data.Open);
			$$$("#huClose").innerHTML = this.formatPrice(prices.data.Close);
			$$$("#huHigh").innerHTML = this.formatPrice(prices.data.High);
			$$$("#huLow").innerHTML = this.formatPrice(prices.data.Low);
			$$$("#huVolume").innerHTML = CIQ.condenseInt(prices.data.Volume);
			/*** We'll insert comparison logic here ***/
		}
	}
}

CIQ.ChartEngine.prototype.prepend("headsUpHR", prependHeadsUpHR);

Now let's add code to dynamically add the values of comparison symbols.

stxx.chart.series contains an array of all comparison symbols. Each series object will have a field called 'display'. For example, display: "IBM".

stxx.chart.dataSegment objects contain the prices for all comparison symbols. So we use the stxx.chart.series array to get the list of symbols, and then use the dataSegment array to get the closing values for each.

The stxx.chart.dataSegment array elements may look something like this (commented are two symbols that would be part of a comparison):

{
	"Close": 130.12,
	"Date": "2012-03-07",
	"High": 130.33096912079003,
	"IBM": 197.77, // part of comparison
	"INTC": 76.38, // part of comparison
	"Low": 129.39119758272534,
	"Open": 129.51586115410126,
	"Volume": 143692200,
	"atr": 1.1490468537796275
}

It may also look like this if you are sending in full OHLC objects for comparisons:

{
	"Close": 130.12,
	"Date": "2012-03-07",
	"High": 130.33096912079003,
	"IBM": {
		// part of comparison
		"DT": "2012-03-07T00:00:00.000Z",
		"Open": 197.98,
		"High": 197.76,
		"Low": 197.98,
		"Close": 197.77,
		"Volume": 1
	},
	"INTC": {
		// part of comparison
		"DT": "2012-03-07T00:00:00.000Z",
		"Open": 75.98,
		"High": 76.76,
		"Low": 75.98,
		"Close": 76.38,
		"Volume": 1509
	},
	"Low": 129.39119758272534,
	"Open": 129.51586115410126,
	"Volume": 143692200,
	"atr": 1.1490468537796275
}

Here is the logic for getting comparison values:

/*** Inserted comparison logic ***/
for (var symbol in this.chart.series) {
	for (var field in prices.data) {
		if (field == symbol) {
			var price = prices[field]; // !! if price is an object, make sure to further iterate to find the field you want to show !!
			var display = this.chart.series[symbol].display;
			/*** Use logic to update your heads up display! ***/
		}
	}
}

##Example 2:

Display data for the study being hovered

This injection will allow you to display on your UI the data for the study being hovered. Simply update or build your UI with the values from outputMap[field] (name of the field) and prices.data[field] (value for the field).

Note that most studies have more than one value available to display; so you may need to allow the UI to dynamically build the display to show all required values.

function prependHeadsUpHR2() {
	//var tick=Math.floor((CIQ.ChartEngine.crosshairX-this.left-this.micropixels)/this.layout.candleWidth);
	var tick = this.barFromPixel(this.cx);
	var prices = this.chart.xaxis[tick];
	if (prices) {
		if (prices.data) {
			if (stxx.currentPanel && stxx.layout.studies[stxx.currentPanel.name]) {
				var outputMap = stxx.layout.studies[stxx.currentPanel.name].outputMap;

				// now we loop through the available values and display them as needed.
				for (field in outputMap) {
					// add your code here to display on your UI the data for the study being hovered
					console.log(outputMap[field], prices.data[field]);
				}
			}
		}
	}
}

CIQ.ChartEngine.prototype.prepend("headsUpHR", prependHeadsUpHR2);

Next Steps: