Managing Chart Zoom and Range

The charting "zoom" can be controlled in a number of ways:

  • Set the width of a candle using STXChart#setCandleWidth -the chart will automatically figure out how many candles to display.
  • Set the number of candles to display using STXChart#setMaxTicks -the chart will automatically figure out the candle width.
  • Set a time range to display using STXChart#setSpan or STXChart#setRange -the chart will figure out the number of candles and then the candle width.

Concepts

The amount of data that is displayed on the screen is driven by two factors:

  • The width of the chart (stxx.chart.width)
  • The width of a bar or candle (stxx.layout.candleWidth)

The width of the chart is computed automatically: the width of the "chart container" minus the width of the y-axis. The candleWidth is a dynamic variable that changes based on when the user zooms in or out. A chart can be zoomed programatically simply by changing the candleWidth.

Example: Zoom in by 10%

stxx.setCandleWidth(stxx.layout.candleWidth*1.1);
stxx.draw();

stxx.chart.maxTicks is always set to the maximum number of bars/candles that will be displayed on the chart, that is, the width of the chart in candles (note that since a user may zoom past the edge of the chart, maxTicks may not equal the actual number of candles on the screen).

Example: Display 100 candles on screen

stxx.setMaxTicks(100);
stxx.home(); // position the chart with "today" on the far right side
stxx.draw();

Practical applications

Imagine for a moment that you have very little data for a particular symbol. And at the current zoom level, it will not fill the canvas. If you wanted to stretch the chart so no white space shows on the left, for example, you would want to set the width of the candles (zoom level) so the number of candles that display on the chart match the ticks you have.

Here is sample code that would accomplish this:

if ( myData.length < stxx.chart.maxTicks )                 // First, check to see if you have enough data. (This could be stxx.chart.dataSet if already loaded)
    stxx.setMaxTicks(stxx.chart.dataSet.length);        // If you don't, stretch the candles to fit the entire screen.
// After the number of ticks are set, you can call newChart() to display your new data, or draw() if you already have the data loaded. 

Here is another scenario where you may want to manipulate the number of candles to display. By default, the chart tries to maintain the number of visible candles constant as you change periodicity. As such, if you change from a 30 minute interval to a 1 minute interval, for example, the chart will get compressed to display a time span 30 times smaller. If your preferred behavior is to instead maintain the time span constant and have the the number of candles change so no new data is required to be fetched, you can preset the candle size relative to the periodicity using STXChart.setMaxTicks

Here is an example showing how to modify the changePeriodicity function provided in the sample templates by manipulating the maxTicks:

function changePeriodicity(newPeriod, newInterval){
    STXLoader(true);
    if( newInterval== 1 )stxx.setMaxTicks(600); // if the interval is 1 minute show 600 candles
    if( newInterval== 5 )stxx.setMaxTicks(120); // if the interval is 5 minutes show 120 candles
    if( newInterval== 30 )stxx.setMaxTicks(20);    // if the interval is 30 minutes show 20 candles
    stxx.setPeriodicityV2(1, newInterval, function(err){
    showAttribution();
    STXLoader(false);
    if(!err){
      $$$("#periodBtn").childNodes[0].data=stxx.translateIf(intervalDisplayMap[newInterval]);
    }
  });
}

Here is a different approach using setRange:

    Be careful when changing to an introday period from a daily, monthly or weekly period! 
    The range of data may cover several days, weeks or months which, in minute periodicity, can put a strain on the quote feed.
    Similarly maintaining the range when changing from introday to daily, weekly or monthly may cause the chart to display just a few ticks.
    So you may want to add logic to override the ranges as needed.

