Edit in JSFiddle

// Create your QuoteFeed object.
var myQuoteFeed = {};

myQuoteFeed.url = "https://jsfiddle.chartiq.com/sample_json.js";


// This is where the action is. params will tell you what the chart needs (symbol, interval, date ranges)
// Use that data to construct your query. Use our ajax, or jquery, or any other method to fetch the data
// Make sure it's in the right format and return it in the callback like below.  
// Always use cb() to return data from fetch methods!  Even errors. 

// This method is called by the chart to fetch initial data
myQuoteFeed.fetchInitialData = function(symbol, startDate, endDate, params, cb) {
  // this alert and console log are here to help you see what the fetch calls are doing.
  //alert('Open the console to see what is happening....');
  console.log("Asking for initial data...");

  var query = this.url +
    "?symbol=" + symbol +
    "&interval=" + params.interval +
    "&startDate=" + CIQ.yyyymmddhhmm(startDate) +
    "&endDate=" + CIQ.yyyymmddhhmm(endDate);

  CIQ.postAjax(query, null, function(status, response) {
    if (status == 200) {
      cb({
        quotes: JSON.parse(response),
        moreAvailable: true
      });
    } else {
      cb({
        error: (response ? response : status)
      });
    }
  });

  // This sample assumes the response returns only the data and in the right format.
  // Put your code here to format the response according to the specs 
  // and return it in the callback.
  // Example code to iterate trough the responses and load them one at a time:
  //	var quotes=formatQuotes(response);  // your function to creates a properly formatted array.
  //	var newQuotes=[];
  //	for(var i=0;i<quotes.length;i++){
  //		newQuotes[i]={};
  //		newQuotes[i].Date=quotes[i][0]; // Or set newQuotes[i].DT if you have a JS Date
  //		newQuotes[i].Open=quotes[i][1];
  //		newQuotes[i].High=quotes[i][2];
  //		newQuotes[i].Low=quotes[i][3];
  //		newQuotes[i].Close=quotes[i][4];
  //		newQuotes[i].Volume=quotes[i][5];
  //		newQuotes[i].Adj_Close=quotes[i][6];
  //	}

  // Set 'moreAvailable' to 'true' if you know that more, older, 
  // data is available for when the user scrolls back in time.
  // Your feed should send back an indicator you can use to determine if more data is available.
  // Our sample does not have more data, so we set to 'false'.
};

myQuoteFeed.fetchUpdateData = function(symbol, startDate, params, cb) {

  // open your javascript console on your browser to see when the engine calls for a refresh!
  console.log("Chart called for a refresh");

  var query = this.url +
    "?symbol=" + symbol +
    "&interval=" + params.interval +
    "&startDate=" + startDate;
  // We are just returning a single element as an example,
  // but here is a sample of what an Ajax call would look like:  
  // CIQ.postAjax(query, null, function(status, response){
  //	if(status!==200){
  //  		cb({error:status}); // something went wrong, use callback function to return your error
  //  		return;
  //	}
  // Put your code here to format the response according
  // to the specs and return it in the call back.
  // cb({quotes: yourData});  // no need to set moreAvailable for a refresh;
  // Make sure the data returned is for the startDate requested, or newer.
  cb({
    quotes: [{
      "Date": "20150101",
      "Open": 139,
      "High": 140,
      "Low": 138,
      "Close": 139 + Math.random(),
      "Volume": 1000
    }]
  })
  return;
}

myQuoteFeed.fetchPaginationData = function(symbol, startDate, endDate, params, cb) {
  console.log("more data requested");

  // The chart gives you a hint in params.ticks and the start and end dates, 
  // so you can send back enough data to fill the chart.
  // This should be the *minimum* to load. We recommend loading twice this much so that the chart
  // can be scrolled and so that studies have enough back data to compile.

  var query = this.url +
    "&endDate=" + CIQ.yyyymmddhhmm(params.endDate) +
    "&records=" + (params.ticks * 2); // suggested number of data points to fetch.

  // Your ajax call would go here.  Since we don't have any older data, we're not
  // going to put on here, but it's the same idea as in fetchUpdateData() and 
  // fetchInitialData(). 

  // Always use the call back even if there is not data!!!!!!
  cb({
    quotes: [],
    moreAvailable: false
  });

  return;
}

var behavior = {
  refreshInterval: 5 // myQuoteFeed.fetchUpdateData() will be called 
  //every 5 seconds with startDate set to the last tick on the chart
};


var stxx = new CIQ.ChartEngine({
  container: $$$(".chartContainer")
}); // Declare a CIQ.ChartEngine object. This is the main object for drawing charts.

stxx.attachQuoteFeed(myQuoteFeed, behavior); // Attach your QuoteFeed
stxx.setPeriodicityV2(1, "day");
stxx.layout.crosshair = true;
stxx.loadChart("SPY");
<div class="chartContainer" style="width:100%;height:400px;position:relative;"></div>

<!--[if IE 8]><script>alert("This template is not compatible with IE8");</script><![endif]-->

<script src="https://jsfiddle.chartiq.com/chart/js/chartiq.js"></script>