Getting started
Chart interface
Web components
Chart internals
Data integration
Frameworks and bundlers
Mobile development
Time Span Events
Term structures

Customization Rules

Developers should NEVER modify library files except the provided HTML sample templates and images. Instead, to modify default functionality you should create separate files that overwrite the default settings, functions and CSS classes. Your can see this being done on the provided sample templates.

These files should then be loaded AFTER the required library files have been loaded so your adjustments take precedence over the default code.

This will allow for straight forward library upgrades without needing to merge any of your changes back into the new library files. Simply replace the files with the new package and your overwrites will continue to supersede the default functionality. Just keep in mind that as the library changes, you may need to also slightly modify your overwrites as indicated by the release notes.

Customization Basics

The color and style of most chart elements is managed by CSS. See CSS Used by the Chart for more information.

Menus and dialogs (the chart "UI") are completely under your control. You can modify the HTML and CSS styling as much as is desired simply by editing the templates that are provided in the Library.

Customizing Studies

The Study Library is used to initialize all rendering. This is where you would override colors or even the entire rendering function (see CIQ.Studies.studyLibrary).

The output section defines the colors and other artifacts for the rendering of the study.

The Using and Customizing Studies tutorial has more detail on how to define and work with studies.

Here are some examples:

"W MFI": {
    seriesFN: function(stx, sd, quotes) {
        return CIQ.Studies.displayMFI(stx, sd, quotes);
    }, // change rendering function here
    calculateFN: function(stx, sd) {
        return CIQ.Studies.calculateMFI(stx, sd);
    inputs: {},
    outputs: { Green: "#8bc176", Fade: "#ab611f", Fake: "#5f7cb8", Squat: "#ffd0cf" } // change colors here
"ATR Bands": {
    overlay: true,
    seriesFN: function(stx, sd, quotes) {
        return CIQ.Studies.displayChannel(stx, sd, quotes);
    }, // change rendering function here
    calculateFN: function(stx, sd) {
        return CIQ.Studies.calculateATRBands(stx, sd);
    inputs: { Period: 5, Shift: 3, Field: "field", "Channel Fill": true },
    outputs: { "ATR Bands Top": "auto", "ATR Bands Bottom": "auto", "ATR Bands Channel": "auto" } // change colors here

More details can be found in the Study Tutorial

Watermarking / Branding the Chart

You can add a watermark or branding to the chart several ways:

  1. Create a CSS-styled div element in your chart container element to overlay semi-transparent text on the chart. Then have the callback function of CIQ.ChartEngine#loadChart change the innerHTML content of the div element to the watermark/branding text as the new chart is rendered.

    Note: Be sure to locate the div element within the chart container element if you want the div element to be included in your chart share.

  2. Add a background image to the chart container element using CSS, for example:

    .ciq-night .chartContainer {
        background-image: url(img/nameHere.svg);
    .chartContainer {
        background-image: url(img/nameHere.svg);
  3. Use the library watermark function, CIQ.ChartEngine#watermark.

    The watermark must be redrawn on every frame of the animation loop or the watermark disappears. You can implement this with an API injection, for example:

    CIQ.ChartEngine.prototype.prepend("draw", function() {
        // Set the color and font.
        stxx.setStyle("stx_watermark", "font-size", "100px");
        stxx.setStyle("stx_watermark", "color", "red");
        stxx.watermark("chart", {
            h: "center",
            v: "middle",
            text: stxx.chart.symbol
        // Restore the color and font.
        stxx.setStyle("stx_watermark", "font-size", "16px");
        stxx.setStyle("stx_watermark", "color", "rgba(0,0,0,0.5)");

    Note: The CSS style stx_watermark is the same for all watermarks, including chart error messages (used mainly on study panels). So be sure to restore the style settings to their default values (as shown in the example) after you've created your watermark.

Customizing Chart Behavior

If you are looking to change default behavior of the chart, rather than look and feel, you can find all configurable settings for the main chart object and associated x and y axis rendering in the following classes:

Feel free to override them as needed to permanently change the defaults, programmatically change on the fly within your code, or send them in as arguments when constructing a new chart for a more dynamic approach.

When sending in a 'config' argument, any field or object within the config will be added to the CIQ.ChartEngine object itself or override defaults.

If you wanted to create a new candle chart with crosshairs enabled on initial load, you can do something like this:

var stxx = new CIQ.ChartEngine({
	container: document.getElementById("chartContainerSilver"),
	layout: { crosshair: true, chartType: "candle" }

This overrides stxx.layout.crosshair with a value of true and stxx.layout.chartType with a value of "candle".

Or if you wanted to change the shape of the y axis price labels, you can choose from the following: "roundRectArrow", "semiRoundRect", "roundRect","tickedRect","rect","noop" as follows:

var stxx = new CIQ.ChartEngine({
	container: document.querySelector(".chartContainer"),
	yaxisLabelStyle: "rect",
	layout: { candleWidth: 16, crosshair: true }

Or you can use the following syntax if you want to change it dynamically after the chart object has been created:

var stxx = new CIQ.ChartEngine({ container: document.querySelector(".chartContainer") });
// do other things here...
stxx.yaxisLabelStyle = "roundRectArrow";

For additional axis manipulations see Custom X-Axis and Gridlines and axis labels.

Popular UI customizations

Disabling Zooming and Panning

Right after your new CIQ.ChartEngine() declaration put the following lines:

stxx.allowZoom = false;
stxx.allowScroll = false;

See CIQ.ChartEngine#allowZoom and CIQ.ChartEngine#allowScroll for more details.

You may also want to remove the zoom-in and zoom-out buttons by using the following code:

stxx.controls.chartControls.style.display = "none";
stxx.controls.chartControls = null;

If all you want to do is to remove the touch and mouse zooming and panning but allow the zoom buttons to work, use the API injections outlined in the 'Disabling/enabling touch and mouse events' on the Sample API Injections tutorial.

Tip: You may override controls like "zoom", "home" and "more" if you wish to provide your own navigational components. Place your own divs with the same id tags into the chart div container. The chart will use those instead of making its own. Or, simply modify the css to change the look of the existing components. Finally, to hide any of these objects, set the corresponding entry to null in the stx object before creating a chart. The complete list of these objects is outlined in CIQ.ChartEngine#htmlControls.

Decimal place precision

By default, the chart will automatically set display precision of price labels based on the price range of the data being displayed, by using the matrix set in CIQ.ChartEngine.YAxis#shadowBreaks. This can be overridden, however, by settingCIQ.ChartEngine.YAxis#decimalPlaces. If you wish to further configure the current price label floating over the y axis to display less decimal places than the axis labels, set CIQ.ChartEngine.YAxis#maxDecimalPlaces. Also see CIQ.ChartEngine.Chart#dynamicYAxis to allow the y axis to automatically determine its width based on the text length of quotes in a dataSet.

Overriding default y-axis rendering

The y-axis rendering can take in a function to override the default formatting. This function will be called before rendering each tag on the y-axis.

For example, you may want to display prices in fractions instead of decimals. You would set it up as flows in the loadChart callback:

stxx.chart.panel.yAxis.priceFormatter = function(stx, panel, price) {
	var convertedPrice;
	// add our logic here to convert 'price' to 'convertedPrice'
	return convertedPrice;

to remove it you would do this:

stxx.chart.panel.yAxis.priceFormatter = null;

Advanced customization -- API injections

Many modules can be overwritten with an API injection if necessary (append/prepend). We can assist you in creating the necessary code injections if you find there are things you want to change beyond what is made available through the configurable settings.

The charting engine is essentially an animation engine. When a user scrolls or pans a chart, it is redrawn at animation speeds, providing the appearance of a smoothly moving chart in much the same way that a video game does. CIQ.ChartEngine#draw is the rendering function that is called to animate the chart and therefore the most common method for extending chart functionality is to extend the draw() function itself. This can be done easily with the Injection API (see below for more details on the Injection API).

There are two ways to visually extend the draw() function:

  1. By drawing on the canvas
  2. By displaying HTML components

For instance, as a developer you may wish to display an arrow somewhere on the screen. This could be accomplished either by physically drawing an arrow using the canvas, or by creating an HTML arrow object and superimposing it on the canvas. The choice of which technique to use depends on your "use case". Drawing on the canvas takes more programming effort, but if you are sharing charts then you must use this approach because HTML elements will not render on a shared chart image. However, complex interactive graphics are easier to create as plain HTML and so might be the better approach for complex interfaces. For example, Trade From Chart is primarily implemented using HTML elements that are superimposed on the chart.

Your first step to customization is to append your own code to the end of the draw() function. You can do this with the following statement:

CIQ.ChartEngine.prototype.append("draw", function() {
	// my custom code here

This code will now get called whenever the chart is redrawn (possibly hundreds of times per second if the user is scrolling the chart).

You can do anything you want in this code, such as custom drawing. Logically, placing customized drawings or objects on the chart requires finding the appropriate positioning along the x and y axis in pixels. The charting engine however provides functions that allow you to determine the physical X and Y coordinates given dates and prices using functions such as CIQ.ChartEngine#pixelFromPrice and CIQ.ChartEngine#pixelFromDate.

The charting display is subdivided into panels. Each study is drawn in a panel. The chart itself is also a panel. Each panel has its own y-axis. The stx.panels object contains all of the panels on the chart. Drawing on the chart panel is the simplest and most common task. You can get the chart panel easily:

CIQ.ChartEngine.prototype.append("draw", function() {
	var panel = this.chart.panel; // "this" is your stxx object

// Once you have access to a panel you can determine the X and Y coordinates on the canvas given a price and date (or dateTime):

CIQ.ChartEngine.prototype.append("draw", function() {
	var panel = this.chart.panel;
	var dt = yyyymmddhhss(myDate);
	var x = this.pixelFromDate(dt, panel.chart);
	var y = this.pixelFromPrice(myPrice, panel);

Note that pixelFromPrice() can take a value rather than a price if you are dealing with a study panel (for instance a stochastics panel would require a value between 1 and 100)

Now you might want to draw using HTML5 canvas commands:

CIQ.ChartEngine.prototype.append("draw", function() {
	var panel = this.chart.panel;
	var dt = yyyymmddhhss(myDate);
	var x = this.pixelFromDate(dt, panel.chart);
	var y = this.pixelFromPrice(myPrice, panel);

	this.chart.context.fillRect(x, y, x + 10, y + 10);

Placement of HTML objects depends on how they are created. If objects are added to the chart container then positioning is quite simple:

// in your html page

var myHTMLObject = document.createElement("DIV");
myHTMLObject.style.position = "absolute";

CIQ.ChartEngine.prototype.append("draw", function() {
	var panel = this.chart.panel;
	var dt = yyyymmddhhss(myDate);
	var x = this.pixelFromDate(dt, panel.chart);
	var y = this.pixelFromPrice(myPrice, panel);

	myHTMLObject.style.left = x + "px";
	myHTMLObject.style.top = y + "px";

If objects are absolutely positioned at the document level you can use CIQ.ChartEngine#resolveX and CIQ.ChartEngine#resolveY to convert to absolute screen coordinates

// in your html page

var myHTMLObject = document.createElement("DIV");

myHTMLObject.style.position = "absolute";

CIQ.ChartEngine.prototype.append("draw", function() {
	var panel = this.chart.panel;
	var dt = yyyymmddhhss(myDate);
	var x = this.pixelFromDate(dt, panel.chart);
	var y = this.pixelFromPrice(myPrice, panel);

	myHTMLObject.style.left = this.resolveX(x) + "px";
	myHTMLObject.style.top = this.resolveY(y) + "px";

Management of HTML objects is up to you as the developer so you'll need to build logic into your draw() extension to determine when to display or not display the objects.

You can use panel.top, panel.bottom, chart.left and chart.right to determine the boundaries of a panel.

It is also possible to work with "bars". A bar is a candle location on the screen. The number of ticks displayed on the screen is chart.maxTicks.

For instance if you wanted to draw a line between bars 5 and 10 on the screen:

CIQ.ChartEngine.prototype.append("draw", function() {
	var panel = this.chart.panel;
	var x0 = this.pixelFromBar(5);
	var x1 = this.pixelFromBar(10);

	// draw line between x0 and x1

Note: If using transformations (such comparison charts that transform a price to a percentage) then pixelFromPrice() will return a Y value based on the transformation. For instance, to get the Y location of a closing price in a comparison chart you would use pixelFromPrice(someBar.Close). Whereas if you wanted to get the pixel for the Y axis location of 10% you would use pixelFromTransformedValue(10). If no transformation is in effect then the two functions are equivalent.

More details can be found in the Injection API Tutorial

Where do I put my injection code?

It is recommended to put the API injections on the main HTML file you have customized to render the chart or a separate js file. Never in any of the library files. In this way, when a new release is available, you won't have to worry about merging you customized code into the core library files.

Anywhere within the tags will work.

Here is an example of what your code may look like:

<!DOCTYPE html>
	<head> </head>
	<body onLoad="displayChart()">
			// API injection
			CIQ.ChartEngine.prototype.prepend("someFunction", function() {
				// injection code here;

			// Declare a CIQ.ChartEngine object. This is the main object for drawing charts
			var stxx = new CIQ.ChartEngine({
				container: document.querySelector(".chartContainer"),
				layout: { candleWidth: 16, crosshair: true }

			// more js here

Can I disable the inertia (animated) scroll and zoom effects ?

By default, the chart will use a rolling effect to continue to scroll or zoom the cart as you swipe or pinch it; depending on your gesture velocity. The faster you gesture, the more it will continue to 'roll' and incrementally slow down until it comes to a full stop. If you want to disable this rolling effect, add this to your project right after you call new CIQ.ChartEngine():

// stops zooming animation
stxx.animations.zoom = new CIQ.EaseMachine(Math["easeOutCubic"], 1);
// stops scrolling animation
stxx.swipeRelease = function() {};

Next steps