function changePeriodicity(newPeriod, newInterval){
    STXLoader(true);
// Get the current range for the chart BEFORE periodicty is set to keep it constant after change of interval var startpt = stxx.chart.dataSegment[0] var endpt = stxx.chart.dataSegment[stxx.chart.dataSegment.length - 1]; stxx.setRange( { dtLeft: startpt.DT, // Set this to the date to appear on the left edge of chart dtRight: endpt.DT, // Set this to the date to appear on the right edge of chart periodicity: { period: newPeriod, interval: newInterval } }, function(err){ showAttribution(); STXLoader(false); if(!err){ $$$("#periodBtn").childNodes[0].data=stxx.translateIf(intervalDisplayMap[newInterval]); } }); }

Setting Default Zoom using time Spans and Ranges

Convenience functions have been provided to set specific date ranges.

setSpan() can be used to set the chart to a specific span of time, for instance a one year chart or a one month chart.

setSpan() will automatically select a periodicity for optimal chart display unless the maintainPeriodicity parameter is present and set to true.

Example:

// Display a one year chart with 30 pixels of padding
stxx.setSpan ({
        multiplier: 1,
        span: "year",
        padding: 30
    });

Note that is important that you have enough data to display the desired span. It wouldn't make sense to display a one year chart if the data is minute bars.

setRange() can set the chart to a specific date range.

stxx.setRange({
   dtLeft: ,        // Set this to the date to appear on the left edge of chart
   dtRight: ,        // Set this to the date to appear on the right edge of chart
   padding:         // Set this to the number of pixels of padding to leave between the chart and y-axis
});

Example:

setRange() will automatically select a periodicity for optimal chart display unless the params.periodicity object is present.

The best practice for setting defaults on the chart is to do so with the stxx.newChart() parameter object or in the callback.

Parameter example:

stxx.newChart(newSymbol, null, null, callback(),{span:{base:'day',multiplier:1}});

Callback example:

function displayChart(){                          // Called for instance from body.onload
  stxx.setPeriodicityV2(1, "day");              // Initialize the periodicity
  stxx.newChart(symbol, null, null, function(){
    stxx.setSpan ({
        multiplier: 1,
        span: "year",
        padding: 30
    });
}); }



The following is an example of how to set a menu drop down to allow the user to select different time spans.

setSpan

In the HTML section you would add the drop down ( next to the periodicity drop down is a good place):

<!--  existing periodicity drop down -->
<div id="periodBtn" class="stx-btn stx-menu-btn stxMenu">1D<em></em>
  <ul id="periodicity" class="periodicity menuSelect menuOutline" style="display:none">
    <li stxToggle="changePeriodicity('day')">1 D</li>
    <li stxToggle="changePeriodicity('week')">1 W</li>
    <li stxToggle="changePeriodicity('month')">1 Mo</li>
    <li class="stx-menu-divider"></li>
    <li stxToggle="changePeriodicity(1)">1 Min</li>
    <li stxToggle="changePeriodicity(5)">5 Min</li>
    <li stxToggle="changePeriodicity(30)">30 Min</li>
  </ul>
</div>

<!-- new range drop down -->
<div id="rangeBtn" class="stx-btn stx-menu-btn stxMenu">1 Month<em></em>
  <ul id="range" class="range menuSelect menuOutline" style="display:none">
    <li stxToggle="changeRange(1,'month','1 Month')">1 Month</li>
    <li stxToggle="changeRange(3,'month','3 Month')">3 Months</li>
    <li stxToggle="changeRange(1,'year','1 Year')">1 Year</li>
    <li stxToggle="changeRange(5,'year','5 Years')">5 Years</li>
  </ul>
</div>

Then you would define the changeRange() function as follows:

function changeRange(newMult,newSpan, text){
    stxx.setSpan ({
       multiplier: newMult,
       span:newSpan,
       padding: 30
    });
    $$$("#rangeBtn").replaceChild(STX.translatableTextNode(stxx,text),$$$("#rangeBtn").childNodes[0]);
}

// note that the periodicity dropdown resets the range to 'Select Range'. // This is due to the fact that when a new periodicity is activated on the chart, // the range is not maintained unless you call setRange again with the new periodcity. // By default the candle size (zoom level) is what persists rather then the range. function changePeriodicity(newPeriod, newInterval){ STXLoader(true); stxx.setPeriodicityV2(newPeriod, newInterval, function(err){ STXLoader(false); if(!err){ $$$("#periodBtn").replaceChild(STX.translatableTextNode(stxx,intervalDisplayMap[newInterval]),$$$("#periodBtn").childNodes[0]); $$$("#rangeBtn").replaceChild(STX.translatableTextNode(stxx,'Select Range'),$$$("#rangeBtn").childNodes[0]); } }); }

Last, don't forget to set your initial span to match the default menu value:

  stxx.newChart(symbol, null, null, function(){
     stxx.setSpan(1, "month", 30);                  // callback function when chart is created
  });

Note: The chart will remember the zoom level even if you change periodicity. SetRange or SetSpan can be used to override this default behavior.

Whitespace

The initial amount of whitespace to display between the right edge of the chart and the y-axis is controlled by the stxx.preferences.whitespace variable. Set this to zero in order to get a chart that is flush against the y-axis.

The default value for the desktop layout is 30.

The following code snippet illustrates how to override the default:

var stxx=new STXChart($$("chartContainer"));
stxx.preferences.whitespace=0;

Please note that this value is used for initial rendering, but will be automatically adjusted as needed when the chart zooms in and out. It is important to mention that if your candleWidth does not evenly divide into the chart.width, the remainder will be additional whitespace on the right margin of the chart. This can become very apparent if candleWidth is set to a very large size