Search code examples
chartscandlestick-chartplottable

How to create candlestick chart in plottable.js


What is the best way to create candlestick chart in plottable? I would like to do something like this image on wiki: Wiki example

I was thinking about using stacked bar plot and styling it with css. For example lowermost value in bar would be transparent, just to position candlestick vertically. Next value in a bar would be lower stick(rectangle horizontally squeezed with css to become line). Next would be the body which is already rectangle and upper stick would again be rectangle squeezed to line.

Is this proper way to go or are there any more elegant solutions? Are there any examples out there? Has anyone done something like this before?


Solution

  • Glad you asked! The best way to do this in Plottable is to combine Plots.Rectangle and Plots.Segment using a Group. Here's an example:

    window.onload = function() {
      var xScale = new Plottable.Scales.Time();
      var yScale = new Plottable.Scales.Linear();
      
      var dataset = new Plottable.Dataset(exampleData);
      
      var wicks = new Plottable.Plots.Segment();
      wicks.addDataset(dataset);
      wicks.x(function(d) { return parseDate(d.date, 12); }, xScale);
      wicks.y(function(d) { return d.high; }, yScale);
      wicks.y2(function(d) { return d.low; });
      wicks.attr("stroke", "black");
      
      var candles = new Plottable.Plots.Rectangle();
      candles.addDataset(dataset);
      candles.x(function(d) { return parseDate(d.date, 2); }, xScale);
      candles.x2(function(d) { return parseDate(d.date, 22); });
      candles.y(function(d) { return d.open; }, yScale);
      candles.y2(function(d) { return d.close; });
      candles.attr("fill", function(d) {
        if (d.close > d.open) {
          return "#63c261";
        } else {
          return "#fd373e";
        }
      });
      
      var candlesticks = new Plottable.Components.Group([wicks, candles]);
      
      candlesticks.renderTo("#chart");
    };
    
    function parseDate(dateString, hourOfDay) {
      var day = new Date(dateString);
      day.setHours(hourOfDay);
      return day;
    }
    
    var exampleData = [
      {
        date: "2014-08-29",
        open: 102.86,
        high: 102.90,
        low: 102.20,
        close: 102.50
      },
      {
        date: "2014-08-28",
        open: 101.59,
        high: 102.78,
        low: 101.56,
        close: 102.25
      },
      {
        date: "2014-08-27",
        open: 101.02,
        high: 102.57,
        low: 100.70,
        close: 102.13
      },
    ];
    body { background-color: #AAA; }
    svg { background-color: #FFF; }
        <html>
          <head>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.16.2/plottable.js"></script>
            <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.16.2/plottable.css">
          </head>
          <body>
            <svg id="chart" width="400" height="300"></svg>
          </body>
        </html>

    Plots.Segment draws line segments, so setting the ends of each segment to the high/low on each day gets the "wicks" for each candlestick. Meanwhile, Plots.Rectangle draws rectangles, so we set the top/bottom of each rectangle to the open/close on each day. Overlaying the two Plots gets us a candlestick chart.

    Hope this helps!